
Новый nape. Testbed. И немного теории.
Новый nape:
1. Новый nape. Hello world
2. Новый nape. Обработка событий
3. Новый nape. Testbed. И немного теории. (Его вы сейчас читаете)
4. Новый nape. Создание тел, материалы, фильтрация столкновений
5. Новый nape. Соединение тел
6. Новый nape. Приложение сил к телам и raycast
Все примеры кода в Testbed: Скачать проект для FlashDevelop.
По хорошему этот пост должен был идти вторым, а не третьим. Когда я начал писать очередной пост про nape, я понял, что до сих пор изложение было довольно сумбурным и непоследовательным. Думаю, оно и дальше будет таким же, но все же предлагаю навести небольшой порядок, чтобы было легче двигаться дальше.
Cписки в nape
В nape вся физическая симуляция живет внутри экземпляра класса Space. Все тела, соединения, слушатели событий и все остальное работает только если добавлено в мир, т.е. в Space. У класса space несколько разных свойств, похожих по назначению — это списки, в которых перечислено все, что есть в мире:
Кроме того, например, геометрические фигуры Shape тоже живут внутри списка shapes, но это свойство класса Body, а не Space.
Все эти списки имеют похожие типы, отличающиеся только хранимыми объектами. К примеру, тела (Body) живут в BodyList, а геометрические фигуры (Shape) в ShapeList.
Добавление чего-либо в мир — это просто добавление этого чего-то в соответствующий список, а удаление — это удаление из соответствующего списка. Причем если мы удалим тело из списка dynamics, в котором хранятся все динамические тела, оно удалится и из списка bodies, в котором перечислены все тела вообще. Кроме того у тел, а также у других объектов живущих в классе Space, есть свойство space, присвоив ему значение мы автоматически добавим этот объект в соответствующий список, а присвоив этому свойству null — удалим его. У геометрических фигур (Shape) есть аналогичное свойство body. Таким образом получается, что добавление и удаление объектов можно делать так:
Перебрать все значение в списке тоже можно:
Оператор for each к сожалению не работает.
На практике мы уже использовали списки тел, списки слушателей событий и списки геометрических фигур тела. К сожалению, на сегодня всё.
Testbed
Пока я пробовал всякие разные штуки с целью написания этих постов, у меня как-то само-собой написалась некая обвязка, позволяющая запускать всякий разный код, не отвлекаясь на создание нового проекта, инициализацию и прочие скучные вещи. Скачать Nape Testbed.
Код простого теста:
Думаю, пояснять каждую строчку не нужно. Чтобы создать тест, нужно создать класс, унаследовав его от Test. В конструкторе можно создать всякие тела, метод update вызывается каждый кадр, метод createUI служит для создания всяких кнопочек и слайдеров (я использовал библиотеку MinimalComps.)
В этом тесте создается слайдер для количества тел, и каждый шаг, если количество не соответствует, создаются или удаляются тела. Кроме того создано тело superBody, и каждый шаг проверяется с какими телами оно соприкасается.
Результат: (Найдите с помощью кнопок Next и Prev тест с названием Test 0. Также предлагаю посмотреть на приблизительный аналог крана из Mining Truck 2 Антона Карлова — тест с названием Crane, очень мне в душу эти краны запали.)
1. Новый nape. Hello world
2. Новый nape. Обработка событий
3. Новый nape. Testbed. И немного теории. (Его вы сейчас читаете)
4. Новый nape. Создание тел, материалы, фильтрация столкновений
5. Новый nape. Соединение тел
6. Новый nape. Приложение сил к телам и raycast
Все примеры кода в Testbed: Скачать проект для FlashDevelop.
По хорошему этот пост должен был идти вторым, а не третьим. Когда я начал писать очередной пост про nape, я понял, что до сих пор изложение было довольно сумбурным и непоследовательным. Думаю, оно и дальше будет таким же, но все же предлагаю навести небольшой порядок, чтобы было легче двигаться дальше.
Cписки в nape
В nape вся физическая симуляция живет внутри экземпляра класса Space. Все тела, соединения, слушатели событий и все остальное работает только если добавлено в мир, т.е. в Space. У класса space несколько разных свойств, похожих по назначению — это списки, в которых перечислено все, что есть в мире:
- bodies — в этом списке присутствуют все тела.
- statics, dynamics, kinematics, liveBodies — в этих списках те же тела, что и в bodies, но только подходящие по смыслу к называнию списка, т.е. соответственно статические, динамические, кинематические (т.е. двигающиеся, но не по физике, а как вы захотите) и не спящие, активные тела.
- constraints — это список всех соединений тел.
- liveConstraints — это список не спящих соединений тел.
- arbiters — это список арбитров, т.е. объектов создающихся самим движком nape, в случае если тела соприкасаются. В nape есть три типа таких арбитров: столкновений, плавания и сенсорные. Добавлять и удалять записи из этого списка нельзя, это делает сам nape.
- callbacks — в этот список nape добавляет необработанные события. Я не рассматриваю этот метод обработки событий, т.к. использовать вызов функций при возникновении событий гораздо удобнее, а этот метод видимо просто достался в наследство от старого nape. Если им пользоваться, то после каждого шага надо проходить по этому списку обрабатывать события и очищать его.
- listeners — здесь список всех добавленных слушателей событий.
Кроме того, например, геометрические фигуры Shape тоже живут внутри списка shapes, но это свойство класса Body, а не Space.
Все эти списки имеют похожие типы, отличающиеся только хранимыми объектами. К примеру, тела (Body) живут в BodyList, а геометрические фигуры (Shape) в ShapeList.
Добавление чего-либо в мир — это просто добавление этого чего-то в соответствующий список, а удаление — это удаление из соответствующего списка. Причем если мы удалим тело из списка dynamics, в котором хранятся все динамические тела, оно удалится и из списка bodies, в котором перечислены все тела вообще. Кроме того у тел, а также у других объектов живущих в классе Space, есть свойство space, присвоив ему значение мы автоматически добавим этот объект в соответствующий список, а присвоив этому свойству null — удалим его. У геометрических фигур (Shape) есть аналогичное свойство body. Таким образом получается, что добавление и удаление объектов можно делать так:
space.bodies.add(body); // самый очевидный способ добавить тело
body.space = space; // тоже добавит тело
space.dynamics.add(body); // если тело динамическое, то оно добавится, иначе будет ошибка
space.bodies.remove(body); // удаление тела
body.space = null; // так тело тоже удалится
space.dynamics.at(0).space = null; // так к примеру удалится самое первое динамическое тело
Перебрать все значение в списке тоже можно:
for(var i:int = 0; i < space.bodies.length; ++i)
trace(space.bodies.at(i));
Оператор for each к сожалению не работает.
На практике мы уже использовали списки тел, списки слушателей событий и списки геометрических фигур тела. К сожалению, на сегодня всё.
Testbed
Пока я пробовал всякие разные штуки с целью написания этих постов, у меня как-то само-собой написалась некая обвязка, позволяющая запускать всякий разный код, не отвлекаясь на создание нового проекта, инициализацию и прочие скучные вещи. Скачать Nape Testbed.
Код простого теста:
package Tests
{
import com.bit101.components.*;
import nape.dynamics.*;
import nape.geom.*;
import nape.phys.*;
import nape.shape.*;
import nape.space.*;
import nape.util.*;
public class Test0 extends Test
{
private var bodyCount:HUISlider;
private var superBody:Body;
public function Test0()
{
super("Test #0");
createWalls(Material.steel());
superBody = new Body(BodyType.DYNAMIC, new Vec2(400, 300));
superBody.shapes.add(new Circle(70, null, Material.steel()));
superBody.align();
space.dynamics.add(superBody);
superBody.allowRotation = false;
}
override public function createUI(parent:VBox):void
{
bodyCount = new HUISlider(parent);
bodyCount.label = "bodies";
bodyCount.minimum = 0;
bodyCount.maximum = 300;
bodyCount.tick = 1;
bodyCount.value = 50;
}
override public function update():void
{
while (bodyCount.value + 1 > space.dynamics.length)
{
var b:Body = new Body(BodyType.DYNAMIC, new Vec2(Math.random() * 700 + 50, Math.random() * 500 + 50));
var s:Shape = new Polygon(Polygon.regular(Math.random() * 80 + 20, Math.random() * 80 + 20,
Math.round(Math.random() * 4 + 3), 0), Material.rubber());
s.body = b;
b.align();
b.space = space;
}
while (bodyCount.value + 1 < space.dynamics.length)
{
if(space.dynamics.at(0) != superBody)
space.dynamics.at(0).space = null;
else
space.dynamics.at(1).space = null;
}
var collidingBodies:String = "";
for (var i:int = 0; i < superBody.arbiters.length; ++i)
{
var arbiter:Arbiter = superBody.arbiters.at(i);
if (arbiter.isCollisionArbiter())
{
var another:Body = arbiter.body1 == superBody ? arbiter.body2 : arbiter.body1;
if (another.isDynamic())
{
collidingBodies += another.toString();
}
}
}
if (collidingBodies.length > 0)
trace(collidingBodies);
}
}
}
Думаю, пояснять каждую строчку не нужно. Чтобы создать тест, нужно создать класс, унаследовав его от Test. В конструкторе можно создать всякие тела, метод update вызывается каждый кадр, метод createUI служит для создания всяких кнопочек и слайдеров (я использовал библиотеку MinimalComps.)
В этом тесте создается слайдер для количества тел, и каждый шаг, если количество не соответствует, создаются или удаляются тела. Кроме того создано тело superBody, и каждый шаг проверяется с какими телами оно соприкасается.
Результат: (Найдите с помощью кнопок Next и Prev тест с названием Test 0. Также предлагаю посмотреть на приблизительный аналог крана из Mining Truck 2 Антона Карлова — тест с названием Crane, очень мне в душу эти краны запали.)
- +23
- romamik
Комментарии (11)
в testbed счетчика fps не хватает
правый верхний там? а то я уже начал в себе сомневаться :)
Как поправить не знаю, кроме как переделывать флешку на меньшую ширину.
dl.dropbox.com/u/11399208/NapeTestbed.swf