Вторник, 23 Апреля 2024, 11:21

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 2 из 5
  • «
  • 1
  • 2
  • 3
  • 4
  • 5
  • »
Форум игроделов » Записи участника » vovnet [98]
Результаты поиска
vovnetДата: Четверг, 28 Июня 2012, 11:00 | Сообщение # 21 | Тема: Box2D 2.1a Tutorial – Part 4 (Render)
почетный гость
Сейчас нет на сайте


Предыдущий урок:
Part 3

Box2D 2.1a Tutorial – Part 4 (Render)


В этом уроке речь пойдет:
1. отображение тел в режиме отладки (debug)
2. создание графического отображения для тела.

В предыдущих уроках я использовал код, в котором некоторые его части были вам не известны и приходилось попросту закрывать на него глаза. В этом же уроке мы детально рассмотрим те части кода, которые до сих пор оставались без внимания.
Для лучшего закрепления материала мы напишем код с нуля. Но объяснять я буду только 2 темы, поэтому если вы не читали предыдущие уроки — настоятельно рекомендую с ними ознакомится.

Итак, в предыдущих уроках мы научились создавать мир, обновлять его и добавлять тела. Теперь же напишем код в котором и применим наши знания.

Code
package     
{
     import Box2D.Collision.Shapes.b2CircleShape;
     import Box2D.Collision.Shapes.b2Shape;
     import Box2D.Dynamics.b2World;
        import Box2D.Common.Math.b2Vec2;
        import Box2D.Dynamics.b2BodyDef;
        import Box2D.Dynamics.b2Body;
        import Box2D.Collision.Shapes.b2PolygonShape;
        import Box2D.Dynamics.b2Fixture;
        import Box2D.Dynamics.b2FixtureDef;
     import Box2D.Dynamics.b2DebugDraw;
     import flash.display.Bitmap;
        import flash.display.MovieClip;
        import flash.display.Sprite;
        import flash.events.Event;
         
     [SWF(width = "800", height = "600", backgroundColor="#292929", frameRate = "30")]
     public class TestClass extends Sprite
     {
      private var world:b2World;    // Мир
      private const WORLD_WIDTH:int = 800;    // Ширина мира в пикселях
      private const WORLD_HEIGHT:int = 600;    // Высота мира в пикселях
      private const METERS:int = 30;   // Коэффициент преобразования пикселей в метры (30px = 1m)
          
      public function TestClass():void
      {
       initWorld();
       stage.addEventListener(Event.ENTER_FRAME, updateWorld);
      }
          
      ////////////////////////////////////////////////////////////////
      // Инициализация игрового мира
      private function initWorld():void
      {
       var gravity:b2Vec2 = b2Vec2.Make(0, 20);    // Вектор гравитации в мире
       var doSleep:Boolean = true;     // Разрешаем телам засыпать
           
       world = new b2World(gravity, doSleep);  // Создаем мир
           
       createBody();
      }
          
      ////////////////////////////////////////////////////////////////
      // Обновление мира
      private function updateWorld(e:Event):void
      {
       world.Step(1 / 30, 10, 10);    // Запускаем расчет физики
       world.ClearForces();  // Очищаем силы в мире
      }
          
      ////////////////////////////////////////////////////////////////
      // Создание объекта
      private function createBody():void
      {
       var body:b2Body;                    // Тело
       var bodyDef:b2BodyDef    = new b2BodyDef();  // Геометрические свойства тела
       var bodyShape:b2PolygonShape    = new b2PolygonShape();    // Форма тела
       var fixtureDef:b2FixtureDef  = new b2FixtureDef();    // Физические свойства тела
           
       bodyDef.position.Set(WORLD_WIDTH / METERS / 2, 1);
       bodyDef.type = b2Body.b2_dynamicBody;
       body = world.CreateBody(bodyDef);
       bodyShape.SetAsBox(1, 1);
       fixtureDef.shape = bodyShape;
       body.CreateFixture(fixtureDef);
      }
     }
         
}


Если мы запустим этот код, то все скомпилируется без ошибок, но на экране мы ничего не увидим. Что же произошло, почему ничего нет?
На самом деле наш мир создался, в него добавилось тело и оно успешно подчиняется физическим законам, но оно невидимое. Для того, чтобы его увидеть, необходимо создать графическое отображение этого тела.
Здесь мы можем столкнуться с еще одной проблемой — графика для игры еще не готова, а работать над игрой нужно дальше.

1. Отображение тел в режиме отладки (debug).
Для отображения тела в режиме отладки, в движке существует класс b2DebugDrow. Нам лишь остается создать на его основе объект и передать его в мир, чтобы он знал как отрисовывать тела. Но это еще не все! Так как мир обновляется со скоростью частоты кадров нашей флешки, нам придется каждый раз перерисовывать debug всех тел в мире с помощью метода DrawDebugData().

Теперь давайте добавим в наш код возможность отрисовки debug тел:
Code
///////////////////////////////////////////////////////////////
      // Отрисовка debug тела
      private function drowDeb():void
      {
       // Создаем спрайт в который будет отрисован debug
       var debugSprite:Sprite = new Sprite();
       addChild(debugSprite);
           
       // Объект который отрисует debug
       var debugDrow:b2DebugDraw = new b2DebugDraw();
       debugDrow.SetSprite(debugSprite);   // Устанавливаем спрайт
       debugDrow.SetDrawScale(METERS);    // Масштаб отрисовки
       debugDrow.SetFillAlpha(0.5);    // Прозрачность тел
       debugDrow.SetLineThickness(1);    // Толщина линий
       debugDrow.SetFlags(b2DebugDraw.e_shapeBit);    // Флаги
       world.SetDebugDraw(debugDrow);   // Добавляем debug в мир
           
      }

