I am making a game using Andengine/Box2D physics addon. I experienced the random crashes due to the addition/movement/deletion of box2d bodies during the world step calculation, so I have implemented code to flag sprites/bodies for removal using the setUserData method - I attach a JSON object to each body and sprite that contains the type of sprite, the body, and the sprite itself and its delete status:
private JSONObject makeUserData(int type, Body body, Object sprite)
{
JSONObject myObject = new JSONObject();
try {
myObject.put("type", type);
myObject.put("sprite", sprite);
myObject.put("body", body);
myObject.put("deleteStatus", false);
} catch (JSONException e) {
Log.d(TAG,"Exception creating user data:"+e);
}
return myObject;
}
then in an update thread iterate through all the bodies in my world looking for these flags and delete the sprites/bodies with the flag. The bodies remove correctly, however the sprite removal seems to delete every instance of that particluar sprite rather than just removing the particular one i flagged to remove! I can tell the bodies are still present without the sprite as my player collides with invisible objects! Here is the code for removal:
private void removeObjectsSetForDestruction()
{
if(this.mPhysicsWorld!=null)
{
Iterator<Body> allMyBodies = this.mPhysicsWorld.getBodies();
boolean isDelete = false;
JSONObject currentBodyData;
while(allMyBodies.hasNext())
{
try {
currentBodyData = (JSONObject)allMyBodies.next().getUserData();
if(currentBodyData!=null)
{
isDelete = (Boolean) currentBodyData.get("deleteStatus");
if(isDelete)
{
destroyObstruction((Body) currentBodyData.get("body"));
}
}
} catch (JSONException e) {
Log.d(TAG,"Error getting world bodies data:"+e);
}
}
}
}
private void destroyObstruction(Body obstructionBody) throws JSONException
{
obstructionBody.setActive(false);
JSONObject secondBodyData = null;
if(obstructionBody.getUserData()!=null)
{
secondBodyData=(JSONObject) obstructionBody.getUserData();
//explodeObstruction(((IEnti开发者_JAVA技巧ty) secondBodyData.get("sprite")).getX(),((IEntity) secondBodyData.get("sprite")).getY());
if(secondBodyData.get("sprite") instanceof AnimatedSprite)
{
removeObject((AnimatedSprite) secondBodyData.get("sprite"));
}
else
{
removeObject((Sprite) secondBodyData.get("sprite"));
}
}
}
private void removeObject(final AnimatedSprite myAnimSprite)
{
final PhysicsConnector myPhysicsConnector = this.mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape(myAnimSprite);
this.mPhysicsWorld.unregisterPhysicsConnector(myPhysicsConnector);
this.mPhysicsWorld.destroyBody(myPhysicsConnector.getBody());
this.mScene.unregisterTouchArea(myAnimSprite);
this.mScene.detachChild(myAnimSprite);
System.gc();
}
private void removeObject(final Sprite mySprite)
{
final PhysicsConnector myPhysicsConnector = this.mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape(mySprite);
this.mPhysicsWorld.unregisterPhysicsConnector(myPhysicsConnector);
this.mPhysicsWorld.destroyBody(myPhysicsConnector.getBody());
this.mScene.unregisterTouchArea(mySprite);
this.mScene.detachChild(mySprite);
System.gc();
}
I would like to take a look at your objects creating code. I assume every sprite has the same TextureRegion
used, so when the region of one sprite is being changed - same regions on other sprites are being changed too due to Android architecture specifics. For every sprite with same TextureRegion
you should use textureRegion.clone()
as the last parameter of the constructor. Hope this helps.
精彩评论