ResetCollisions очищает эти слои для следующего цикла отрисовки/проверки. Для отрисовки и определения коллизий в слоях используются CollideImage и CollideRect . Для простого определения коллизии двух картинок используются ImagesCollide и ImagesCollide2, которые используют слой 32 по умолчанию, на что следует обратить внимание при работе со слоями коллизий. Теперь подробнее о функциях: 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 если картинки пересекаются. Использование: Это вторая из простейших функций определения попиксельной коллизии. Продвинутый вариант первой функции. Здесь мы можем задать поворот и размер каждой картинке индивидуально. Подходит лучше для не объектно-ориентированного программирования или когда мы работаем с небольшим количеством объектов. ResetCollisions ( mask%=0 ) mask – маска слоев для очистки, по умолчанию – все слои. Маска задаются в виде комбинации следующих величин: COLLISION_LAYER_ALL, COLLISION_LAYER_1 … COLLISION_LAYER_32. Использование: служит для очистки слоев коллизий. Есть смысл использовать в начале цикла отрисовки/проверки коллизий. !: Вот тонкий момент – со слоями. Cлои нельзя определять просто цифрами от 1 до 32, а определяются они масками (это относится и к остальным функциям, которые работают со слоями коллизий). Это нужно и что самое главное - полезно, если мы будем работать сразу с несколькими слоями. Это будет показано подробнее дальше. !: при работе с ImagesCollide и ImagesCollide2 не надо использовать ResetCollisions - При вызове этих функций ResetCollisions вызывается автоматически. (спс Crunatus за дополнение). Примеры: 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 – маска для слоев, куда будем рисовать картинку Object – ссылка на наш объект(класс, тип – как кому нравится), который будет сохраняться в слое(ях) для отрисовки картинки Возвращает: массив базовых объектов Objectс которыми наша картинка столкнулась. Если картинка ни с чем не сколлидилась, то массив объектов будет равен NULL. Описание: функция тестирует на пересечение картинку со слоем(ями) collidemask и сохраняет в слое(ях) writemask картинку и ссылку на наш объект. Таким образом, в слое накапливается некоторое количество картинок, которые мы туда помещаем. Поэтому его и надо очищать перед новым циклом отрисовки с новыми координатами картинок. Использование: благодаря возвращаемому значению и параметру Object хороша для использования при объектно-ориентированном программировании (ООП). Ах как хороша Пример использования: при отрисовке врагов, отрисовываем их и в слой коллизий. Потом при отрисовке пули (или игрока) тестируем коллизию со слоем, в который мы сохраняли врагов. !: Для отрисовки в слои коллизий используются текущие установки поворота и размера, поэтому удобно использовать функцию в методе отрисовки объекта. !: Слои для отрисовки и тестирования на коллизии можно задавать одновременно: CollideImage( Bullet_Image, x, y, frame, COLLISION_LAYER_1, COLLISION_LAYER_2, Bullet_Object ). !: Можно использовать два метода определения коллизии с помощью этой функции: просто есть ли коллизия: Quote | If CollideImage(…) Then … | и не просто, а с объектами: Quote | Local obj:Object = CollideImage(…) If obj Then For Local i%=0 To obj.length-1 ... Next EndIf | !: Преобразование типов для возвращаемого значения не работает. Т.е. возвращается всегда Object и при преобразовании TMyType ( CollideImage(…) ) будет возвращаться NULL. А было бы приятно, если бы при преобразовании производилась автоматическая выборка элементов нужного типа. Преобразование работает для конечного элемента: TMyType( obj]i[).myMethod(Paramaters). !: При использовании 0 (COLLISION_LAYER_ALL ) в качестве параметра маски слоя происходит игнорирование операции. Т.е. если мы выставим collidemask = 0, то будет производиться только запись в слои по writemask. Еще немного и перейдем к практике. CollideRect:Object( x,y,w,h,collidemask%,writemask%,id:Object=Null ) Здесь останавливаться долго не будем - все идентично предыдущей функции, только вместо картинки для определения коллизии используется прямоугольник, который задается параметрами x, y, w, h – координаты, ширина и высота. И вообще по сабжу – я говорю о попиксельных коллизиях, а это коллизия попрямоугольная. Вот и практика. Простейшее определение коллизии двух объектов: Quote | 'сбрасываем угол поворота и размеры (если надо) SetRotatin 0 SetScale 1, 1 'определяем коллизию If ImagesCollide(BulletImage, BulletX, BulletY, BulletFrame, EnemyImage, EnemyX, EnemyY, EnemyFrame ) Then ... 'делаем доброе дело EndIf | или так: Quote | 'определяем коллизию If ImagesCollide2(BulletImage, BulletX, BulletY, BulletFrame, BulletAngle, BulletScaleX, BulletScaleY, EnemyImage, EnemyX, EnemyY, EnemyFrame, EnemyAngle, EnemyScaleX, EnemyScaleY) Then ... 'творим действо EndIf | Вот посложнее: Quote | 'начало цикла ResetCollisions 'очищаем слои коллизий ... 'что-нибудь делаем For i=0 To Enemyes.Count-1 'цикл отрисовки врагов SetScale EnemyScaleX, EnemyScaleY 'размер SetRotation EnemyAngle 'угол поворота 'рисуем супостата в соответсвии с его местом и текущим кадровым положением DrawImage( Enemy.Image, Enemy.X, Enemy.Y, Enemy.Frame ) 'сохраяем картинку противника в коллизионном слое 1 'здесь есть такой момент, что маска слоя 1 равна цифре 1, поэтому приведенное 'ниже выражение правильно, но если мы хотим сохранить информацию о гаде в слое 4, 'то надо использовать COLLISION_LAYER_4 вместо 1 'при этом не тестируем остальные слои на коллизии CollideImage( EnemyImage, EnemyX, EnemyY, EnemyFrame, 0, 1 ) Next ... 'что-нибудь делаем 'проверяем коллизию пули с врагами, которые в коллизионном слое №1 If CollideImage (BulletImage, BulletX, BulletY, BulletFrame, 1, 0) ... 'что-нибудь делаем??? А что тут можно вообще делать – примерчик так – для понимания только EndIf | Этот пример дан просто для понимания того, что буфер коллизий можно заполнять. Потому как что делать с врагом при попадании в него пули не ясно, потому, что не ясно с каким врагом нам надо это делать. Ну пуля вроде одна (или даже если не одна и в цикле), она определяется однозначно – с ней можно что-то сделать. А как быть с врагами – как добраться до супостатов и учинить над ними месть неминучую? А вот если мы расширим немного пример, использовав всю мощь и красоту ООП и БМакса, то поймем, что месть действительно неминучая и враги будут настигнуты. Хотя если в этом примере заменить врагов на стены, то пуля может о них разбиться. А если еще пулю на игрока – то тогда при столкновении со стеной игрок останавливается. Т.е. просто взяты неправильные игровые объекты для примера. Но хватит флейма, снова к делу: Quote | 'начало цикла ResetCollisions 'очищаем слои коллизий ... 'что-нибудь делаем For i=0 To Enemyes.Count-1 'цикл отрисовки врагов SetScale EnemyScaleX, EnemyScaleY 'размер SetRotation EnemyAngle 'угол поворота 'рисуем супостата в соответсвии с его местом и текущим кадровым положением DrawImage( Enemy.Image, Enemy.X, Enemy.Y, Enemy.Frame ) 'сохраяем картинку противника в коллизионном слое 1 'и !!! сохраняем на него ссылку CollideImage( EnemyImage, EnemyX, EnemyY, EnemyFrame, 0, 1, Enemy ) 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 | !: В слой коллизий можно записывать несколько типов объектов, а не только один, как в примере. Определить что это за объект можно приведением типов. !: Как уже говорилось выше, можно одновременно и записывать в слой коллизий и проверять на коллизии. Это надо – если вы используете динамическое создание объектов без их сортировки, то вам не известно какой из объектов отрисуется первым, а какой последним – поэтому тестировать столкновения можно перекрестно во время их отрисовки. Вот фрагмент кода: Quote | Type TBullet Extends TSсeneObject Method Draw() SetBlend LIGHTBLEND SetAlpha 1 DrawImage(img, x, y) 'COLLISIONS Local o:Object = CollideImage(img,x,y, 0, enemy_collide_layer, bullet_collide_layer, self ) If o Then destroy = true For Local i%=0 To o.length-1 TEnemy(o]i[).destroy = true Next End If End Method End Type | Я не использую здесь проверку на валидность объекта из массива коллизий к классу TEnemy, т.к. отрисовываю в слое enemy_collide_layer только врагов, и, следовательно, там столкновение может быть только с TEnemy. В классе TEnemy код идентичный, только меняется местами слои для записи и тестирования коллизий. Quote | Local o:Object = CollideImage(img,x,y, i, bullet_collide_layer, enemy_collide_layer, self ) |
Источник: http://- |