Так же добавим в вызов DrawDebugData() в метод updateWorld() нашего класса:
Code
world.DrawDebugData();


И схемка для наглядности:


Методы 2dDebugDraw:
b2DebugDraw() - Конструктор.
AppendFlags(flags:uint):void - Добавляет указанные флаги к текущим флагам отрисовки.
ClearFlags(flags:uint):void - Удаляет указанные флаги из текущих флагов отрисовки.
GetAlpha():Number - Возвращает текущую установленную прозрачность линий.
GetDrawScale():Number - Возвращает текущий установленный масштаб отрисовки тел.
GetFillAlpha():Number - Возвращает текущую установленную прозрачность заливки.
GetFlags():uint - Возвращает текущие установленные флаги отрисовки.
GetLineThickness():Number - Возвращает текущую установленную толщину линий.
GetSprite():Sprite - Возвращает ссылку на спрайт, в который отрисовываются debug тела.
SetAlpha(alpha:Number):void - Устанавливает значение прозрачности линий.
SetDrawScale(drawScale:Number):void - Устанавливает масштаб отрисовки тел.
SetFillAlpha(alpha:Number):void - Устанавливает значение прозрачности заливки.
SetFlags(flags:uint):void - Устанавливает флаги отрисовки.
SetLineThickness(lineThickness:Number):void - Устанавливает толщину линий.
SetSprite(sprite:Sprite):void - Записывает ссылку на спрайт, в который будут отрисовываться debug тела.

Флаги определяют что должно рисоваться на экране:
e_aabbBit: uint = 0x0004 - Отрисовывать AABB.
e_centerOfMassBit: uint = 0x0010 - Отрисовывать центр массы тела в текущем кадре.
e_controllerBit: uint = 0x0020 - Отрисовывать контроллеры.
e_jointBit: uint = 0x0002 - Отрисовывать соединения.
e_pairBit: uint = 0x0008 - Отрисовывать пары AABB широкой-фазы.
e_shapeBit: uint = 0x0001 - Отрисовывать шейпы.

2. Создание графического отображения для тела.
Для хранения графики мы будем использовать Bitmap, который в свою очередь будет находится в спрайте. А ссылку на Sprite сохраним в свойстве тела userData:*.
Поскольку в мире точка регистрации объектов находится по центру объекта, то нам придется Bitmap оборачивать спрайтом и уже внутри смещать Bitmap на половину его ширины и высоты.

Code
// Изображение тела
var pictures:Bitmap = new Pic();    // Создаем изображение
// Смещаем по ширине и высоте на половину
pictures.x -= pictures.width / 2;
pictures.y -= pictures.height / 2;
var spr:Sprite = new Sprite();  // Создаем контейнер для изображения
// Устанавливаем спрайт в необходимые координаты
spr.x = 400;
spr.y = 100;
spr.addChild(pictures);    // Добавляем в контейнер изображение
addChild(spr);


Здесь мы создали изображение, после сместили его на половину по Х и Y, затем поместили его в спрайт и задали начальные координаты в мире.
Теперь необходимо в свойство userData геометрических свойств объекта присвоить наш спрайт:

Code
bodyDef.userData = spr;    // Сохраняем изображение в свойство userData объекта


А так же задать телу размеры нашего спрайта и начальную позицию:

Code
bodyDef.position.Set(spr.x / METERS, spr.y / METERS);
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.userData = spr;    // Сохраняем изображение в свойство userData объекта
body = world.CreateBody(bodyDef);
bodyShape.SetAsBox(spr.width / METERS / 2, spr.height / METERS / 2);
fixtureDef.shape = bodyShape;
body.CreateFixture(fixtureDef);


Если вы сейчас запустите приложение, то увидите, что тело падает вниз, а спрайт по-прежнему остается на своей позиции. Это происходит потому, что с каждым обновлением мира меняется позиция тела, но не его изображения, потому как в свойстве userData могут храниться любые данные: звук, текст, анимация..., естественно нам придется самим запрограммировать поведение этих данных.
Тут мы сталкиваемся с еще одной проблемой — все объекты в мире созданы с помощью одного и того же экземпляра класса, как же нам обратиться к нужному телу?

Сначала, для наглядности я покажу способ, который подойдет для случая с одним телом в мире. Перепишем наш метод updateWorld

Code
////////////////////////////////////////////////////////////////
      // Обновление мира
      private function updateWorld(e:Event):void
      {
       world.Step(1 / 30, 10, 10);    // Запускаем расчет физики
       world.ClearForces();  // Очищаем силы в мире
           
       var bodyList:b2Body = world.GetBodyList();
       var img:* = bodyList.GetUserData();
       var pos:b2Vec2 = bodyList.GetPosition();
           
       if (img)
       {
        img.x = pos.x * 30;    // переводим в пиксели
        img.y = pos.y * 30;
        img.rotation = bodyList.GetAngle();
       }
           
       world.DrawDebugData();
      }


