Nape 2 — работа с PreListener

Как и обещал заметка по работе с таким типом слушателя как PreListener.
Механизм работы PreListener несколько отличается от своих собратьев. Вместе с этим слушателем можно использовать только один тип события — CbEvent.PRE (но вам не придется его задавать, так как он установлен в PreListener по-умолчанию)
Nape генерирует это событие в тот момент, когда было зафиксировано пересечение двух тел, но еще не был произведен никакой физический расчет. В этот вы можете игнорировать пересечение на этом этапе симуляции или игнорировать пересечении и на последующих этапах (именно пока пересекаются эти два тела), можете принять это пересечение только на этом шаге симуляции или принять пересечение и на всех последующих шагах (пока пересекаются эти два тела).

Обработчик этого слушателя принимает как параметр объект класса PreCallback и должен возвращать тип PreFlag.
PreFlag содержит четыре константы:
PreFlag.ACCEPT
PreFlag.ACCEPT_ONCE
PreFlag.IGNORE
PreFlag.IGNORE_ONCE

Возможно надо немного яснее объяснить смысл этих флагов.
Когда два тела пересекаются перед физ вычислениями вызывается обработчик слушателя PreListener. В нем можно вернуть значение PreFlag.IGNORE_ONCE, тогда пересечение будет игнорироваться (то есть никакие калькуляции проведены не будут) и тела будут дальше проникать друг в друга. На следующем шаге вызовется опять обработчик и если опять вернуть PreFlag.IGNORE_ONCE то опять будет тоже самое и так каждый шаг симуляции.
Разница между PreFlag.IGNORE и PreFlag.IGNORE_ONCE в том, что пока тела пересекаются если возвращать PreFlag.IGNORE_ONCE, то на следующий шаг симуляции этот обработчик снова вызовется, а если PreFlag.IGNORE то пока тела будут пересекаться обработчик больше не будет вызван.
Тоже самое с PreFlag.ACCEPT и PreFlag.ACCEPT_ONCE, только наоборот :) Столкновение будет принято и обработано, столкновение будет принято и обработано только один шаг симуляции.

Ну ладно немного кода. Подключим слушатель и обработчик:

_space.listeners.add(new PreListener(InteractionType.COLLISION, _cubeCBType, _platformCBType, preListenerHandler));
 
private function preListenerHandler(cb:PreCallback):PreFlag
{
	 return PreFlag.IGNORE;
}

Вот результат

Теперь пример простенького One way platform.

private function preListenerHandler(cb:PreCallback):PreFlag
{
    // Берем нормаль контакта
    var normal:Vec2 = cb.arbiter.collisionArbiter.normal;
 
    // Проверяем смотрит ли нормаль наверх и если да игнорируем столкновение
    // а если нет, принимаем
    if (normal.y < 0) 
    {
    	return PreFlag.IGNORE;
    }
    else
    {
        return PreFlag.ACCEPT;    
    }
}

This movie requires Flash Player 9

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

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

    Будут ли вызываться события
    CbEvent.BEGIN
    CbEvent.ONGOING
    CbEvent.END,
    если будет возвращаться PreFlag.IGNORE в PreListener?
    Другими словами: будет ли .IGNORE означать только НЕприложение сил к телам от их взаимодействия, а события взаимодействия всё равно будут?

  • VirtualMaestro

    Да, эти события будут вызваны. Возвращаемые флаги в PreListener никак не влияют на эти события.

  • XELAD

    Большое спасибо за статью!)

  • VirtualMaestro

    Пожалуйста))

  • Дмитрий

    Привет, может подскажешь если будет время и идея. У меня герой должен прыгать, но не должен действовать на динамические тела (типа слабенький чтоб двигать коробки и камни), но на них потом могут воздействовать другие силы. Можно ли как-то запретить герою двигать дела? Проблема в том что если задать маленькую density, то он перестает прыгать..

  • Дмитрий

    Пожалуйста не обращай внимание на предыдущий комент, я разобрался. Надо лишь подобрать density (причем менять на верхней и нижней части героя)

  • VirtualMaestro

    Не хотел отписывать пока сам не протестирую, но ты уже походу разобрался :) Там действительно только подбирая массы для героя и всего остального. А силу прыжка можно контролировать через скорость или через силу (если прыжок реализован через импульс).

  • LiuWong

    Доброго времени суток.

    Есть PreListener — для односторонних платформ. Также есть InteractionListener для события CbEvent.ONGOING — для обработки возможности прыгать игроку.

    Не в курсе как определить во втором событии что в первом мы отбросили контакт(второе событие вызывается в любом случае) ?