Отслеживаем столкновения двух круглых областей в SDL

Эта статья наврядли научит вас правильно отслеживать столкновения, ведь спрайты редко бывают идеально круглыми..
.. но сейчас представим что в мире всё иначе и спрайты действительно только в форме круга.

Не буду описывать стандартные для sdl функции. Можете поискать информацию о них на єтом сайте

Для отслеживания столкновения нужно ещё и считать:

#include <SDL/SDL.h>

#include <cmath>

Зададим размер и заголовок константами:

const int WINDOW_WIDTH = 640;

const int WINDOW_HEIGHT = 480;

const char* WINDOW_TITLE = «SDL HOWTO»;

Оприделим функцию для обработки столкновений:

bool box(SDL_Rect one,SDL_Rect two);

В функции main:

int main(int argc, char **argv){

Стандартно для SDL приложения (подробнее в предыдущих статьях):

SDL_Init( SDL_INIT_VIDEO );

    SDL_Surface* screen = SDL_SetVideoMode( WINDOW_WIDTH,

    WINDOW_HEIGHT, 0,

    SDL_HWSURFACE | SDL_DOUBLEBUF );

    SDL_WM_SetCaption( WINDOW_TITLE, 0 );

    SDL_ShowCursor(SDL_DISABLE);

    SDL_Surface* bitmap = SDL_LoadBMP(«sprite.bmp»);

    SDL_SetColorKey( bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(bitmap->format,0, 0, 0) );


SDL_Rect source;

source.x = 0;

source.y = 0;

source.w = 120;

source.h = 120;

Всё также в цикле ожидания действий:

SDL_Event event;

bool run = true;

while(run) {

    while ( SDL_PollEvent(&event) ) {

        switch (event.type) {

            case SDL_MOUSEMOTION:

                    SDL_Rect fill;

                    fill.x = 0;

                    fill.y = 0;

                    fill.w = WINDOW_WIDTH;

                    fill.h = WINDOW_HEIGHT;

                    SDL_FillRect(screen,&fill,SDL_MapRGB(bitmap->format,0, 0, 0) );


                    SDL_Rect destination;

                    destination.x = event.motion.x — 60;

                    destination.y = event.motion.y — 60;

                    destination.w = 120;

                    destination.h = 120;  

После этого начинаются немного новые вещи:

Рисуем круг «враг». Он будет стоять на месте:

SDL_Rect target;

target.x = 100;

target.y = 100;

target.w = 120;

target.h = 120; 

SDL_BlitSurface(bitmap, &source, screen, &target);

Пользуемся нашей функцией для определения столкновения:

if (!box(destination,target)) {

                    SDL_BlitSurface(bitmap, &source, screen, &destination);

                    SDL_Flip(screen);

            }

Дальше опять всё стандартно:

 break;

            case SDL_QUIT:

                run = false;

        }

    }

    }

    SDL_FreeSurface(bitmap);

    SDL_Quit();

    return 0;

}

Старался не пропускать ничего, такчто извените за такие куски кода.

Теперь остановимся на функции box:

bool box(SDL_Rect one,SDL_Rect two) {

    int oneX,oneY,twoX,twoY;

    oneX = one.x + one.w/2;

    oneY = one.y + one.h/2;

   

    twoX = two.x + two.w/2;

    twoY = two.y + two.w/2;

   

    int width1 = one.w/2;

    int width2 = two.w/2;

    int rad = width1 + width2; //сумма радиусов

    int rad2 = sqrt(pow((oneX — twoX),2)+(pow((oneY — twoY),2)));  //расстояние между центрами

    if (rad > rad2)

        return true;

    else

        return false;

        printf(«%d :: %dn»,rad,rad2    );

}

Её суть в том, что объекты (круги) сталкиваются если расстояние между их центрами (красный) меньше суммы их радиусов (синий/чёрный).

Будем считать, что радиус спрайта равен половине его ширины (width1 и width2), а центр находится путём добавления половины ширины спрайта к его Х координате и высоты к Y.
После нахождения координат центров находим расстояние между ними по школьной формулe:

В случае если объекты пересекаются будет возвращено true, иначе false.

Учтите, что это очень простая функция и вести себя адекватно она будет только с круглыми спрайтами и только при условии, что они касаются краями граници (тоесть ширина = 2 радиуса). В других условиях процедура похожа, но необходимо считать не радиусы, а ту часть спрайта (прямоугольника) которая является картинкой, а не пустым местом…

Скачать пример

 

Источник: malimar.ru

teamviewer-com
Не копируйте текст!