Теперь все работает отлично, но вот добавив второй объект, его спрайт будет по-прежнему находится на одном месте. Для этого у класса b2Body есть методы позволяющие получить доступ к каждому свойства объекта, просто перебирая их в цикле с использованием метода GetNext() который с каждым вызовом будет возвращать следующее тело.
Если вы знакомы с динамическими структурами данных в C++, то наверняка поймете, что это реализовано с помощью алгоритма односвязных списков.
Если вкратце, то каждое создаваемое тело сохраняет ссылку на себя в предыдущем теле и чтобы, например получить доступ к пятому телу, нам необходимо обратиться к первому и в цикле пробежаться до пятого.
Теперь давайте добавим еще немного тел в наш мир:

Code
for (var i:int = 0; i < 5; i++ )
       {
        // Изображение тела
        var pictures:Bitmap = new Pic();    // Создаем изображение
        // Смещаем по ширине и высоте на половину
        pictures.x -= pictures.width / 2;
        pictures.y -= pictures.height / 2;
        var spr:Sprite = new Sprite();  // Создаем контейнер для изображения
        // Устанавливаем спрайт в необходимые координаты
        spr.x = 100 * i + 200;
        spr.y = 100;
        spr.addChild(pictures);    // Добавляем в контейнер изображение
        addChild(spr);
            
        bodyDef.position.Set(spr.x / METERS, spr.y / METERS);
        bodyDef.type = b2Body.b2_dynamicBody;
        bodyDef.userData = spr;    // Сохраняем изображение в свойство userData объекта
        body = world.CreateBody(bodyDef);
        bodyShape.SetAsBox(spr.width / METERS / 2, spr.height / METERS / 2);
        fixtureDef.shape = bodyShape;
        body.CreateFixture(fixtureDef);
       }


И добавим цикл в метод updateWorld(), который будет с каждой итерацией получать доступ к следующему телу:

Code
for (var bodyList:b2Body = world.GetBodyList(); bodyList; bodyList = bodyList.GetNext() )
       {
        var img:* = bodyList.GetUserData();
        var pos:b2Vec2 = bodyList.GetPosition();
            
        if (img)
        {
         img.x = pos.x * 30;    // переводим в пиксели
         img.y = pos.y * 30;
         img.rotation = bodyList.GetAngle();
        }
}


GetAngle():Number Возвращает угол поворота тела в радианах.
GetAngularDamping():Number Возвращает значение углового торможения тела.
GetAngularVelocity():Number Возвращает угловую скорость тела.
GetDefinition():b2BodyDef Возвращает геометрические настройки тела.
GetLinearDamping():Number Возвращает значение линейного торможения тела.
GetLinearVelocity():b2Vec2 Возвращает линейную скорость тела.
GetPosition():b2Vec2 Возвращает позицию тела в мире.
GetType():uint Возвращает тип тела.
GetUserData():* Возвращает пользовательские данные записанные в свойство userData тела.

IsActive():Boolean Если тело в активном состоянии то возвращает true.
IsAwake():Boolean Если тело спит возвратит true.
IsBullet():Boolean Если тело использует технологию continuous collision detection возвратит true.
IsFixedRotation():Boolean Если телу запрещено поворачиваться возвратит true.
IsSleepingAllowed():Boolean Если телу разрешено спать возвратит true.

SetActive(flag:Boolean):void Устанавливает состояние активности тела.
SetAngle(angle:Number):void Устанавливает угол поворота тела в радианах.
SetAngularDamping(angularDamping:Number):void Устанавливает значение углового торможения тела.
SetAngularVelocity(omega:Number):void Устанавливает угловую скорость тела.
SetAwake(flag:Boolean):void Устанавливает состояние сна тела.
SetBullet(flag:Boolean):void Тело будет использовать технологию CCD для обнаружения столкновений.
SetFixedRotation(fixed:Boolean):void Запретит телу поворачиваться.
SetLinearDamping(linearDamping:Number):void Устанавливает значение линейного торможения тела.
SetLinearVelocity(v:b2Vec2):void Устанавливает линейную скорость тела.
SetPosition(position:b2Vec2):void Устанавливает позицию тела в мире.
SetPositionAndAngle(position:b2Vec2, angle:Number):void Устанавливает позицию тела в мире и его угол поворота (в радианах).
SetSleepingAllowed(flag:Boolean):void Запретим телу спать если установим в false
SetType(type:uint):void Устанавливает тип тела.
SetUserData(data:*):void Записывает пользовательские данные.

Итог:



Скачать исходник




Сообщение отредактировал vovnet - Четверг, 28 Июня 2012, 11:11
vovnetДата: Вторник, 26 Июня 2012, 20:29 | Сообщение # 22 | Тема: Box2D 2.1a Tutorial – Part 3 (World)
почетный гость
Сейчас нет на сайте

Предыдущий урок:
Part2
Box2D 2.1a Tutorial – Part 3 (World)


В этом уроке мы подробнее поговорим о мире Box2D.
Этот урок будет небольшим, по-большей части для закрепления материала и более полного представления о мире в Box2D.

Мир в Box2D является центральной частью движка — в нем создаются объекты, которые тут же и взаимодействуют друг с другом. Как и в реальном мире, мир Box2D имеет гравитацию. Итак, давайте рассмотрим создание объекта мира.

