Используя пользовательское событие для прослушивания столкновений? - PullRequest
0 голосов
/ 13 февраля 2012

Я новичок во флеше и программировании в целом, но учусь делать игры. В настоящее время я возиться с обнаружением попаданий, и его нетрудно проверить в игровом тике (запущено с onEnterFrame)

Что мне интересно, так это если бы было возможно / полезно создать пользовательское событие, которое я могу слушать. И заставьте eventListener услышать, когда происходит столкновение.

Также было бы лучше или хуже для процессора, чем тестирование столкновений большого количества врагов на экране?

Ура, Тайлер

Ответы [ 2 ]

2 голосов
/ 13 февраля 2012

Создание пользовательского события:

Во-первых, вы, вероятно, захотите создать свой собственный класс событий, который будет расширяться Event.Это объясняется тем, что вы можете добавить свойства, которые вам, вероятно, понадобятся в функции прослушивания.

Ваше основное событие начнется с того, что будет выглядеть так:

public class PhysicsEvent extends Event
{
    public function PhysicsEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false)
    {
        super(type, bubbles, cancelable);
    }
}

ПервоеВозможно, вы захотите добавить к вашему событию некоторые константы, которые представляют тип события, которое вы собираетесь отправлять.В качестве примера вы можете добавить:

public static const COLLISION:String = "collision";

Это может представлять событие, которое происходит при обнаружении столкновения между двумя объектами.

Некоторая информация, к которой вы, возможно, захотите получить доступкогда произошло столкновение, это может включать двух участников столкновения и, возможно, некоторую числовую информацию, такую ​​как угол между участниками, а также расстояние.Вы также можете добавить их в свой пользовательский класс событий:

public var p1:GameEntity;
public var p2:GameEntity;
public var angle:Number;
public var distance:Number;

В целом ваш класс должен выглядеть следующим образом:

public class PhysicsEvent extends Event
{
    public static const COLLISION:String = "collision";

    public var p1:GameEntity;
    public var p2:GameEntity;
    public var angle:Number;
    public var distance:Number;

    public function PhysicsEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false)
    {
        super(type, bubbles, cancelable);
    }
}

Отправка события:

К сожалению, вам все равно нужно будет использовать Event.ENTER_FRAME, чтобы пройти по всем игровым объектам и проверить на столкновения, как вы делаете в настоящее время.Обычно вы должны иметь класс Physics или аналогичный, который содержит список всех ваших физических объектов и проверяет наличие столкновений между ними каждый раз, когда вы заканчиваете перемещать все свои игровые объекты.

Функция, которая оценивает возможные коллизии, может выглядеть примерно так:

for each(var a:PhysicsObject in physicsObjects)
{
    for each(var b:PhysicsObject in physicsObjects)
    {
        if(a == b) continue; // Prevent objects from colliding with themselves.

        // Check for a collision between a and b.
    }
}

Когда есть коллизия между a и b, вы сможете подготовиться к отправке экземпляра вашегособытие с информацией о них, например:

// Collision was detected, prepare an event for dispatch.
var evt:PhysicsEvent = new PhysicsEvent(PhysicsEvent.COLLISION);

Затем вам нужно будет назначить некоторую информацию для вашего события, прежде чем вы сможете отправить его:

evt.p1 = a;
evt.p2 = b;
evt.angle = <insert angle math. hint: Math.atan2>;
evt.distance = <insert distance math. hint: pythag>;

И, наконец, выможет отправить это событие:

dispatchEvent(evt);

Прослушивание:

Предполагая, что вы отправили свое событие из экземпляра класса, который имеет дело с физикой игры, вы можете прикрепитьслушатель события этого экземпляра.Это может выглядеть так:

physics.addEventListener(PhysicsEvent.COLLISION, onCollision);

Подготовьте функцию прослушивания:

function onCollision(e:PhysicsEvent):void
{
    // Todo.
}

И заполните эту функцию, чтобы делать все, что вам нужно делать с двумя сталкивающимися объектами:

function onCollision(e:PhysicsEvent):void
{
    // Push participants away from each other.
    e.p1.x -= Math.cos(e.angle) * (e.distance/2);
    e.p1.y -= Math.sin(e.angle) * (e.distance/2);
    e.p2.x += Math.cos(e.angle) * (e.distance/2);
    e.p2.y += Math.sin(e.angle) * (e.distance/2);
}

Надеюсь, это поможет.

0 голосов
/ 13 февраля 2012

Марти Уоллес дал вам исчерпывающий пример того, как вы можете реализовать пользовательские события для физического движка.Теперь я попытаюсь взвесить вопрос о том, стоит ли нагрузка на процессор:

Ответ однозначен ... «Может быть?»

Первое, что нужнопомните, что система событий, подобная той, что реализована во Flash, имеет большой вес.Вот что происходит неявно, когда отправляется событие:

  1. Создание экземпляра объекта события
  2. [N] вызывает функцию, передавая этот объект события [N] слушателям
  3. Если вы используете всплывающее окно событий для обхода списка отображения, то на каждом уровне списка отображения происходит новое создание экземпляров (полезно помнить при рассмотрении событий мыши, таких как MOUSE_MOVE, MOUSE_OVER, ROLL_OVER, MOUSE_OUT, ROLL_OUT и др.)

Итак, если ваша система настроена таким образом, что может произойти много коллизий и уведомить многих слушателей, тогда у вас будет много вызовов функций и много экземпляров, происходящих в вашем цикле обновления.Это плохо.Как плохо?Мне нравится указывать на www.jacksondunstan.com для примеров того, как оптимизировать AS3.Он подробно объясняет, что происходит внутри проигрывателя, когда вы выполняете действие X, и дает несколько хороших ориентиров для всех его тестов.

Если вам не хочется читать весь его блог, проблема со всеми этими примерамив том, что они будут генерировать много недолговечного мусора, который будет вызывать частые запуски GC.Вы хотите избежать этого, если это вообще возможно в игре с высокой производительностью.Другими вещами, которые вы можете избежать, могут быть конкатенация строк или вспомогательные функции, которые возвращают новые экземпляры объекта в качестве побочного эффекта (например, localToGlobal).

В этот момент вопрос заключается в том, «что представляет собойинтенсивный "?

Это действительно то, что вы должны определить для себя.

Лично я в основном отказался от системы событий Flash.Когда мне нужно будет уведомить объекты о событиях, я сделаю это напрямую.Мне редко нужны служебные данные родной системы событий в контексте игры.

...