Отслеживаем столкновения двух круглых областей в 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

Technology United