Для создания мира необходимо создать объект типа b2World в конструктор которого необходимо передать вектор гравитации и булево значение, которое разрешит (true) или запретит (false) телам засыпать. Рассмотрим эти параметры подробнее:

Вектор гравитации.

Его можно создать при помощи объекта типа b2Vec2, в конструктор которого необходимо передать два значения:
1. сила гравитации по оси Х;
2. сила гравитации по оси Y.

Code
var gravity:b2Vec2 = new b2Vec2(0, 10);

Хочу добавить, что необязательно создавать объект гравитации, можно просто воспользоваться статическим методом b2Vec2.Make().

Code
var gravity:b2Vec2 = b2Vec2.Make(0, 10);


Засыпание тел.
Мир постоянно моделирует поведение активных объектов, которые в нем находятся, а это использование ресурсов центрального процессора. Для того, чтобы сэкономить ресурсы компьютера, в Box2D реализована возможность «засыпания» объектов, то есть мир не обрабатывает объекты которые находятся в покое. Не рекомендуется отключать (false) засыпание тел.

Создание мира.

Code
var world:b2World = new b2World(gravity, true);

Таким образом мы создали мир.
Теперь необходимо запустить непрерывный цикл моделирования физики тел. Для этого в нашем мире предусмотрен метод Step(), который с каждым своим вызовом будет моделировать взаимодействие объектов в мире. А чтобы этот метод вызывался постоянно обычно используют событие ENTER_FRAME по которому и происходит отработка Step().

Пример:

Code
addEventListener(Event.ENTER_FRAME, update);

public function update(e:Event):void
{
      var timeStep:Number = 1 / 30;
      var velocityIterations:int = 6;
      var positionIterations:int = 2;
       
      _world.Step(timeStep, velocityIterations, positionIterations);
       
      // в версии 2.1 мы должны очистить силы
      _world.ClearForces();
      // отрисовываем
      world.DrawDebugData();
}


Теперь можем подробнее рассмотреть методы объекта b2World:

Step(dt:Number, velocityIterations:int, positionIterations:int) — моделирование физики в текущий момент.
Принимает следующие параметры:
- dt:Number – время необходимое для моделирования физики. Чем это значение меньше, тем быстрее будет идти жизнь в мире. Обычно в играх используют значение 1/60.
- velocityIterations:int – количество итераций для расчета столкновения тел. Чем больше значение, тем точнее просчитываются столкновения тел, но это сказывается на скорости работы приложения. Рекомендуемое значение 10.
- positionIteration:int – количество итераций для расчета позиции тел.

ClearForces():void - Вызовите после шага обновления мира World.Step(), чтобы очистить мир от действующих на него сил.
CreateBody(def:b2BodyDef):b2Body - Создает твердое тело.
DestroyBody(b:b2Body):void - Удаляет твердое тело.
GetBodyCount():int - Возвращает число тел в мире
GetBodyList():b2Body - Возвращает список тел находящихся в мире.
GetGravity():b2Vec2 - Возвращает вектор гравитации действующей в мире.
SetGravity(gravity:b2Vec2):void - Изменить гравитацию, действующую в мире.
SetWarmStarting(flag:Boolean):void - Включает/выключает теплый старт мира.

Это не все методы, которыми обладает мир, но пока что нам хватит и этого smile

Следующий урок:
Part 4




Сообщение отредактировал vovnet - Четверг, 28 Июня 2012, 11:01
vovnetДата: Вторник, 26 Июня 2012, 13:29 | Сообщение # 23 | Тема: Box2D 2.1a Tutorial – Part 2 (Body)
почетный гость
Сейчас нет на сайте

Box2D 2.1a Tutorial – Part 2 (Body)

Предыдущие уроки:
Part1

Итак, в прошлом уроке мы выяснили, что все тела в Box2D являются экземплярами класса b2Body, и создаются при помощи вспомогательных классов b2BodyDef, b2Shape и b2FixtureDef.
В этом уроке мы как раз и рассмотрим классы b2BodyDef, b2Shape, b2FixtureDef, их свойства и методы.

Для наших экспериментов возьмем код-заготовку из предыдущего урока:

Code
package
{
       import Box2D.Collision.b2Bound;
       import Box2D.Collision.b2DistanceInput;
       import Box2D.Dynamics.b2World;
       import Box2D.Common.Math.b2Vec2;
       import Box2D.Dynamics.b2BodyDef;
       import Box2D.Dynamics.b2Body;
       import Box2D.Collision.Shapes.b2PolygonShape;
       import Box2D.Dynamics.b2Fixture;
       import Box2D.Dynamics.b2FixtureDef;
       import Box2D.Dynamics.b2DebugDraw;
       import Box2D.Dynamics.Joints.b2MouseJoint;
       import flash.display.MovieClip;
       import flash.display.Sprite;
       import flash.events.Event;
       
    [SWF(width = "800", height = "600", backgroundColor="#fafed6", frameRate = "30")]
    public class Main extends MovieClip
    {
     private const PIXELS_TO_METRE:int = 30;    // коэффициент преобразования пикселей в метры
     private var _world:b2World;    // игровой мир
        
     public function Main()
     {
      // создаем мир
      _world = new b2World(new b2Vec2(0, 10), true);
         
/*
    *
    * Тут ваш код
    *
    *
    */      
      // отображаем все на экране
      var debugSprite:Sprite = new Sprite();
      addChild(debugSprite);
      var debugDraw:b2DebugDraw = new b2DebugDraw();
      debugDraw.SetSprite(debugSprite);
      debugDraw.SetDrawScale(PIXELS_TO_METRE);
      debugDraw.SetLineThickness(1.0);
      debugDraw.SetAlpha(1);
      debugDraw.SetFillAlpha(0.4);
      debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
      _world.SetDebugDraw(debugDraw);
         
      // добавляем слушателя
      addEventListener(Event.ENTER_FRAME, update);
     } // end Main()
        
     public function update(e:Event):void
     {
      var timeStep:Number = 1 / 30;
      var velocityIterations:int = 6;
      var positionIterations:int = 2;
         
      _world.Step(timeStep, velocityIterations, positionIterations);
         
      // в версии 2.1 мы должны очистить силы
      _world.ClearForces();
      // отрисовываем
      _world.DrawDebugData();
     } // end update()
    }
}


