Nape 2 — Фильтрация взаимодействий

Каждый шейп имеет свойство filter типа InteractionFilter. Это свойство дает возможность сказать Nape какие фигуры надо принимать во внимании при сталкивании, а какие нет. Работает это дело не основе битовых масок — для сталкиваемых шейпов задаются числа (наглядней всего в шестнадцатеричном виде). Если результат операции конъюнкции (или побитовый оператор & в AS3) над этими числами равен 1, значит шейпы будут сталкиваться, если 0 — нет.
В старом Nape именно так и было, в новом почти так, только немного сложнее (но зато дает больше возможностей).
Я не буду вдаваться с основы, потому рекомендую ознакомится с этой статьей. Там описана теоретическая часть, а также работа фильтрации в старой версии движка (старая версия легче для понимания).

В старой версии движка были два свойства для фильтрации — одно для коллизий (collisionGroup), второе для сенсорного слоя (sensorGroup).
В новой версии таких свойств 6 (класс InteractionFilter):

collisionGroup
collisionMask
sensorGroup
sensorMask
fluidGroup
fluidMask

Как видно из названий свойств, получается по два поля на столкновения, сенсор и для воды.
***Group — говорит о том к какой группе принадлежит данный шейп;
***Mask — говорит о том с какими другими группами шейп должен взаимодействовать;
(тут может ввести в заблуждение понятие группа, так как эта терминология пересекается с другой группой о которой мы поговорим позже, но так уж повелось…)) )
В коде это правило выглядит так:

(a.group & b.mask != 0) && (b.group & a.mask != 0)

То есть, если группа шейпа «a» и маска шейпа «b» через побитовый «И» не дает 0, а также группа шейпа «b» и маска шейпа «a» также не дает 0, тогда эти шейпы будут сталкиваться.

В старой версии Nape это выглядело так:

a.bitmask & b.bitmask != 0

Если вы хотите добиться старого поведения в новом Nape, надо просто и группу и маску установить в одно значение.

Обратите внимание на то что по-умолчанию collisionGroup установлен в 0×00000001, а collisionMask в 0xFFFFFFFF.
То есть маска установлена для столкновений со всеми группами, но группа не установлена для столкновений со всеми масками.

Далее небольшой пример.
Есть три объекта — квадрат, треугольник, гексагон. Треугольник сталкивается с квадратом и гексагоном, но гексагон не сталкивается с квадратом.
Для статической платформы я установил и collisionGroup и collisionMask в 0xFFFFFFFF, чтобы она сталкивалась со всеми группами и масками (ну кроме конечно 0×00000000).

private function init():void
{
	var bigBoxCollisionGroup:int = 0x000000001;
	var bigBoxCollisionMask:int =  0x000000001;
 
	var triangleCollisionGroup:int = 0x000000011;
	var triangleCollisionMask:int =  0x000000001;
 
	var hexagonCollisionGroup:int = 0x000000001;
	var hexagonCollisionMask:int =  0x000000010;
 
	//
	var bigBox:Body = new Body(BodyType.DYNAMIC, new Vec2(APP_WIDTH/2, APP_HEIGHT-150));
	var bigBoxSize:int = 100;
	bigBox.shapes.add(new Polygon(Polygon.box(bigBoxSize, bigBoxSize), new Material(0.5), new InteractionFilter(bigBoxCollisionGroup, bigBoxCollisionMask)));
	bigBox.space = _core.space();
 
	//
	var triangle:Body = new Body(BodyType.DYNAMIC, new Vec2(APP_WIDTH/2, APP_HEIGHT-300));
	var triangleSize:int = 30;
	var vertices:GeomPoly = new GeomPoly();
	vertices.push(new Vec2(-triangleSize, -triangleSize));
	vertices.push(new Vec2(triangleSize, -triangleSize));
	vertices.push(new Vec2(triangleSize, triangleSize));
	triangle.shapes.add(new Polygon(vertices, new Material(0.5), new InteractionFilter(triangleCollisionGroup, triangleCollisionMask)));
	triangle.align();
	triangle.space = _core.space();
 
	//
	var hexagon:Body = new Body(BodyType.DYNAMIC, new Vec2(APP_WIDTH/2, APP_HEIGHT-400));
	var hexagonSize:int = 50;
	hexagon.shapes.add(new Polygon(Polygon.regular(hexagonSize, hexagonSize, 6), new Material(0.5), new InteractionFilter(hexagonCollisionGroup, hexagonCollisionMask)));
	hexagon.space = _core.space();
 
 
	// Static platform
	var platform:Body = new Body(BodyType.STATIC, new Vec2(APP_WIDTH/2, APP_HEIGHT-50));
	var polygonShape:Polygon = new Polygon(Polygon.box(APP_WIDTH, 50), new Material(0.5), new InteractionFilter(0xFFFFFFFF, 0xFFFFFFFF));
	platform.shapes.add(polygonShape);
	platform.space = _core.space();
}

Исходный код

This movie requires Flash Player 9

Поделиться в соц. сетях

Опубликовать в LiveJournal
Опубликовать в Google Plus
  • Вова

    Прикольная статья.А можно ли как нибудь в новом Найпе узнать все действующие силы на тело(взаимодействие с объектами,гравитация) до того как они применялись к телу? Чтоб в последствий самому их применить

  • VirtualMaestro

    Не знаю, довольно таки специфичный вопрос. Немного порылся в документации ничего такого не нашел.
    Да и надобно не было никогда этого делать.
    Можно узнать разные типы импульсов, которые воздействовали на тело, суммарный импульс, точки контактов…
    Можно попробовать на форуме у Луки спросить.
    Если не секрет для чего это?

  • Вова

    Мне это нужно чтобы можно было сделать траекторию падения тела до начала его падения.

  • Вася

    Подскажите как полностью удалить body так что освободить память ??? Просто удаление со space недостаточно

  • VirtualMaestro

    Именно так и удаляется тело из space в нейп.
    А что касается освобождения памяти, так это та же задача, которая актуальна для экземпляров любых классов во флеш. Основные причины мусора в памяти не удаленные ссылки на объекты. Потому, надо самому менеджировать объекты, чтобы быть уверенным, что ни одна ссылка не ссылается на данный объект (чтобы ссылки были обнулены). Но даже в этом случае не гарантируется сбор мусора, так как сборщик сам решает когда нужно освободить память.

  • http://lalusto.de.tl Дима

    Сам сосуд был обнаружен в 2010 году, однако очистили его только сейчас. Во многих странах такой корм запрещен. Данные факторы поощряют интерес инвесторов к более рискованным вложениям, что отрицательно сказывается на состоянии доллара.