Воскресенье, 19.05.2024, 02:54
Personal dimanche13 site
Главная | Регистрация | Вход Приветствую Вас Гость | RSS
Категории каталога
Мои статьи [22]
BlitzMax [17]
раздел содержит статьи относящиеся к языку программирования BlitzMax
SDL [9]
раздел содержит статьи на тему SDL
Code::Blocks [3]
в этом разделе рассказывается как прикрутить движок к интегрированной среде разработки(IDE) Code::Blocks
Форма входа
Поиск
Друзья сайта
Главная » Статьи » BlitzMax

BlitzMax + Farseer (3)
Сложные объекты.
Как я уже говорил ранее, к одному телу можно прицепить сразу несколько геометрий. Ну не всеже объекты так просты как круг или квадрат. Есть множество объектов, которые легко построить из простых. Допустим возьмем объект, из сэмпла к физ.движку. Это перекрещенные под прямым углом палки, на концах, которых 4 желтых шарика, и один шарик в центре. Вы удивитесь как легко это сделать, начнем.
Сделайте новый проект, и прицепите модуль farseer-а. Приинклудьте так же помощник рисования и описания цветов:
SuperStrict ' я всегда его использую ;)

Import aco.farseerphysics ' подключим физ.движок farseer

Include "DrawingSystem\Color.bmx"
Include "DrawingSystem\DrawingHelper.bmx"

Теперь опишем наш с вами тестовый объект переменными:
 Global ObjectTexture:TImage
 Global ObjectCrossBeamTexture:TImage
 Global ObjectBody:TBody
 Global ObjectGeom:TGeom[7] 

Здесь все очевидно, одно тело (Tbody) и 7 геометрий(TGeom) к нему. 5 шариков +2 палки = 7. Соответственно и две текстуры, одна для палок и одна для изображения шарика.
Опишем сначала весь наш главный игровой цикл. По образу и подобию, которые я привдил в самом начале, как рекомендуемые автором. А потом разберем все по частям.
Global physics:TPhysicsSimulator ' это будет симулятор физики
physics = TPhysicsSimulator.Create( Vector2.Create(0, 100) )

Global deltaTime:Float = 0.016

Graphics(800, 600) ' включим оконный видеорежим 800х600 
CreateObject()

SetClsColor( 255 , 128, 128 )   ' очищать экран бледно-розовым.

While Not(KeyDown(KEY_ESCAPE))
 
 physics.Update( deltaTime )
   
 Cls

  DrawObject()
  
 Flip
 
Wend

В основном должно быть все понятно. Единственное что я добавил , это цвет очистки экрана(фона), он будет бледно розовым. Нас сейчас интересуют две функции CreateObject() - которая создает объект и DrawObject() - которая этот объект рисует. Начнем по порядку, то есть с создания. 
Function CreateObject() 
 
 ' создать текстуры объекта: желтый(TColor.Yellow) круг с черной(TColor.Black) окантовкой
 ObjectTexture = TDrawingHelper.CreateCircleTexture(16, TColor.Yellow, TColor.Black, 2) 
 ' и темносерый(TColor.DarkGray) прямоугольник с черным периметром(TColor.Black)
 ObjectCrossBeamTexture = TDrawingHelper.CreateRectangleTexture(16, 120, TColor.DarkGray, TColor.Black, 2) 
 
 ' текстуры отцентровать
 MidHandleImage(ObjectTexture) 
 MidHandleImage(ObjectCrossBeamTexture) 
 
 ' создать тело для нашего обхекта
 ObjectBody = TBodyFactory.CreateRectangleBody(physics, 80, 80, 5)
 ' задать начальную позицию
 Objectbody.SetPosition(Vector2.Create(800 / 2, 110)) 
 
 ' создать 7 геометрий: два перекрещивающихся прямоугольника и пять шариков (5+2=7)
 ObjectGeom = New TGeom[7] 
 ' создаем геометрию круга, указываем ее параметры и привязываем к телу
 ObjectGeom[0] = TGeomFactory.CreateCircleGeom(physics, ObjectBody, 16, 10, Vector2.Create(- 40, - 40), 0)
 ObjectGeom[0].SetRestitutionCoefficient(.2) 
 ObjectGeom[0].SetFrictionCoefficient(.2) 
 
 ' расставляем по периметру объекта используя ObjectGeom[0] как образец, а последний в центре и привязываем к телу
 ObjectGeom[1] = TGeomFactory.CloneGeom(physics, ObjectBody, ObjectGeom[0], Vector2.Create(- 40, 40), 0)
 ObjectGeom[2] = TGeomFactory.CloneGeom(physics, ObjectBody, ObjectGeom[0], Vector2.Create(40, - 40), 0)
 ObjectGeom[3] = TGeomFactory.CloneGeom(physics, ObjectBody, ObjectGeom[0], Vector2.Create(40, 40), 0)
 ObjectGeom[4] = TGeomFactory.CloneGeom(physics, ObjectBody, ObjectGeom[0], Vector2.Create(0, 0), 0)
 
 ' теперь перекрещиваем прямоугольники
 ObjectGeom[5] = TGeomFactory.CreateRectangleGeom(physics, ObjectBody, 16, 130, Vector2.Zero(), MathHelper.PiOver4)
 ObjectGeom[6] = TGeomFactory.CreateRectangleGeom(physics, ObjectBody, 16, 130, Vector2.Zero(), - MathHelper.PiOver4)
 
End Function