1. b2BodyDef — это геометрические свойства тел. Далее рассмотрим подробнее все свойства этого класса:

active:Boolean – определяет должно ли тело быть активным при старте. Если установить значение в false, то тело не будет реагировать на столкновения.

allowSleep:Boolean — установка значения этого свойства в false запретит объекту засыпать, когда оно находится в покое. Но это делать не рекомендуется в связи с большой нагрузкой на процессор.

angle:Number — начальный угол поворота тела в радианах.

angularDamping:Number — угловое торможение для снижения угловой скорости тела.

angularVelocity:Number — угловая скорость тела.

awake:Boolean — определяет бодрствует тело или спит при старте. Если установить false для динамического тела, то при запуске приложения это тело будет находится в состоянии покоя, даже будучи подвешенным в воздухе.

bullet:Boolean — устанавливается в true, если необходимо гарантировать, что это тело не пройдет насквозь другого тела.

linearDamping:Number — линейное торможение тела для снижения линейной скорости. Удобно использовать для имитации тела под водой, так как торможение в отличии от трения действует на тело не только в момент соприкосновения с другим телом, а постоянно.

linearVelocity:b2Vec2 — линейная скорость тела.

position:b2Vec2 — позиция тела в мире. Задается при помощь метода Set() принимающего координаты точки в которую подставится центр тела. Координаты относительно Х и Y задаются в метрах!

type:uint — тип тела. Может быть:

Cтатическим = 0 (или b2Body.b2_staticBody). Тело не реагирует при воздействии на него сил или других тел. Такие тела являются нерушимыми объектами.

Кинематическим = 1 (или b2Body.kinematicBody). Тело такое же как и статическое, но ему можно задать линейную и угловую скорость. Подходит для создания движущихся платформ, шестеренок и прочего.

Динамическим = 2 (или b2Body.b2_dynamicBody). Под эту категорию подпадают все остальные объекты, которые могут взаимодействовать между собой.

userData:* - здесь храним любые наши данные, например графическое отображение тела.

Итак, с геометрическими свойствами тела мы разобрались, так что теперь можем создать тело при помощи метода:
CreateBody(def:b2BodyDef):b2Body — метод объекта b2World, который принимает объект b2BodyDef и возвращает объект b2Body.

Приведу пример:

Code
var _world:b2World = new b2World(new b2Vec2(0, 10), true); // создаем мир
var body:b2Body; // в этой переменной будет хранится тело
var bodyDef:b2BodyDef = new b2BodyDef(); // создаем объект геометрических свойств тела
bodyDef.type = b2Body.b2_dynamicBody; // указываем, что тело будет динамическим
bodyDef.position.Set(8, 12); // задаем начальную позицию тела
body = _world.CreateBody(bodyDef);


При создании тела, ссылка на объект b2BodyDef не сохраняется, а значит мы можем использовать этот объект для создания множества тел.

2. b2Shape — форма тела. Даже после того, как мы описали геометрические свойства тела и добавили его в мир, мы его не увидим, т. к. у тела нет формы. А без формы тело не может взаимодействовать с другими телами, поэтому давайте опишем его форму.

Тело может иметь форму многоугольника b2PolygonShape или окружности b2CircleShape.

Создаем окружность:

Code
// Окружность
var circle:b2CircleShape = new b2CircleShape();
bodyDef.position.Set(3, 3);
circle.SetRadius(1);
body = _world.CreateBody(bodyDef);
fixtureDef.shape = circle;
body.CreateFixture(fixtureDef);


При создании формы мы можем в конструктор передавать радиус окружности (в метрах), или же ничего не передавать, тогда радиус будет по умолчанию равен нулю. В данном примере я так и поступил. Радиус я указал позже, вызвав у окружности метод SetRadius(), с помощью которого можно задать его. Здесь я использую некий объект fixtureDef, на который пока не обращайте внимание, позже мы рассмотрим и его.

Создаем многоугольник:

Code
// Многоугольник
var dynamicBox:b2PolygonShape = new b2PolygonShape();
dynamicBox.SetAsBox(1, 1);
fixtureDef.shape = dynamicBox;
body.CreateFixture(fixtureDef);


Тут мы создаем новый объект типа многоугольник и с помощью метода SetAsBox() задаем ширину и высоту тела.

3. b2FixtureDef — объект этого класса позволяет объединить тело с его формой, а также задать ему некоторые физические свойства.

