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

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

Жанры

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

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

Шрифт:

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

СОВЕТ

Кое-что о классе CRect

Класс MFC CRect реализован так, чтобы при вычитании поля left из поля right получалась ширина прямоугольника. Такой подход удобен, но смысл поля right несколько изменяется. Например, рассмотрим прямоугольник, у которого поле left равно 0, а полю right

присвоено значение 4. В соответствии с реализацией класса CRect такой прямоугольник имеет ширину в 4 пикселя, но если использовать эти же значения для обращений к пикселям, ширина прямоугольника окажется равной 5 пикселям (поскольку в нее будут включены пиксели с номерами от 0 до 4). Такие же расхождения возникают и для полей top и bottom. Следовательно, чтобы использовать поля CRect для работы с пикселями, необходимо уменьшить на 1 значения полей right и bottom.

Настоящая проверка столкновений происходит на этапе 3. Способ ее выполнения зависит от того, используют ли оба спрайта одну и ту же поверхность или нет. Сначала мы получаем поверхности обоих спрайтов функцией Sprite::GetSurf:

LPDIRECTDRAWSURFACE surf1=sprite1->GetSurf;

LPDIRECTDRAWSURFACE surf2=sprite2->GetSurf;

Если поверхности совпадают, проверка выполняется следующим фрагментом:

if (surf1==surf2) {

 surf1->Lock(0, &desc1, DDLOCK_WAIT, 0);

 surfptr1=(BYTE*)desc1.lpSurface;

 for (int yy=0;yy<height;yy++) {

for (int xx=0;xx>width;xx++) {

pixel1=surfptr1+(yy+r1target.top)*desc1.lPitch +(xx+r1target.left);

pixel2=surfptr1+(yy+r2target.top)*desc1.lPitch +(xx+r2target.left);

if (*pixel1 && *pixel2) {

ret=TRUE;

goto done_same_surf;

}

}

 }

done_same_surf:

 surf1->Unlock(surfptr1);

 return ret;

}

Сначала мы блокируем поверхность, чтобы получить доступ к ее памяти. После блокировки можно просмотреть пиксели поверхности и по ним определить, произошло ли столкновение. Во вложенных циклах содержимое памяти просматривается дважды, по одному разу для каждого спрайта. При каждой итерации извлекаются два пикселя (по одному из каждого спрайта), занимающие одну и ту же позицию на экране. Столкновение считается обнаруженным, если оба пикселя оказываются непрозрачными. Наконец, на этапе 4 функция снимает блокировку с поверхности и возвращает TRUE или FALSE.

Если два спрайта находятся на разных поверхностях, проверка столкновений выполняется другим фрагментом функции SpritesCollidePixel. Ниже снова приведен соответствующий фрагмент листинга 9.1:

surf1->Lock(0, &desc1, DDLOCK_WAIT, 0);

surfptr1=(BYTE*)desc1.lpSurface;

surf2->Lock(0, &desc2, DDLOCK_WAIT, 0);

surfptr2=(BYTE*)desc2.lpSurface;

for (int yy=0;yy<height;yy++) {

 for (int xx=0;xx>width;xx++) {

pixel1=surfptr1+(yy+r1target.top)*desc1.lPitch +(xx+r1target.left);

pixel2=surfptr2+(yy+r2target.top)*desc2.lPitch +(xx+r2target.left);

if (*pixel1 && *pixel2) {

ret=TRUE;

goto done;

}

 }

}

done:

surf2->Unlock(surfptr2);

surf1->Unlock(surfptr1);

return ret;

Этот

фрагмент похож на приведенный выше, за исключением того, что в нем блокируются обе поверхности и каждая из них просматривается по отдельности. Столкновение снова обнаруживается по совпадению двух непрозрачных пикселей. Перед тем как функция возвращает TRUE или FALSE, она снимает блокировку с обеих поверхностей.

Класс Sprite 

В коде предыдущего раздела класс Sprite использовался для представления спрайтов, проверяемых на столкновение. Давайте посмотрим, как он реализован.

Как мы уже видели, класс Sprite содержит ряд функций, с помощью которых при проверке столкновений можно получить сведения о каждом спрайте. В частности, функция GetRect возвращает контурный прямоугольник спрайта, а функция GetSurf — поверхность, на которой находится спрайт. Однако класс Sprite не ограничивается функциями простого контейнера для данных спрайта. Он предназначен не столько для обнаружения столкновений, сколько для их обработки.

На обнаруженное столкновение необходимо как-то прореагировать. Подробности обработки столкновения определяются приложением, но как проверка, так и обработка подчиняются некоторым общим правилам.

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

Рассмотрим столкновение, в котором участвуют два спрайта. Наш код должен обнаруживать столкновение и сообщать об этом спрайтам. Предположим, один из спрайтов получает уведомление, немедленно вычисляет новую траекторию и изменяет свое положение. Когда сообщение о столкновении дойдет до второго спрайта, столкнувшийся с ним спрайт уже будет находиться в новом месте. Более того, перемещение первого спрайта может привести к тому, что для второго спрайта предыдущего столкновения как бы и не будет.

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

Город драконов

Звездная Елена
1. Город драконов
Фантастика:
фэнтези
6.80
рейтинг книги
Город драконов

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

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

На границе империй. Том 9. Часть 2

INDIGO
15. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 2

ВоенТур 3

АЗК
3. Антиблицкриг
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
ВоенТур 3

Недотрога для темного дракона

Панфилова Алина
Фантастика:
юмористическое фэнтези
фэнтези
сказочная фантастика
5.00
рейтинг книги
Недотрога для темного дракона

Неудержимый. Книга V

Боярский Андрей
5. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга V

Семья. Измена. Развод

Высоцкая Мария Николаевна
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Семья. Измена. Развод

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Зеркало силы

Кас Маркус
3. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Зеркало силы

Релокант. Вестник

Ascold Flow
2. Релокант в другой мир
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Релокант. Вестник

Свет во мраке

Михайлов Дем Алексеевич
8. Изгой
Фантастика:
фэнтези
7.30
рейтинг книги
Свет во мраке

Скандальная свадьба

Данич Дина
1. Такие разные свадьбы
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Скандальная свадьба

Кодекс Крови. Книга IХ

Борзых М.
9. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IХ

Адвокат Империи 2

Карелин Сергей Витальевич
2. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 2