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

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

Баги

Куда ж без них-то. Сколько пишут, а все никак не поисправлют. Хотя это еще ничего в сравнении с некоторыми (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 и все было хорошо. Решил тестик написать – и жуки полезли.



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

Всего комментариев: 4
09.07.2007
1. nLc
не совсем понял суть фразы:
"вращение делать с помощью спрайтов, а не команды SetRotation"
кадрами анимации что-ли?

а так респект за иследование этой темы! applause


09.07.2007
2. oxid
Все правильно ты понял smile
Заранее отрисовать положения картинки под разными углами и занести в спрайт. Потом выводить нужный кадр в соответствии с углом поворота.

10.07.2007
3. nLc
Дык это не всегда приемлимо, да и кадров/(а значит и памяти) больно много надо.

10.07.2007
4. oxid
А кто говорит, что всегда? Это просто рекомендации. А там можно и свою либу для коллизий написать biggrin Или стороннюю использовать.

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