Итак, мы научились создавать тела, добавлять их в мир, а также создавать для тел форму. Но в Box2D тело и форма разные объекты, и чтобы объединить их в одно целое необходимо воспользоваться классом b2FixtureDef. У объекта этого класса есть свойство shape которому необходимо присвоить объект формы. А после, у объекта тела вызвать метод CreateFixture() в который необходимо передать наш объект типа b2FixtureDef.

Code
// соединение тела и формы
var fixtureDef:b2FixtureDef  = new b2FixtureDef();
fixtureDef.shape = dynamicBox;
body.CreateFixture(fixtureDef);


Для наглядности я нарисовал небольшую схемку:

Мы начинаем с того, что создаем объект типа b2BodyDef, в котором описываем геометрические свойства тела.
Далее у объекта типа b2World вызываем метод CreateBody(), который и создаст в мире тело. Но так как тело будет бесформенное, необходимо создать объект формы. На картинке я просто обозначил форму как Shape, а в реальности требуется создавать форму как окружность, многоугольник, либо же совокупность и того и другого (об этом в следующих уроках).
После того как мы создали форму, нам необходимо прикрепить ее к нашему телу, которое находится в мире. Для этого мы создаем вспомогательный объект типа b2FixtureDef в свойствах которого указываем форму и другие физические свойства: трение, плотность, упругость.
Теперь у нас есть форма с физическими свойствами, которую необходимо «надеть» на тело. С этой целью у тела вызываем метод CreateFixture() в который и передаем объект b2FixtureDef.

Теперь мы разобрали достаточно, чтобы создавать простые тела. Для закрепления полученных знаний небольшое задание:
Отобразите принцип домино как на рисунке:



Скачать эту флэшку.

Следующий урок:
Part3




Сообщение отредактировал vovnet - Вторник, 26 Июня 2012, 20:30
vovnetДата: Понедельник, 25 Июня 2012, 17:34 | Сообщение # 24 | Тема: Box2D 2.1a Tutorial – Part 1 (Basic)
почетный гость
Сейчас нет на сайте
Quote (Anarchyst)
По-моему я это где-то на английском видел.

да, это с англоязычного блога.


vovnetДата: Понедельник, 25 Июня 2012, 15:40 | Сообщение # 25 | Тема: Box2D 2.1a Tutorial – Part 1 (Basic)
почетный гость
Сейчас нет на сайте

Всем привет, меня зовут Владимир.
С недавних пор решил изучить Box2D Flash версии 2.1а. Облазив множество сайтов, я по-крупинкам собирал информацию по движку, на некоторых из них были хорошие уроки, на других сжатые, на третьих заумные... В общем для систематизирования полученных знаний я набросал в word'e конспектик. И решил поделится знаниями, если уроки вас заинтересует - пишите, буду работать над остальными.

Box2D 2.1a Уроки – Часть 1 (Базовые знания)
Физические движки, вероятно, являются самыми привлекательными элементами игровых приложений. Они не только добавляют реалистичности, но также позволяют сделать вашу игру более интерактивной. Платформа Flash имеет множество физических движков, но я остановил свое внимание на Box2D 2.1a — пожалуй, самом мощном и функциональном физическом движке среди остальных.

Немного общей информации: Box2D является детищем Эрина Катто, который написал ее на С++. Но благодаря своей популярности, Box2D был портирован на множество других языков и ActionScript 3.0 не стал исключением. Первый порт был создан неким BorisTheBrave, который следил за обновлениями движка. С выходом версии 2.1 появился новый порт, созданный Джесси Штернбергом.

Тем не менее, на данный момент, я сосредоточу свое внимание на порте BorisTheBrave, который можно скачать отсюда .

Box2D может быть довольно пугающим для тех, кто только начинает свое знакомство с библиотекой в связи с его масштабами, поэтому я постараюсь немного облегчить уроки. Перед началом урока давайте убедимся, что вы знакомы со следующими определениями из руководства по Box2D:
Shape: 2D-форма геометрических объектов, таких как круг или многоугольник.
Rigit body: твердое тело — кусок материи, которая настолько сильна, что расстояние между двумя молекулами вещества всегда является постоянным. Тело твердое как алмаз.
Fixture: соединение — связывает форму тела и добавляет свойства материала, такие как плотность, трение и т.д.
World: мир физики представляет собой совокупность тел, соединений, которые взаимодействуют друг с другом. Box2D поддерживает несколько миров, но обычно в этом нет необходимости.

Конечным результатом этого урока будет такая флэшка:


Для визуального представления связи между классами я создал эту таблицу:


Итак, приступаем к кодингу:

1. Создание мира. Первым параметром является 2D-вектор, определяющий силу тяжести во всем мире. Второй параметр является логическим, который позволяет/запрещает физическим объектам засыпать. Это необходимо для оптимизации, чтобы движок без надобности не обрабатывал объекты, которые находятся в неподвижном состоянии.

