Вход/Регистрация
Графика для Windows средствами DirectDraw
вернуться

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

Шрифт:

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);

  • Читать дальше
  • 1
  • ...
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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