Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Actionscript 3 如何以干净、易于管理的方式跟踪所有Box2D碰撞?_Actionscript 3_Flash_Box2d_Collision Detection - Fatal编程技术网

Actionscript 3 如何以干净、易于管理的方式跟踪所有Box2D碰撞?

Actionscript 3 如何以干净、易于管理的方式跟踪所有Box2D碰撞?,actionscript-3,flash,box2d,collision-detection,Actionscript 3,Flash,Box2d,Collision Detection,我第一次在我正在开发的一款中型Flash游戏中认真使用Box2D。我目前使用Box2D的经验仅限于创建一个世界、多个实体,并以实用的方式将这些实体添加到世界中 我发现将Box2D集成到我的游戏环境中非常容易,维护编写良好的代码,并且已经完成了一些处理碰撞的教程。我现在面临的问题是,我的游戏将有许多身体,每个身体以不同的方式与其他身体交互,我发现很难编写自己的b2ContactListener子类而不让它变得非常混乱 根据我使用的教程,我创建了自己的子类b2ContactListener,并添加了

我第一次在我正在开发的一款中型Flash游戏中认真使用Box2D。我目前使用Box2D的经验仅限于创建一个世界、多个实体,并以实用的方式将这些实体添加到世界中

我发现将Box2D集成到我的游戏环境中非常容易,维护编写良好的代码,并且已经完成了一些处理碰撞的教程。我现在面临的问题是,我的游戏将有许多身体,每个身体以不同的方式与其他身体交互,我发现很难编写自己的
b2ContactListener
子类而不让它变得非常混乱

根据我使用的教程,我创建了自己的子类
b2ContactListener
,并添加了对
BeginContact()
方法的重写。调用
BeginContact()
时收到的参数将引用
b2Contact
的一个实例,通过该实例,我可以访问两个
b2Fixture
实例(发生冲突的两个实例)。然后,我可以访问与这些
b2Fixture
s关联的
b2Body
实例

  • 问题:目前,我有一种迂回的方法来找出哪两个东西发生了碰撞(即,它们是墙和导弹,还是播放器和树等等),它使用
    GetUserData()
    ,如下所示:

    var f1Player:Boolean = contact.GetFixtureA().GetBody().GetUserData() is Player
    var f2Player:Boolean = contact.GetFixtureB().GetBody().GetUserData() is Player
    var f1Tree:Boolean = contact.GetFixtureA().GetBody().GetUserData() is Tree
    var f2Tree:Boolean = contact.GetFixtureB().GetBody().GetUserData() is Tree
    // ... continutes with all possible combinations.
    
    
    // Example of managing a collision:
    if(f1Player && f2Tree)
    {
        // Player (FixtureA) and Tree (FixtureB)
    }
    
    if(f2Player && f1Tree)
    {
        // Player (FixtureB) and Tree (FixtureA)
    }
    
    正如你所看到的,这将是非常漫长和难以管理的。我还必须编写每一组要执行两次的操作,以满足特定元素FixtureA或FixtureB的需要,反之亦然(显然是以函数调用的形式,参数交换,而不是重新编写)

这显然不是正确的方法,但我无法找到更全面地解释冲突检测管理的资源


是否有人拥有使用Box2D进行碰撞检测管理的经验,可以与大家分享?此外,正在使用
SetUserData(拥有主体的实体)使用该方法的正确方法?

我使用了
c++
版本的
Box2d
,但我认为同样的方法也适用于actionscript。我创建了一个类
对象
,它包含一个
b2Body*\u body
指针和一个指向图形表示的指针
\u body
UserData
被设置为指向
对象*
。类
Object
具有以下方法:

virtual bool acceptsContacts    ();
virtual void onContactBegin     (const ContactData &data);
virtual void onContactEnded     (const ContactData &data);
virtual void onContactPreSolve  (const ContactData &data);
virtual void onContactPostSolve (const ContactData &data);
当在
b2ContactListener
子类中检测到碰撞时,它会检查碰撞的实体是否具有用户数据。如果是这样,它会将其用户数据投射到
对象*
,如果任何被碰撞的对象接受了contacts,它会创建
ContactData
(一个包含有关碰撞的所有必需信息的类),并将其放入其内部
列表
,以便稍后交付

当返回
b2World::update
方法时,
ContactListener
将所有联系人信息传递给要处理的对象。延迟交付是为了在处理碰撞时创建新的实体、关节等(执行更新时不允许这样做)


此外,如果在碰撞处理过程中删除了一个碰撞物体,您必须通知
ContactListener
(只需在
ContactData
中放置一个指向它的指针),这样它就可以使相应的接触失效,而不会传递它们

是的,这确实有点麻烦。事实上,我认为你的方式很典型

在测试夹具是否重叠时,fwiw Box2D本身必须处理类似的问题。有一系列函数,如b2CollideCircles、b2CollidePolygons、b2CollidePolygons等,当两个装置彼此靠近时,引擎会选择应使用这些函数中的哪一个

它将函数指针放在一个二维数组中,然后使用这两种形状类型作为索引来查找该数组中相应的函数。有关详细信息,请参见b2Contact.cpp中的前三个功能


当然,如果你不能在AS3中传递像这样的函数引用,那么我想这个答案不会有多大帮助,但我想我还是会发帖子,因为C/C++/JS用户可能会来。

我想出了比原来更好的东西

首先,我只是让我的
Being
类(它拥有一个
b2Body
)将自己设置为其body的
UserData
。此类还将包含一个
onContact()
方法,看起来类似于以下内容:

public class Being
{

    private var _body:b2Body;


    public function Being()
    {
        // Define the body here.
        // ...

        _body.SetUserData(this);
    }


    public function onCollision(being:Being = null):void
    {
        //
    }

}
然后,在我自己的
b2ContactListener
实现中,我只需将冲突
Being
(如果没有
Being
分配给冲突
b2Body
用户数据
)传递给对立的
Being
onCollision()

最后,在我的
Being
的每个子类中,我可以很容易地为某种类型的其他
Being
之间的冲突准备合适的逻辑:

class Zombie extends Being
{
    override public function onCollision(being:Being = null):void
    {
        if(being && being is Bullet)
        {
            // Damage this Zombie and remove the bullet.
            // ...
        }
    }
}

似乎长的“如果”语句被转移到了Being类中。对于只应为碰撞执行一次的处理,例如播放声音或增加分数如何。@如果orce2d是真的,我的意思是必须有
if()
语句来为每个碰撞组合添加条件,但这似乎比将所有内容都放在一个文件中更有条理。它使我能够通过相关类轻松定位两个事物之间的碰撞,而不必手动检查每次碰撞中哪个是哪个。至于单个事件,个人也可以通过简单的
hasbeintouch
boolean或类似的方式来管理。根据物品接触时发生的情况,你可能实际上需要一个列表而不是一个boolean,除非它只是可能的
class Zombie extends Being
{
    override public function onCollision(being:Being = null):void
    {
        if(being && being is Bullet)
        {
            // Damage this Zombie and remove the bullet.
            // ...
        }
    }
}