Code
package
{
         import Box2D.Collision.b2Bound;
         import Box2D.Dynamics.b2World;
         import Box2D.Common.Math.b2Vec2;
         import Box2D.Dynamics.b2BodyDef;
         import Box2D.Dynamics.b2Body;
         import Box2D.Collision.Shapes.b2PolygonShape;
         import Box2D.Dynamics.b2Fixture;
         import Box2D.Dynamics.b2FixtureDef;
         import Box2D.Dynamics.b2DebugDraw;
         import flash.display.MovieClip;
         import flash.display.Sprite;
         import flash.events.Event;
         
         [SWF(width = "800", height = "600", backgroundColor="#fafed6", frameRate = "30")]

         public class Main extends MovieClip
         {
              private const PIXELS_TO_METRE:int = 30;
              private const SWF_HALF_WIDTH:int = 400;
              private const SWF_HEIGHT:int = 600;
              private var _world:b2World;
          
              public function Main()
              {
                   // создаем мир
                   _world = new b2World(new b2Vec2(0, 10), true);


b2World() конструктор.
public function b2World(gravity:b2Vec2, doSleep:Boolean)
Параметры:
gravity:b2Vec2 – вектор гравитации мира.
doSleep:Boolean — повысить производительность за счет исключения из моделирования неактивных объектов? (true — да).

B2Vec2() конструктор.
public function b2Vec2(x_:Number = 0, y_:Number = 0)
Параметры:
x_:Number (default = 0) - вектор по Х.
y_:Number (default = 0) - вектор по Y.

2. Создание бокса игрового мира. В Box2D единицы измерения в метрах. Поэтому мы указываем количество пикселей на метр (я выбрал 30, а вы можете использовать другую величину). Кроме того, координаты объекта относительно мира располагаются в центре этого объекта. Поэтому, чтобы наш бокс мира соответствовал ширине экрана, я разделил 800/2.

Code
// создаем свойства тела
var groundBodyDef:b2BodyDef = new b2BodyDef();
groundBodyDef.position.Set(SWF_HALF_WIDTH / PIXELS_TO_METRE,     
                    SWF_HEIGHT / PIXELS_TO_METRE-20 / PIXELS_TO_METRE);

b2BodyDef() конструктор.
public function b2BodyDef()
Этот конструктор устанавливает значения тела по умолчанию.

3. Здесь мы наблюдаем использование шаблона проектирования Factory, который служит для создания тела.

Code
// добавляем тело к миру
var groundBody:b2Body = _world.CreateBody(groundBodyDef);


4. Теперь мы создадим нашу форму (shape).

Code
// создаем форму (shape)
var groundBox:b2PolygonShape = new b2PolygonShape();
groundBox.SetAsBox(SWF_HALF_WIDTH / PIXELS_TO_METRE, 20 / PIXELS_TO_METRE);


5. При создании связи объекта с формой мы можем установить различные физические свойства.

Code
// устанавливаем свойства тела
var groundFixtureDef:b2FixtureDef = new b2FixtureDef();
groundFixtureDef.shape = groundBox; // форма
groundFixtureDef.density = 1;       // плотность
groundFixtureDef.friction = 1;      // трение
groundBody.CreateFixture(groundFixtureDef);


На этом шаге мы создаем объект и соединяем его с формой.

Code
// создаем динамическое тело
var bodyDef:b2BodyDef = new b2BodyDef();
bodyDef.type = b2Body.b2_dynamicBody;    // тело будет динамическим
bodyDef.position.Set(SWF_HALF_WIDTH / PIXELS_TO_METRE, 4);
var body:b2Body = _world.CreateBody(bodyDef);
           
var dynamicBox:b2PolygonShape = new b2PolygonShape();
dynamicBox.SetAsBox(1, 1);
           
var fixtureDef:b2FixtureDef = new b2FixtureDef();
fixtureDef.shape = dynamicBox;
fixtureDef.density = 1;
fixtureDef.friction = 0.3;
           
body.CreateFixture(fixtureDef);


6. Следующий фрагмент кода позволит нам отобразить наш мир на экране.

Code
// отображаем все на экране
var debugSprite:Sprite = new Sprite();
addChild(debugSprite);
var debugDraw:b2DebugDraw = new b2DebugDraw();
debugDraw.SetSprite(debugSprite);
debugDraw.SetDrawScale(PIXELS_TO_METRE);
debugDraw.SetLineThickness(1.0);
debugDraw.SetAlpha(1);
debugDraw.SetFillAlpha(0.4);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
_world.SetDebugDraw(debugDraw);


7. Теперь нам осталось только вдохнуть жизнь в наш мир и дать ему работать. Для этого воспользуемся слушателем ENTER_FRAME события.

Code
// добавляем слушателя
addEventListener(Event.ENTER_FRAME, update);


8. Для обновления мира мы будем вызывать функцию Step. Step принимает три параметра. Первый — шаг времени. В руководстве по Box2D рекомендуется использовать 1/60 секунды. Я считаю, что лучше всего установить его на частоту кадров flash-ролика, в данном случае 1/30. Второй и третий параметры пока что рассматривать не будем.

Code
public function update(e:Event):void
{
       var timeStep:Number = 1 / 30;
       var velocityIterations:int = 6;
       var positionIterations:int = 2;
           
       _world.Step(timeStep, velocityIterations, positionIterations);


9. В версии 2.1 мы должны очистить силы.

Code
_world.ClearForces();


10. Отображаем отладочные данные, которые мы устанавливали ранее.

Code
// отрисовываем
_world.DrawDebugData();


Скачать исходник с примером.

Следующие уроки:
Part2




Сообщение отредактировал vovnet - Среда, 27 Июня 2012, 14:16
vovnetДата: Среда, 20 Июня 2012, 22:07 | Сообщение # 26 | Тема: Продаётся онлайн игра Vk
почетный гость
Сейчас нет на сайте
дизайн игрухи стремный.

vovnetДата: Пятница, 01 Июня 2012, 22:06 | Сообщение # 27 | Тема: Пишем свою браузерную игру
почетный гость
Сейчас нет на сайте
даешь ООП

vovnetДата: Четверг, 31 Мая 2012, 17:37 | Сообщение # 28 | Тема: Обновленный курс "Создание браузерной ролевой игры"
почетный гость
Сейчас нет на сайте
11andriy11, 3DTutorial, в лс можно ссылку кинуть?!

vovnetДата: Четверг, 31 Мая 2012, 17:30 | Сообщение # 29 | Тема: Пишем свою браузерную игру. Урок 2
почетный гость
Сейчас нет на сайте
а еще лучше сразу бы писали с ООП!

vovnetДата: Четверг, 29 Декабря 2011, 12:32 | Сообщение # 30 | Тема: Помогите
почетный гость
Сейчас нет на сайте
скинь сам файл sql

vovnetДата: Понедельник, 26 Декабря 2011, 13:51 | Сообщение # 31 | Тема: Создание боя(в браузерке)
почетный гость
Сейчас нет на сайте
Книгу Колина Мука почитай - хорошо объясняет!

vovnetДата: Воскресенье, 11 Сентября 2011, 07:39 | Сообщение # 32 | Тема: Помощь в создание игры
почетный гость
Сейчас нет на сайте
смысл писать плагиат, никто играть в нее кроме тебя не будет

vovnetДата: Суббота, 03 Сентября 2011, 12:35 | Сообщение # 33 | Тема: Тип боя
почетный гость
Сейчас нет на сайте
Quote (Ищейка)
Просто не для каждого жанра может подойти бой.

если у тебя есть варианты - озвучивай, там разберемся))


vovnetДата: Суббота, 03 Сентября 2011, 11:01 | Сообщение # 34 | Тема: Тип боя
почетный гость
Сейчас нет на сайте
LunarPixel, хороший метод, но довольно долго придется отыгрывать бой))

