Чтение онлайн

на главную - закладки

Жанры

Графика для Windows средствами DirectDraw

Трухильо Стэн

Шрифт:

Итак, как же будет выглядеть код проверки? Начнем с верхнего уровня и будем постепенно продвигаться вниз. Прежде всего нам понадобится цикл, который бы выполнял проверку столкновений для каждой пары спрайтов. Возникает искушение написать вложенный цикл следующего вида:

for (int i=0;i<nsprites;i++) for (int j=0;j>nsprites;j++) if (SpritesCollide(sprite[i], sprite[j])) {

 sprite[i]->Hit(sprite[j]);

 sprite[j]->Hit(sprite[i]);

}

Однако приведенный фрагмент обладает двумя недостатками.

Во-первых, каждая пара спрайтов проверяется дважды, потому что и внешний, и внутренний циклы перебирают все элементы массива спрайтов. Это вызывает напрасную трату времени и может стать источником ошибок, потому что о каждом столкновении будет сообщено дважды. Во-вторых, мы проверяем каждый спрайт, чтобы узнать, не столкнулся ли он с самим собой — полученную информацию вряд ли можно назвать полезной. Чтобы избавиться от этих проблем, следует изменить цикл:

for (int i=0;i<nsprites;i++) for (int j=i+1;j>nsprites;j++) if (SpritesCollide(sprite[i], sprite[j])) {

 sprite[i]->Hit(sprite[j]);

 sprite[j]->Hit(sprite[i]);

}

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

Теперь давайте рассмотрим функцию SpritesCollide. Как видно из кода, аргументами этой функции являются два спрайта. Функция SpritesCollide возвращает TRUE, если спрайты сталкиваются, и FALSE в противном случае.

Реализация функции SpritesCollide будет начинаться с проверки столкновений на уровне ограничивающих прямоугольников. Если результат окажется положительным (то есть ограничивающие прямоугольники пересекаются), следует перейти к проверке на уровне пикселей; в противном случае функция возвращает FALSE.

BOOL SpritesCollide(Sprite* sprite1, Sprite* sprite2) {

 ASSERT(sprite1 && sprite2);

 if (SpritesCollideRect(sprite1, sprite2)) if (SpritesCollidePixel(sprite1, sprite2)) return TRUE;

 return FALSE;

}

Обратите внимание на то, что функция SpritesCollide должна получать два аргумента — два указателя на объекты Sprite (класс Sprite рассматривается ниже). Сначала функция проверяет, что оба указателя отличны от нуля, с помощью макроса ASSERT.

СОВЕТ

ASSERT в DirectDraw

Хотя в библиотеку MFC входит макрос ASSERT, он плохо подходит для полноэкранных приложений DirectDraw. В приложении А описана нестандартная версия ASSERT, использованная в программах этой книги.

Затем функция SpritesCollide проверяет, пересекаются ли ограничивающие прямоугольники двух спрайтов. Эта проверка выполняется функцией SpritesCollideRect, которая, как и SpritesCollide, получает два указателя на объекты Sprite и возвращает логическое значение. Если прямоугольники не пересекаются (то есть SpritesCollideRect

возвращает FALSE), дальнейшая проверка не нужна, и функция возвращает FALSE — это означает, что два спрайта не сталкиваются.

Если ограничивающие прямоугольники пересекаются, необходимо продолжить проверку. Мы вызываем функцию SpritesCollidePixel и также передаем ей два указателя на объекты Sprite. Если эта проверка окажется неудачной, SpritesCollide возвращает FALSE; в противном случае она возвращает TRUE, что говорит о столкновении спрайтов.

Перед тем как рассматривать процедуру проверки на уровне пикселей, давайте рассмотрим функцию SpritesCollideRect, в которой проверяется пересечение ограничивающих прямоугольников:

BOOL SpritesCollideRect(Sprite* sprite1, Sprite* sprite2) {

 CRect rect1 = sprite1->GetRect;

 CRect rect2 = sprite2->GetRect;

 CRect r = rect1 & rect2;

 // Если все поля равны нулю, прямоугольники не пересекаются

 return !(r.left==0 && r.top==0 && r.right==0 && r.bottom==0);

}

Пересечение ограничивающих прямоугольников проверяется в функции SpritesCollideRect с помощью класса MFC CRect. Сначала для каждого спрайта вызывается функция Sprite::GetRect. Она возвращает объект CRect, определяющий текущее положение и размеры каждого спрайта. Затем третий объект CRect инициализируется оператором пересечения класса CRect (& ), который вычисляет область пересечения двух своих операндов. Если пересечения не существует (два прямоугольника не перекрываются), все четыре поля CRect обнуляются. Этот признак используется для возврата TRUE в случае пересечения прямоугольников, и FALSE — в противном случае.

Функция SpritesCollidePixel работает на уровне пикселей и потому выглядит значительно сложнее, чем ее аналог для ограничивающих прямоугольников. Функция SpritesCollidePixel приведена в листинге 9.1.

Листинг 9.1. Функция SpritesCollidePixel

BOOL SpritesCollidePixel(Sprite* sprite1, Sprite* sprite2) {

 CRect rect1=sprite1->GetRect;

 CRect rect2=sprite2->GetRect;

 CRect irect = rect1 & rect2;

 ASSERT(!(irect.left==0 && irect.top==0 && irect.right==0 && irect.bottom==0));

 CRect r1target = rect1 & irect;

 r1target.OffsetRect(-rect1.left, -rect1.top);

 r1target.right--;

 r1target.bottom--;

 CRect r2target = rect2 & irect;

 r2target.OffsetRect(-rect2.left, -rect2.top);

Поделиться:
Популярные книги

70 Рублей

Кожевников Павел
1. 70 Рублей
Фантастика:
фэнтези
боевая фантастика
попаданцы
постапокалипсис
6.00
рейтинг книги
70 Рублей

Ваше Сиятельство

Моури Эрли
1. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ваше Сиятельство

Я не Монте-Кристо

Тоцка Тала
Любовные романы:
современные любовные романы
5.57
рейтинг книги
Я не Монте-Кристо

Метатель. Книга 2

Тарасов Ник
2. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель. Книга 2

Мама из другого мира. Дела семейные и не только

Рыжая Ехидна
4. Королевский приют имени графа Тадеуса Оберона
Любовные романы:
любовно-фантастические романы
9.34
рейтинг книги
Мама из другого мира. Дела семейные и не только

Истребитель. Ас из будущего

Корчевский Юрий Григорьевич
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.25
рейтинг книги
Истребитель. Ас из будущего

Академия

Кондакова Анна
2. Клан Волка
Фантастика:
боевая фантастика
5.40
рейтинг книги
Академия

Убивать чтобы жить 5

Бор Жорж
5. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 5

Девочка-лед

Джолос Анна
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка-лед

Жена по ошибке

Ардова Алиса
Любовные романы:
любовно-фантастические романы
7.71
рейтинг книги
Жена по ошибке

Ведьма Вильхельма

Шёпот Светлана
Любовные романы:
любовно-фантастические романы
8.67
рейтинг книги
Ведьма Вильхельма

Дракон с подарком

Суббота Светлана
3. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
6.62
рейтинг книги
Дракон с подарком

Законы Рода. Том 7

Flow Ascold
7. Граф Берестьев
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Законы Рода. Том 7

Ох уж этот Мин Джин Хо 1

Кронос Александр
1. Мин Джин Хо
Фантастика:
попаданцы
5.00
рейтинг книги
Ох уж этот Мин Джин Хо 1