使用自定义事件来侦听碰撞



我对flash和编程很陌生,但我正在学习制作游戏。我目前正在忙于命中检测,这并不难在游戏中测试(从onEnterFrame发射)。

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

此外,这对cpu来说是好是坏,而不是在屏幕上测试许多敌人的碰撞?

干杯,Tyler

创建自定义事件:

首先,您可能想要创建自己的事件类来扩展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);
}

希望这能有所帮助。

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

答案是肯定的。。。"也许?"

首先要记住的是,像Flash中实现的事件系统是很重的。以下是发送事件时隐含发生的情况:

  1. 事件对象的实例化
  2. [N] 函数调用将该事件对象传递给[N]侦听器
  3. 如果使用事件冒泡遍历显示列表,则在显示列表的每个级别都会发生一个新的实例化(在考虑鼠标事件时,请记住,如mouse_MOVE、mouse_OVER、ROLL_OVER、mouse_OUT、ROLL_OUT等)

因此,如果您的系统设置为可能发生许多冲突并通知许多侦听器,那么您的更新循环中会发生许多函数调用和实例。太糟糕了。有多糟糕?我想在www.jacksondunstan.com上找到如何优化AS3的示例。他详细解释了当你执行动作X时,球员体内会发生什么,并为他的所有测试提供了一些好的基准。

不过,如果你不想阅读他的整个博客,那么所有这些实例化的问题在于,它们会生成大量短暂的垃圾,从而引发频繁的GC运行。在一场高性能的比赛中,如果可能的话,你需要避免这种情况。您可能希望避免的其他事情是字符串连接,或者作为副作用返回新对象实例的方便函数(例如localToGlobal)。

在这一点上,问题是"什么构成‘绩效密集型’"?

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

就我个人而言,我基本上放弃了Flash事件系统。当我需要通知对象事件时,我会直接这样做。在游戏的上下文中,我很少需要本地事件系统的开销。

相关内容

  • 没有找到相关文章

最新更新