使用自定义事件来侦听冲突?

时间:2012-02-13 00:12:58

标签: flash events event-handling collision

我是一般的flash和编程新手,但我正在学习制作游戏。我目前正在搞乱命中检测并且不难在游戏中测试(从onEnterFrame中解雇)。

我想知道的是,创建一个我可以收听的自定义事件是否可行/有用。并在发生碰撞时让eventListener听到。

对于cpu而言,这比测试屏幕上许多敌人的碰撞更好还是更糟?

干杯, 泰勒

2 个答案:

答案 0 :(得分:2)

创建自定义事件:

首先,您可能希望创建自己的事件类,以扩展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.
    }
}

ab之间发生冲突时,您将能够准备好发送事件实例并提供有关这两者的信息,例如:

// 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);
}

希望这有帮助。

答案 1 :(得分:0)

Marty Wallace为您提供了一个详尽的示例,说明如何为物理引擎实现自定义事件。现在,我将尝试权衡一下CPU是否值得应对的问题:

答案是确定的......“也许?”

要记住的第一件事是像Flash中实现的事件系统是重量级的。以下是调度事件时隐式发生的事情:

  1. 事件对象的实例化
  2. [N]函数调用将该事件对象传递给[N]个侦听器
  3. 如果使用事件冒泡来遍历显示列表,则在显示列表的每个级别都会出现一个新的实例化(在考虑鼠标事件时要记住,例如MOUSE_MOVE,MOUSE_OVER,ROLL_OVER,MOUSE_OUT,ROLL_OUT等)
  4. 因此,如果您的系统设置为可能发生许多冲突并通知许多侦听器,那么您在更新循环中会发生许多函数调用和许多实例化。那很糟。多么糟糕?我想指点www.jacksondunstan.com,了解如何优化AS3。他详细解释了当你执行动作X时玩家内部会发生什么,并为他的所有测试提供一些好的基准。

    如果您不想阅读他的整个博客,那么所有这些实例化的问题在于它们会产生大量短暂的垃圾,这会引起频繁的GC运行。你想在性能密集型游戏中尽可能避免这种情况。您可能想要避免的其他事情是字符串连接,或者将新对象实例作为副作用返回的便捷函数(例如localToGlobal)。

    那时,问题是“什么构成'表现密集型'”?

    这真的是你必须自己决定的事情。

    就我个人而言,我大多放弃了Flash事件系统。当我需要通知事件对象时,我会直接这样做。我很少需要在游戏环境中使用原生事件系统的开销。