Box2D AndEngine:在ContactListener中创建关节时应用程序挂起?

我在AndEngine中使用Box2D (适用于Android)。

我的目的是在两个物体相互碰撞时创建一个力关节。

当我尝试在ContactListner进程中创建两个对象(正文)之间的鼠标关节时 。 应用程序将挂起一段时间然后退出,没有任何错误,只是线程结束的通知。

当我在ContactListener之外调用mEnvironment.CreateForceJoint(..)时,联合创建是可以 – 当app在某些physics.UpdateHandler()中运行时。

请帮我解决问题,或找出原因。 谢谢你的帮助!

This is my code:

 public class MyActivity extends SimpleBaseGameActivity { private final String DEBUG_TAG = "MyActivity"; private GEnvironment mEnvironment; private PhysicsWorld mPhysicsWorld; private MyFixture FIXTURE_PLANET = GlobalSettings.FIXTURE_PLANET; private MyFixture FIXTURE_VACUUM = GlobalSettings.FIXTURE_VACUUM; // CODE TO CREATE RESOURCES and ENGINE OPTIONS.... @Override protected Scene onCreateScene() { Scene scene = new Scene(); scene.setBackground(new Background(0.8627f, 0.9020f, 1.0f)); //CODE: creating physic world //..... //creating game environment mEnvironment = new GEnvironment(mPhysicsWorld, scene, mEngine); //CODE: creating objects, register and attach them into scene GMediaPlanet sunZone = mEnvironment.CreatePlanet(x1, y1, sunTextureRegion, FIXTURE_PLANET); GMediaPlanet earthZone = mEnvironment.CreatePlanet(x2, y2, earthTextureRegion, FIXTURE_PLANET); // enable contact listener, detect collision between bodies mPhysicsWorld.setContactListener(new PlanetContactHandler()); return scene; } // ---------------------------------------------------- // Handling collision between letter cubes // ---------------------------------------------------- /** * Handling the collision of GMediaPlanets */ public class PlanetContactHandler implements ContactListener { private final String DEBUG_TAG = "CONTACT"; // if there's one collision, do not handle others or re-handle it private boolean mIsColliding = false; @Override public void beginContact(Contact contact) { if (mIsColliding) return; //----------------------------------------------- //suppose colliding objects to be sunZone and earthZone //----------------------------------------------- Object aTag = contact.getFixtureA().getBody().getUserData(); Object bTag = contact.getFixtureB().getBody().getUserData(); if (aTag != null && bTag != null) { GMediaPlanet box = null; GMediaPlanet cube = null; if (aTag instanceof GMediaPlanet && bTag instanceof GMediaPlanet) { box = (GMediaPlanet) aTag; cube = (GMediaPlanet) bTag; } if (box != null && cube != null) { //!!!!!!!----------------------------------------------------- //This code will HANG the app when called inside contact listner: MouseJoint mTestJoint = mEnvironment.CreateForceJoint(box, cube); //!!!!!!!----------------------------------------------------- Vector2 target = Vector2Pool.obtain(box.GetLocation()); mTestJoint.setTarget(target); Vector2Pool.recycle(target); } } mIsColliding = true; } @Override public void endContact(Contact contact) { Log.d(DEBUG_TAG, "end colliding!"); mIsColliding = false; } @Override public void preSolve(Contact contact, Manifold oldManifold) { } @Override public void postSolve(Contact contact, ContactImpulse impulse) { } } } public class GMediaPlanet { protected IAreaShape mSprite = null; protected Body mBody = null; public GMediaPlanet() { } public Vector2 GetLocation() { mBody.getPosition(); } }//end public class GEnvironment { private PhysicsWorld mWorld; private Scene mScene; private org.andengine.engine.Engine mEngine; public GEnvironment(PhysicsWorld pWorld, Scene pScene, org.andengine.engine.Engine pEngine) { mWorld = pWorld; mScene = pScene; mEngine = pEngine; } /** the constructor is hidden, available within Appearances packet only */ public GMediaPlanet CreatePlanet(float pX, float pY, ITextureRegion pTextureRegion, MyFixture pFixture) { GMediaPlanet entity = new GMediaPlanet(); entity.mSprite = new Sprite(pX, pY, pTextureRegion, mEngine.getVertexBufferObjectManager()); entity.mBody = PhysicsFactory.createCircleBody(mWorld, entity.mSprite, BodyType.DynamicBody, pFixture.GetDef(), GlobalSettings.PIXEL_2_METER); mScene.attachChild(entity.mSprite); entity.mSprite.setUserData(entity.mBody); entity.mBody.setUserData(entity); mWorld.registerPhysicsConnector(new PhysicsConnector(entity.mSprite, entity.mBody, true, true)); return entity; } // ----------------------------- // Creating JOINTS // ----------------------------- /** * Creating a force joit based on type of MouseJointDef * * @param anchorObj * the static object in the mTestJoint (anchor base) * @param movingObj * object to move forward the target */ public MouseJoint CreateForceJoint(GMediaPlanet anchorObj, GMediaPlanet movingObj) { ChangeFixture(movingObj, GlobalSettings.FIXTURE_VACUUM); MouseJointDef jointDef = new MouseJointDef(); jointDef.dampingRatio = GlobalSettings.MOUSE_JOINT_DAMP; jointDef.frequencyHz = GlobalSettings.MOUSE_JOINT_FREQ; jointDef.collideConnected = true; Vector2 initPoint = Vector2Pool.obtain(movingObj.mBody.getPosition()); jointDef.bodyA = anchorObj.mBody; jointDef.bodyB = movingObj.mBody; jointDef.maxForce = (GlobalSettings.MOUSE_JOINT_ACCELERATOR * movingObj.mBody.getMass()); // very important!!!, the initial target must be position of the sattelite jointDef.target.set(initPoint); MouseJoint joint = (MouseJoint) mWorld.createJoint(jointDef); Vector2Pool.recycle(initPoint); // very important!!!, the target of the joint then changed to target anchor object Vector2 targetPoint = Vector2Pool.obtain(anchorObj.mBody.getWorldCenter()); joint.setTarget(targetPoint); Vector2Pool.recycle(targetPoint); return joint; } public void ChangeFixture(GMediaPlanet entity, MyFixture pFixture) { Filter fil = new Filter(); fil.categoryBits = pFixture.categoryBit; fil.maskBits = pFixture.maskBits; if(entity.mBody != null) { entity.mBody.getFixtureList().get(0).setFilterData(fil); } } } 

你不能在Step()中调用世界 – 因为世界被锁定了! 你应该得到一个例外。 您必须记住哪些对象发生冲突并在beginContact之后执行操作…例如在更新函数中。