Tabrakan Dua Lingkaran

Jika sebelumnya saya pernah membahas tentang cara mengecek tabrakan antara dua bujur sangkar atau persegi panjang, sekarang saya akan membahas tentang cara  mengecek tabrakan dua lingkaran.

Pertama, kita akan membuat struct untuk menyimpan informasi tentang lingkaran. Struct tersebut berisi informasi tentang jari-jari, koordinat x dan y dari lingkaran.
struct Lingkaran{
    int x;
    int y;
    int r;
};
Setelah membuat struct-nya, kita akan buat function untuk mengecek tabrakannya. Parameter function tersebut menggunakan pointer struct yang sudah kita buat di atas.
int cekTabrakan(Lingkaran *l1, Lingkaran *l2){
int tabrakan=0;
int jarak, x, y;
    x=l1->x-l2->x;
    y=l1->y-l2->y;
    jarak=sqrt(x*x+y*y);
    if (jarak<(l1->r+l2->r)){
        tabrakan=1;
    }
    return tabrakan;
}
Function untuk mengecek tabrakan tersebut cukup singkat, kan? Kita cuma perlu percabangan if untuk membandingkan jarak pusat lingkaran dengan total dari panjang jari-jari kedua lingkaran. Lingkaran dianggap bertabrakan jika jarak pusat kedua lingkaran kurang dari total ukuran jari-jari kedua lingkaran.

Selanjutnya, kita akan satukan function dengan kode program utamanya. Kita juga akan menggunakan function untuk menggambar lingkaran yang pernah saya tulis sebelum ini. Kode program di bawah ini akan menampilkan dua lingkaran yang akan berubah warna saat bertabrakan dan berpisah.
#include <math.h>
#include <SDL2/SDL.h>
#define playar 640
#define tlayar 480

SDL_Renderer *trender=NULL;
struct Lingkaran{
    int x;
    int y;
    int r;
};

int cekTabrakan(Lingkaran *l1, Lingkaran *l2){
int tabrakan=0;
int jarak, x, y;
    x=l1->x-l2->x;
    y=l1->y-l2->y;
    jarak=sqrt(x*x+y*y);
    if (jarak<(l1->r+l2->r)){
        tabrakan=1;
    }
    return tabrakan;
}

int warnai_lingkaran(SDL_Renderer *trender, int xpos, int ypos, int r){
int tx, ty, i;
    for(i=0;i<r;i++){
        tx=i;
        ty=sqrt(r*r-i*i);
        SDL_RenderDrawLine(trender, xpos+tx, ypos+ty, xpos+tx, ypos-ty);
        SDL_RenderDrawLine(trender, xpos-tx, ypos+ty, xpos-tx, ypos-ty);
    }
    return 0;
}

int gambar_lingkaran(SDL_Renderer *trender, int xpos, int ypos, int r){
int tx1, ty1, tx2, ty2, i;
    for(i=0;i<r;i++){
        tx1=i;
        ty1=sqrt(r*r-tx1*tx1);
 
        tx2=i+1;
        ty2=sqrt(r*r-tx2*tx2);
        SDL_RenderDrawLine(trender, xpos+tx1, ypos+ty1, xpos+tx2, ypos+ty2);
        SDL_RenderDrawLine(trender, xpos-tx1, ypos+ty1, xpos-tx2, ypos+ty2);
        SDL_RenderDrawLine(trender, xpos+tx1, ypos-ty1, xpos+tx2, ypos-ty2);
        SDL_RenderDrawLine(trender, xpos-tx1, ypos-ty1, xpos-tx2, ypos-ty2);
    }
    return 0;
}

int main(int argc, char* args[]){
    SDL_Window* window = NULL;
    SDL_Event evt;
    Lingkaran rct1={200, 100, 75};
    Lingkaran rct2={200, 100, 50};

    if( SDL_Init( SDL_INIT_VIDEO ) < 0){
        printf( "Error: %s\n", SDL_GetError() );
    }else{
        window = SDL_CreateWindow( "SDLku", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, playar, tlayar, SDL_WINDOW_SHOWN );
        if( window == NULL ){
            printf( "Error : %s", SDL_GetError() );
        }else{
            trender = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
            
            while(evt.type!=SDL_QUIT){
                while(SDL_PollEvent(&evt)){
                    if(evt.type==SDL_KEYDOWN){
                        switch(evt.key.keysym.sym){
                            case SDLK_a:
                                rct1.x-=2;
                                break;
                            case SDLK_d:
                                rct1.x+=2;
                                break;
                            case SDLK_s:
                                rct1.y+=2;
                                break;
                            case SDLK_w:
                                rct1.y-=2;
                                break;
                            case SDLK_LEFT:
                                rct2.x-=2;
                                break;
                            case SDLK_RIGHT:
                                rct2.x+=2;
                                break;
                            case SDLK_DOWN:
                                rct2.y+=2;
                                break;
                            case SDLK_UP:
                                rct2.y-=2;
                                break;
                    
                        }
                    }

                    SDL_SetRenderDrawColor(trender, 0xFF, 0xFF, 0xFF, 0xFF);
                    SDL_RenderClear(trender);
            
                    if(cekTabrakan(&rct1, &rct2)!=0)SDL_SetRenderDrawColor(trender, 0x00, 0x00, 0xFF, 0xFF);
                    else SDL_SetRenderDrawColor(trender, 0xFF, 0xFF, 0x00, 0xFF);
                    warnai_lingkaran(trender, rct1.x, rct1.y, rct1.r);
                    SDL_SetRenderDrawColor(trender, 0xFF, 0x00, 0x00, 0xFF);
                    warnai_lingkaran(trender, rct2.x, rct2.y, rct2.r);
                    
                    SDL_RenderPresent(trender);
                }
            }
        }
    }

    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;
}
Coba gunakan tombol w, s, a, d, atau tombol panah untuk menggerakkan salah satu lingkarannya. Saat lingkaran bertabrakan warnanya akan berbeda jika dibandingkan dengan saat lingkaran sudah tidak saling menempel.