Blitzmax
Понедельник, 25.11.2024, 03:09
Приветствую Вас Гость | RSS
 
Главная СтатьиРегистрацияВход
Меню сайта
Категории каталога
Разное [2]
BlitzMax [5]
Доки/Уроки [8]
Игровое программирование [1]
Наш опрос
Оцените скорость работы с сайтом
Всего ответов: 112
Главная » Статьи » Доки/Уроки

Коллизии или столкновения по нашему, часть 1.

Теория

Для работы с коллизиями (столкновениями) есть две методики: непосредственное определение и отложенное. Непосредственное использует функции 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



Другие материалы по теме
Категория: Доки/Уроки | Добавил: oxid (09.07.2007)
Просмотров: 6593 | Рейтинг: 5.0/1 |

Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа
Поиск
Ссылки
Статистика
Copyright Oxid © 2024
Сайт создан в системе uCoz