一个我无法追踪的奇怪错误。我已经实现了一个ContactListener
类,用于在我的Android游戏中处理冲突。在beginContact(Contact arg0)
方法中,我可以看到arg0
中的两个实体在那里,并被推到堆栈上。在调用world.step()
之后,我立即运行自己的handleCollisions()
方法,在那里我弹出Contact
对象并执行一些游戏逻辑。然而,偶尔当我弹出Contact
时,它的一个或两个主体都为空。
Contact
在堆栈中的实体在那里,但它的实体为空。我不知道为什么会发生这种情况,更重要的是,我找不到这种情况是什么时候发生的。据我所知,我在其他地方的代码都没有删除尸体,但也可能有我不知道的副作用。这种情况并不总是发生,这也于事无补。通常,当发生多个碰撞时,就会发生这种情况。
有人知道怎样才能移走尸体吗?或者,有人知道追踪尸体的方法,以确定它们何时变为空吗?
以下是一些可能有帮助也可能没有帮助的代码:
public class ConcreteContactListener implements ContactListener
{
private Stack<Contact> contacts;
public ConcreteContactListener()
{
contacts = new Stack<Contact>();
}
@Override
public void beginContact(Contact arg0)
{
contacts.push(arg0);
System.out.println("push: " + arg0.m_fixtureA.m_body);
}
public int handleCollisions(ArrayList<Ball> balls, World world, ArrayList<Ball> smears, SoundEffects sfx, Combos combos)
{
int score = 0;
while (!contacts.isEmpty())
{
Contact contact = contacts.pop();
System.out.println("Contact: " + contact.m_fixtureA.m_body);
int a = -1;
int b = -1;
for (int i = 0; i < balls.size(); i++)
{
System.out.println("Ball: " + balls.get(i).getBody());
if (contact.m_fixtureA.m_body.equals(balls.get(i).getBody()))
a = i;
else if (contact.m_fixtureB.m_body.equals(balls.get(i).getBody()))
b = i;
}
...
}
}
联系人被合并并重复使用,所以我不建议使用这种方法。相反,我只会缓冲你需要的信息(可能是两个机构)。jbox2d测试台是这样处理的:
首先我们有一个联络点:
public class ContactPoint {
public Fixture fixtureA;
public Fixture fixtureB;
public final Vec2 normal = new Vec2();
public final Vec2 position = new Vec2();
public PointState state;
}
然后我们这样听:
public void beginContact(Contact contact) {
}
public void endContact(Contact contact) {
}
public void postSolve(Contact contact, ContactImpulse impulse) {
}
private final PointState[] state1 = new PointState[Settings.maxManifoldPoints];
private final PointState[] state2 = new PointState[Settings.maxManifoldPoints];
private final WorldManifold worldManifold = new WorldManifold();
public void preSolve(Contact contact, Manifold oldManifold) {
Manifold manifold = contact.getManifold();
if (manifold.pointCount == 0) {
return;
}
Fixture fixtureA = contact.getFixtureA();
Fixture fixtureB = contact.getFixtureB();
Collision.getPointStates(state1, state2, oldManifold, manifold);
contact.getWorldManifold(worldManifold);
for (int i = 0; i < manifold.pointCount
&& pointCount < MAX_CONTACT_POINTS; i++) {
ContactPoint cp = points[pointCount];
cp.fixtureA = fixtureA;
cp.fixtureB = fixtureB;
cp.position.set(worldManifold.points[i]);
cp.normal.set(worldManifold.normal);
cp.state = state2[i];
++pointCount;
}
}
对于您的目的来说,这可能有点过头了,因为它对每个联系人都执行这个逻辑。相反,您可以使用beginContact()
和endContact()
方法,并在游戏中缓冲一些更优化的东西,比如只存储碰撞的物体或其他东西。