vovnetДата: Суббота, 03 Сентября 2011, 10:20 | Сообщение # 35 | Тема: Тип боя
почетный гость
Сейчас нет на сайте
Quote (LunarPixel)
можно в качестве боевки использовать какую-нибудь мини игру, тут вариантов море.. я например делал для дипломного проекта многопользовательскую игру, и в качестве боевки использовал игру морской бой + доп. возможности в зависимости от уровня и умений персонажей.

а по-подробней, какие дополнительные возможности?


vovnetДата: Суббота, 03 Сентября 2011, 10:05 | Сообщение # 36 | Тема: Тип боя
почетный гость
Сейчас нет на сайте
Quote (Ищейка)
За смаил обиделся. И по ответы "пусть будет" я не смогу тебе помочь.

я не хотел тебя обидеть!
Просто пытаюсь объяснить, что мне важна сама система боя, а жанр не важен. Игры как таковой нет и хочу сделать просто наброски на локальном серваке.. если получится что-нибудь стоящее, тогда можно и поставить в инет.
Суть в том, что есть 2 юнита, которым нужно устроить поединок, а как он будет происходить и нужно придумать))




Сообщение отредактировал vovnet - Суббота, 03 Сентября 2011, 10:05
vovnetДата: Суббота, 03 Сентября 2011, 09:56 | Сообщение # 37 | Тема: Тип боя
почетный гость
Сейчас нет на сайте
wacko пусть будет фентези

vovnetДата: Суббота, 03 Сентября 2011, 09:43 | Сообщение # 38 | Тема: Тип боя
почетный гость
Сейчас нет на сайте
не важно о чем игра, сюжет любой может быть. меня интересует техническая сторона.
у игрока просто есть персонаж, которого он прокачивает выполняя квесты и дерется с ботами и другими игроками.
вот для таких вот разборок нужен бой, только оригинальный, а не как в других играх.


vovnetДата: Суббота, 03 Сентября 2011, 09:35 | Сообщение # 39 | Тема: Тип боя
почетный гость
Сейчас нет на сайте
Всем привет! Помогите определиться с типом боя для браузерки. В браузерных играх используют бои типа БК(блок - удар на javascript), или сделанные на флеше.. Если делать на флеше, то геморойно получается, тем более я не знаю actionScript, а делать по типу БК - избитая тема. Вот обращаюсь к вам, может у кого есть какая идея?!
Хочу что-бы были простые бои и не нужно было сильно заморачиваться игроку.. просто что-бы можно было отдохнуть пару часиков за любимой игрой.


vovnetДата: Воскресенье, 03 Июля 2011, 11:25 | Сообщение # 40 | Тема: Бесплатные видео курсы
почетный гость
Сейчас нет на сайте
Quote (maker-rus)
В первом уроке "Урок 1 - Ознакомление + Софт " после слов "mother fuck выброси его нахрен" у меня чуть-чуть не отвалилась челюсть.

гы biggrin ща посмотрю даже! ))


Форум игроделов » Записи участника » vovnet [98]
  • Страница 2 из 5
  • «
  • 1
  • 2
  • 3
  • 4
  • 5
  • »
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг