Баги
Куда ж без них-то. Сколько
пишут, а все никак не поисправлют. Хотя это еще ничего в сравнении с некоторыми
(GarageGames). Но об этом в другой раз.
Вот код:
Rem
Collision Test
EndRem
Strict
Import birdie.pixmaptools
Graphics 800 , 600, 0, 50
Global gbLayerCollision = False
Global gbImagesCollide = False
Global gbImagesCollide2 = False
Global gbCollideRect = False
AutoMidHandle True
Local im1:TImage = CreateImage(40,40)
Local pm:TPixmap = CreatePixmap(40,40,PF_RGBA8888)
PixmapRect( pm , 0,0,
pm.width,pm.height, $FFFFFF00)
im1.SetPixmap( 0, pm.Copy()
)
'SetImageHandle(im1,10,50)
Type TEntity
Field img:TImage
Field x#, y#
Field rotation#
Method Draw()
SetRotation rotation
SetColor 255,255,255
DrawImage(img,x,y)
SetColor 255,0,0
DrawOval(x,y,4,4)
If Self = e2
'send
collisions
CollideImage(img,x,y,0,0,COLLISION_LAYER_1,Self)
CollideRect(x,y,img.width, img.height, 0,COLLISION_LAYER_2,Self)
Else
'responce
collisions
gbLayerCollision=(CollideImage(img,x,y,0,COLLISION_LAYER_1,0,Self)<>Null)
gbCollideRect=(CollideRect(x,y,img.width, img.height,
COLLISION_LAYER_2,0,Self)<>Null)
End If
End Method
End Type
Global e1:TEntity = New TEntity
e1.img = im1
e1.y = 300
e1.x = 450
e1.rotation = 45
Global e2:TEntity = New TEntity
e2.img = im1
e2.y = 300
e2.x = 350
e2.rotation = 0
While Not (KeyHit(key_escape) Or AppTerminate())
Update()
Draw()
Wend
End
Function Update()
If KeyDown( KEY_LEFT )Then e1.x:-1
If KeyDown( KEY_RIGHT )Then e1.x:+1
If KeyDown( KEY_UP )Then e1.y:-1
If KeyDown( KEY_DOWN )Then e1.y:+1
gbImagesCollide = ImagesCollide(e1.img,e1.x,e1.y,0, e2.img,e2.x,e2.y,0)
gbImagesCollide2 = ImagesCollide2(e1.img,e1.x,e1.y,0,e1.rotation,1,1,
e2.img,e2.x,e2.y,0,e2.rotation,1,1)
End Function
Function Draw()
Cls
ResetCollisions
e2.Draw
e1.Draw
'info
SetRotation 0
SetColor 255,255,255
If gbImagesCollide Then DrawText "ImagesCollide",8,8
If gbLayerCollision Then DrawText "CollideImage
(Layers collision)",8,28
If gbImagesCollide2 Then DrawText "ImagesCollide2",8,48
If gbCollideRect Then DrawText "CollideRect",8,68
Flip(-1)
End Function
Кратко суть: определение
коллизий глючит при использовании отрисовки с изменением хэндла картинки (AutoMidHandle(True) и SetImageHandle). С поворотами тоже
наблюдаются странности.
Как проверить? - очень просто!
Запускаем код и жмем курсор влево. Правый квадратик, который повернут (ромбик)
начинает двигаться влево и не доезжая до цели срабатывает коллизия по CollideRect.
А не должна. Ну в общем, поиграйтесь с поворотами (e1.rotation, e1.rotation),
хэндлами (AutoMidHandle, SetImageHandle), если есть желание, а я уже
наигрался. На ImagesCollide можно особо не смотреть – она без учета
поворотов и прочего. Попробуйте найти ошибки в коде. А кому не интересно –
читайте сразу советы.
Советы
Из-за того, что функции для
непосредственного определения столкновений (ImagesCollide и ImagesCollide2)
используют 32-й слой, то мы должны будем ограничиться остальными слоями, не
трогая 32, если будем применять их в работе.
Попиксельное определение
столкновений, достаточно ресурсоемкий процесс и надо оптимизировать работу по
приему-отсылке данных столкновений. Сделать сортировку обработки объектов по
отношению к приему-передаче данных столкновения. Так объекты, отсылающие данные,
должны обрабатываться сначала, а потом – объекты, принимающие столкновения. Это
позволит избежать дополнительных перекрестных проверок на столкновения у всех
объектов, участвующих в группе столкновения и сэкономить ресурсы. И,
следовательно, повысить быстродействие свого кода.
При работе с CollideRect и CollideImage,
можно одновременно и записывать и считывать данные столкновений. Как показала
практика, этого лучше не делать – быстродействие получается заметно ниже, чем
при использовании отдельно двух команд: одну для записи, другую для считывания.
Т.е. не
CollideRect(x,y,width,height, COLLISION_LAYER_1, COLLISION_LAYER_2, self),
а вот так:
CollideRect(x,y,width,height, 0, COLLISION_LAYER_2,
self)
CollidedObjects = CollideRect(x,y,width,height, COLLISION_LAYER_1, 0)
При работе с функциями
определения столкновений, наблюдаются неточности: если изменять хэндл
(центрирование) картинки (AutoMidHandle, SetImageHandle) и вращать саму
картинку. Наиболее точные функции: CollideImage и ImagesCollide2.
Соответственно рекомендуется: не использовать CollideRect и ImagesCollide;
вращение делать с помощью спрайтов, а не команды SetRotation; осторожнее
быть с центрированием картинок при определении столкновений; использовать
сторонние либы (я их не знаю, но, думаю, они есть). Хотя в большинстве
стандартных проектов эти ошибки не встретятся. Я вот юзал CollideImage и
все было хорошо. Решил тестик написать – и жуки полезли.
Другие материалы по теме
|