在Box2D中获取世界的contactListener [英] Getting the world's contactListener in Box2D

查看:141
本文介绍了在Box2D中获取世界的contactListener的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用cocos2D和Box2D为Mac OS编写一个游戏。我添加了一个 b2ContactListener 子类到我的世界如下:

  contactListener = new ContactListener(); 
world-> SetContactListener(contactListener);

这是完美的,但我不确定最好的/接受的方式来访问联系人侦听器从其他目前没有直接引用联系人侦听器的类。



我知道我可以传递一个引用到需要它的其他类,但我想知道的是如果有更好的方法。更具体地说,虽然我不能找到一个方法来做到这一点,是否有一些等效的:

  world-> GetContactListener(); 

在Box2D?



我试图这样做是因为我宁愿移动一些游戏逻辑(即一个身体是否能够基于来自联系人侦听器的信息跳跃)到相关的类本身,而不是把所有的东西放在主游戏类。 / p>

谢谢!

解决方案

联系人侦听器仅作为入口点为四个函数BeginContact,EndContact,PreSolve和PostSolve。通常它没有成员变量,所以没有理由得到它,因为没有什么可以从它得到。



当一个世界步骤,你可以记下哪两个东西被触摸/停止触摸等,但你不应该立即改变世界上的任何东西,直到时间步骤完成。



我认为这个问题的关键是用来记录哪些事情被触动的方法,但这完全取决于你,取决于什么样的信息你需要。例如,如果你只对BeginContact感兴趣,那么绝对最简单的方法可能只是存储哪两个fixtures作为一对列表触摸:

  std :: vector< std :: pair< b2Fixture *,b2Fixture *> >东西

// in BeginContact
thingsThatTouched.push_back(make_pair(contact-> GetFixtureA(),contact-> GetFixtureB()));

//在时间步之后
for(int i = 0; i b2Fixture * fixtureA = thingsThatTouched [i]。第一;
b2Fixture * fixtureB = thingsThatTouched [i] .second;
// ... do something clever ...
}
thingsThatTouched.clear(); //重要!!

为了这个工作,你需要使联系监听器函数中的thingsThatTouched列表可见,它可以是一个全局变量,也可以在联系人监听器类中设置一个指针,也可以有一个全局函数返回指向该列表的指针。



如果您需要跟踪更多信息,例如停止触摸的事物,或者在时间步骤之后根据事情在受到影响时受到的影响等进行某些操作,则需要更多工作,变得更具体。您可能会发现这些教程非常有用:



这一个使用BeginContact / EndContact来更新一个主体触摸的其他东西的列表,并使用它来决定玩家是否可以在任何给定时间跳转:
http://www.iforce2d.net/b2dtut/jumpability



这种方法使用类似的方法来查看汽车轮胎下面的表面类型,以决定表面的摩擦力:
http://www.iforce2d.net/b2dtut/top-down-car



这是一个使用PreSolve来决定两个物体(箭头和目标)在碰撞时是否应该粘在一起,基于碰撞的速度。实际的粘在一起处理是在时间步骤完成后完成的:
http:// www.iforce2d.net/b2dtut/sticky-projectiles


I'm writing a game for Mac OS using cocos2D and Box2D. I've added a b2ContactListener subclass to my world as follows:

contactListener = new ContactListener();
world->SetContactListener(contactListener);

This works perfectly, but I am unsure of the best/accepted way to access the contact listener from other classes that don't currently have a direct reference to the contact listener.

I know I can pass a reference to other classes that need it, but what I was wondering is if there is a better way. More specifically, although I can't find a method to do this, is there some equivalent of this:

world->GetContactListener();

in Box2D?

The reason I am trying to do this is simply because I would prefer to move some game logic (i.e. whether a body is able to jump based on information from the contact listener) to the relevant classes themselves, rather than putting everything in the main gameplay class.

Thanks!

解决方案

A contact listener just serves as an entry point for the four functions BeginContact, EndContact, PreSolve and PostSolve. Typically it has no member variables, so there is no reason to get it, because there is nothing to get from it.

When one of these functions is called during a world Step, you can make a note of which two things touched/stopped touching etc, but you should not change anything in the world right away, until the time step is complete.

I think the crux of this question is the method used to 'make a note' of which things touched, but that's really up to you and depends on what kind of information you need. For example if you're only interested in BeginContact, then the absolute simplest way might be to just store which two fixtures touched as a list of pairs:

std::vector< std::pair<b2Fixture*, b2Fixture*> > thingsThatTouched;

//in BeginContact
thingsThatTouched.push_back( make_pair(contact->GetFixtureA(), contact->GetFixtureB()) );

//after the time step
for (int i = 0; i < thingsThatTouched.size(); i++) {
    b2Fixture* fixtureA = thingsThatTouched[i].first;
    b2Fixture* fixtureB = thingsThatTouched[i].second;
    // ... do something clever ...
}
thingsThatTouched.clear(); //important!!

For this to work you'll need to make the thingsThatTouched list visible from the contact listener function, so it could either be a global variable, or you could set a pointer to it in the contact listener class, or maybe have a global function that returns a pointer to the list.

If you need to keep track of more information such as what things stopped touching, or do something after the time step based on how hard things impacted when they touched etc, it will take a bit more work and becomes more specific. You might find these tutorials useful:

This one uses BeginContact/EndContact to update a list of which other things a body is touching, and uses it to decide if a player can jump at any given time: http://www.iforce2d.net/b2dtut/jumpability

This one uses a similar method to look at what type of surfaces are currently under a car tire, to decide how much friction the surface has: http://www.iforce2d.net/b2dtut/top-down-car

This one uses PreSolve to decide whether two bodies (arrow and target) should stick together when they collide, based on the speed of the impact. The actual 'sticking together' processing is done after the time step finishes: http://www.iforce2d.net/b2dtut/sticky-projectiles

这篇关于在Box2D中获取世界的contactListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