Я сделал комментарии как можно более подробно. Но большинство этих функций вам уже хорошо знакомы.  Можно наблюдать как все геометрии (ObjectGeom[n]) присоединяются к одному телу (ObjectBody). Сначала сделали один шарик [0] и задали ему параметры трения и упругости. Остальные же шарики [1-4] были просто клонами первого. 
TGeomFactory.CloneGeom:TGeom(physics:TPhysicsSimulator, body:TBody, geom:TGeom, offset:Vector2 = Null, rotationOffset:Float = 0) 
вот функция: клонирования геометрии, которую мы использовали для клонирования шариков. Принимает: симулятор физики, тело, оригинал геометрии, сдвиг, поворот. Для прямоугольников совсем просто, создать геометрии и повернуть их, чтоб перекрестились.          
Объект создан и должен быть нарисован! 
Function DrawObject() 
 ' сначала рисуем перекрестие прямоугольников
 For Local i:Int = 5 To ObjectGeom.Length - 1
  TDrawingHelper.DrawGeom( ObjectGeom[i] , ObjectCrossBeamTexture )
 Next
 
 ' затем рисуем шарики на концах и один в середине
 For Local i:Int = 0 To 4
  TDrawingHelper.DrawGeom( ObjectGeom[i] , ObjectTexture )
 Next
 
 ' вернем начало координат и поворот к стандартным значениям
 SetOrigin(0, 0) 
 SetRotation(0) 
 
End Function

К комментариям, мне даже нечего добавить.
Теперь было бы неплохо и поуправлять нашим объктом с клавиатуры к примеру и вращать его по часовой или против часовой стрелки. А для того чтобы сдвинуть физический объкт, в нашей поседневной жизни, к нему надо применить силу, как не удивительно это звучит, но метод который это делает в движке farseer, называется так ApplyForce(forceVector) (Apply - применить, Force - сила)и передается в него вектор. Конечно, это метод для тела (TBody). 
Function UpdateObject()

  Local force:Vector2 = Vector2.Zero()
  Local speed:Float = 1000
  
  If KeyDown(KEY_UP) Then
  force.Y:-speed
  End If
  If KeyDown(KEY_DOWN) Then
  force.Y:+speed
  End If
  If KeyDown(KEY_LEFT) Then
  force.X:-speed
  End If
  If KeyDown(KEY_RIGHT) Then
  force.X:+speed
  End If
  
  ObjectBody.ApplyForce(force)
  
  Local torque:Float = 0
  Local torqueAmount:Float = 1000
  
  If KeyDown(KEY_A) Then torque :- torqueAmount
  If KeyDown(KEY_D) Then torque :+ torqueAmount
  ObjectBody.ApplyTorque(torque) 

End Function

Тут дело такое. Сила - это вектор, который в первую очередь указывает направление, а во вторую очередь, можно приложить разного масштаба силу к объекту. Так же вот и вся функция. ApplyTorque - применяет к телу вращение(Крутящий момент), я повесил на кнопки A и D. Вставьте вызов этой функции, до CLS. 
Категории коллизий.
Объектов на уровне может быть великое множество, и по правилам игры, возможно, некоторые из них не должны контактировать с другими, ну а с третьими просто обязаны. Вы понимаете к чему я клоню?
Каждая геометрия может быть отнесена к 32 категориям коллизий. И каждый объект может определить, с какими категориями он может столкнуться. Это довольно гибкая система определения столкновений между геометриями. Сам же автор признает, что этот метод он заимствовал в другом физ.движке ODE. И надо сказать, что метод действительно прост в использовании. По умолчанию все геометрии сталкиваются(коллизируют) между собой. Категории имеют тип int(32 бита), так что пользователь может указать произвольный характер взаимодействий для 32 объектов. Если есть более 32 объектов, то некоторые из них, безусловно, будут иметь ту же категорию.
Используйте методы геометрии  
SetCollisionGroup( collisionGroup ) 
SetCollisionCategory( collisionCategories )
SetCollidesWith( collidesWith )
Например для некоей геометрии вы можете указать категорию коллизий 5, и указать обработку столкновений со своей категорией(5) с третьей(3) и первой(1) (объединяются категории знаком | (or) )
это будет выглядеть так:
  Geom.SetCollisionGroup( 1 )
  Geom.SetCollisionCategory( CollisionCategories.Cat5 )
  Geom.SetCollidesWith( CollisionCategories.Cat5 | CollisionCategories.Cat3 | CollisionCategories.Ca1)
Если же вы хотите указать, только ту геометрию с которой сталкновений не будет, то следует писать так:
  Geom.SetCollidesWith(CollisionCategories.All & ~CollisionCategories.Cat1)
Если хотите узнать об этом более подробно, то смотрите Демку номер 5. :)

ToDo: про joint-ы (суставы).

Выведение.

Как написано в единственном к Farseer-у оффициальном примере "The rest is really just details." Что на русском означает - "Остальное просто детали." Так что дальше ковыряйтесь сами! 

Спасибо, за внимание! Удачи!




Категория: BlitzMax | Добавил: dimanche (31.07.2008) | Автор: Dmitriy
Просмотров: 979 | Комментарии: 5 | Рейтинг: 0.0/0 |
Всего комментариев: 3
3 Diablo1909  
0
СПАСИБО ОГРОМНОЕ ЗА СТАТЬИ!!!

2 Randomize  
0
Круто!
Очень помогло!
Низкий поклон...

1 ICoder  
0
Премного благодарен за статью!

Имя *:
Email *:
Код *:
Copyright MyCorp © 2024