Теория
Для работы с коллизиями
(столкновениями) есть две методики: непосредственное определение и отложенное.
Непосредственное использует функции ImagesCollide и ImagesCollide2 и служит для определения столкновения именно в
данный момент. Отложенное основано на работе со слоями и может использоваться
для определения столкновения с объектом, который уже обрабатывался.
Подробнее о функциях для
непосредственного определения столкновения:
ImagesCollide(
image1:TImage,x1,y1,frame1,image2:TImage,x2,y2,frame2 )
image1 – первая картинка;
x1,y1,frame1 – координаты и кадр первой картинки.
image2 – вторая картинка
x2,y2,frame2 – координаты и кадр второй картинки.
Возвращает: True если картинки пересекаются.
Использование: Это одна из простейших функций определения попиксельной
коллизии и подходит больше для не объектно-ориентированного подхода к
программированию или когда у нас небольшое количество объектов. Особенности:
Для тестирования используются текущие величины поворота и размера, которые
будут применяться одинаково и к первой и ко второй картинке. Поэтому при
необходимости их надо определить перед использованием этой функции, используя SetScale
и SetRotation.
ImagesCollide2( image1:TImage, x1, y1, frame1, rot1#,
scalex1#, scaley1#, image2:TImage, x2, y2, frame2, rot2#, scalex2#, scaley2# )
image1 – первая картинка;
x1,y1,frame1 – координаты и кадр первой картинки.
rot1#, scalex1#, scaley1# – величины поворота, размера по x и y для
первой картинки.
image2 – вторая картинка
x2,y2,frame2 – координаты и кадр второй картинки.
rot2#, scalex2#, scaley2# – величины поворота, размера по x и y для
второй картинки.
Возвращает: True, если картинки пересекаются.
Использование: Это продвинутый вариант предыдущей функции.
Подходит лучше для не объектно-ориентированного программирования или когда мы
работаем с небольшим количеством объектов.
Особенности:
Мы можем задать поворот и размер каждой картинке
индивидуально.
Теперь о работе со слоями. Есть 32 слоя для определения
столкновений. Слои представлены масками, поэтому задавать их надо
соответственно. Хотя для облегчения работы с ними есть константы, эти маски
задающие. Формат их таков: COLLISION_LAYER_ххх, где ххх – число от 1 до 32 или
слово «ALL», обозначающее все слои сразу. Мы можем записывать и считывать в слои
информацию о столкновениях. Другими словами, посылать и получать данные о
столкновениях. Алгоритм работы такой: сначала мы очищаем нужные слои. Потом во
время прохода по игровым объектам записываем и (или) считываем информацию о
столкновениях. Получив данные столкновения, мы можем вызвать у объектов
столкновения соответствующие методы. Объекты можно распределить по трем
группам: только отсылающие данные о себе, принимающие данные о столкновении с
другими объектами, и смешанные – принимающие и отсылающие данные столкновений. Тут
такой нюанс: если мы не знаем четкого порядка обработки объектов, то мы должны
делать и отсылку и прием данных. На примере: если объект(ы) только принимает
столкновения и обработался первым, то он не получит данных от остальных
объектов, которые только отсылают данные столкновения.
Используемые функции:
ResetCollisions ( mask%=0 )
mask – маска слоев для очистки, по умолчанию – все слои. Маска задаются
в виде комбинации следующих величин: COLLISION_LAYER_ALL, COLLISION_LAYER_1 …
COLLISION_LAYER_32.
Использование: Служит для очистки слоев коллизий. Используется в
начале цикла обработки столкновений.
Примеры:
ResetCollisions – очищает все слои
ResetCollisions ( COLLISION_LAYER_ALL ) – очищает все слои
ResetCollisions ( COLLISION_LAYER_1 ) – очищает слой 1
ResetCollisions ( COLLISION_LAYER_1 | COLLISION_LAYER_2 ) – очищает слой
1 и 2
CollideImage:Object[](
image:TImage,x,y,frame,collidemask%,writemask%,id:Object=Null )
image – наша картинка
x,y,frame – ее координаты и кадр
collidemask – маска для слоев, где будем проверять коллизии (прием)
writemask – маска для слоев, куда будем рисовать картинку (отсылка)
id – ссылка на наш объект, который будет сохраняться для последующей
обработки.
Возвращает: массив базовых объектов Object[] с которыми
столкнулась картинка. Если столкновений нет, то возвращается NULL.
Описание: функция тестирует на пересечение текущую картинку с
другими в слоях, заданных collidemask и сохраняет ее данные в слоях,
заданных writemask. Пи сохранении данных в слое, они накапливаются и его
надо очищать перед новым циклом обработки. Для этого и используется ResetCollisions.
Использование: благодаря возвращаемому значению и параметру id,
используется при объектно-ориентированном программировании (ООП).
Особенности:
Для отрисовки в слои коллизий
используются текущие установки поворота и размера, поэтому удобно использовать
функцию в методе отрисовки объекта.
При использовании 0 (COLLISION_LAYER_ALL)
в качестве параметра маски слоя, происходит игнорирование операции. Т.е. если
мы выставим collidemask = 0, то будет производиться только запись в слои
по writemask.
CollideRect:Object[](x,y,w,h,collidemask%,writemask%,id:Object=Null) – эта функция полностью аналогична предыдущей с той только разницей, что
для определения столкновения задается не картинка, а прямоугольник.
Примеры
Простейшее определение
коллизии двух объектов:
'сбрасываем угол поворота и
размеры (если надо)
SetRotatin 0
SetScale 1, 1
'определяем коллизию
If ImagesCollide(BulletImage, BulletX, BulletY, BulletFrame, EnemyImage,
EnemyX, EnemyY, EnemyFrame ) Then
... 'делаем доброе дело
EndIf
Или так:
'определяем коллизию
If ImagesCollide2(BulletImage, BulletX, BulletY, BulletFrame, BulletAngle,
BulletScaleX, BulletScaleY, EnemyImage, EnemyX, EnemyY, EnemyFrame,
EnemyAngle, EnemyScaleX, EnemyScaleY) Then
... 'делаем доброе дело
EndIf
Отложенное определение
коллизий с ООП:
'начало цикла
ResetCollisions 'очищаем слои коллизий
... 'что-нибудь делаем
For i=0 To Enemyes.Count-1 'цикл отрисовки врагов
SetScale
EnemyScaleX, EnemyScaleY 'размер
SetRotation
EnemyAngle 'угол поворота
'рисуем супостата в соответсвии с его местом и текущим
кадровым положением
DrawImage(
Enemy[i].Image, Enemy[i].X, Enemy[i].Y, Enemy[i].Frame )
'сохраяем картинку противника в коллизионном слое 1
'и сохраняем на него ссылку
CollideImage( EnemyImage, EnemyX, EnemyY, EnemyFrame, 0, 1, Enemy[i] )
Next
... 'что-нибудь делаем
'получаем массив врагов из слоя №1 с которыми
столкнулась пуля
Local obj[] = CollideImage
(BulletImage, BulletX, BulletY, BulletFrame, 1, 0)
'проверяем не пуст ли массив – а было ли столкновение
If obj
'проходим по полученному
массиву
For Local i%=0 To obj.length-1
Local e: TEnemy = TEnemy(obj[i]) 'получаем
врага, используя приведение типов
If e Then e.Kick(BulletPower) 'если это враг, а не кто-то другой, бьем его
Next
DestoyBullet() 'пуля
сделала свое дело – она должна исчезнуть
EndIf
Другие материалы по теме
|