I do skateboarding with obstacles that you have to jump with box2D and AndEngine. I'm trying to make sure that when a player collides with an object, the object is deleted and the explosion is placed in the old position of the objects, however, something in the sprite removal code freezes my program, forcing it to end (not even forcibly closing the message, it just closes and goes to my home screen) and no error / exception information appears in logcat, so I have no idea what causes this! Here are some code snippets -
When I create sprites / borders, I attach a JSONObject to the body containing the sprite and the type of sprite, and attach a similar JSONOB to the sprite with the body and type:
private void constructPlayer(final float pX, final float pY) { final Body body; this.player = new AnimatedSprite(pX, pY, this.mSkaterTextureRegion); long[] frameDurations = {100, 100}; player.animate(frameDurations, 4, 5, true); body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, player, BodyType.DynamicBody, PLAYER_FIXTURE_DEF); this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(player, body, true, false)); body.setUserData(makeUserDataForBody(PLAYER_TYPE,player)); player.setUserData(makeUserDataForSprite(PLAYER_TYPE,body)); this.mScene.registerTouchArea(player);
My code for building sprite sprites is pretty much similar to the player design, but I set the speed for it:
private void addObstruction(final float pX, final float pY) { final Body body; final Sprite myObstruction; myObstruction = new Sprite(pX, pY, this.mCrateTextureRegion); body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, myObstruction, BodyType.DynamicBody, OBJECT_FIXTURE_DEF); this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(myObstruction, body, true, true)); body.setUserData(makeUserDataForBody(OBSTRUCTION_TYPE,myObstruction)); myObstruction.setUserData(makeUserDataForSprite(OBSTRUCTION_TYPE,body)); body.setLinearVelocity(-150f, 0);
Here is the contact for my physics world:
this.mPhysicsWorld.setContactListener(new ContactListener() { @Override public void preSolve(Contact contact, Manifold oldManifold) { } @Override public void postSolve(Contact contact, ContactImpulse impulse) { } @Override public void endContact(Contact contact) { // TODO Auto-generated method stub Body obj1Data = contact.getFixtureA().getBody(); Body obj2Data = contact.getFixtureB().getBody(); JSONObject obj1UserData; JSONObject obj2UserData; int obj1Type = 0; int obj2Type = 0; if(obj1Data.getUserData()!=null) { obj1UserData =(JSONObject) obj1Data.getUserData(); try { obj1Type = obj1UserData.getInt("type"); }catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(obj2Data.getUserData()!=null) { obj2UserData=(JSONObject) obj2Data.getUserData(); try { obj2Type = obj2UserData.getInt("type"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } switch (obj1Type) { case PLAYER_TYPE: break; case GRINDRAIL_TYPE: if(isGrinding) { endGrind(); if(!isJumping) fall(player); } break; case GROUND_TYPE: break; case OBSTRUCTION_TYPE: break; case WALL_TYPE: break; } switch (obj2Type) { case PLAYER_TYPE: break; case GRINDRAIL_TYPE: if(isGrinding) { endGrind(); if(!isJumping) fall(player); } break; case GROUND_TYPE: break; case OBSTRUCTION_TYPE: break; case WALL_TYPE: break; } } @Override public void beginContact(Contact contact) { Body obj1Data = contact.getFixtureA().getBody(); Body obj2Data = contact.getFixtureB().getBody(); JSONObject obj1UserData; JSONObject obj2UserData; int obj1Type = 0; int obj2Type = 0; if(obj1Data.getUserData()!=null) { obj1UserData =(JSONObject) obj1Data.getUserData(); try { obj1Type = obj1UserData.getInt("type"); }catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(obj2Data.getUserData()!=null) { obj2UserData=(JSONObject) obj2Data.getUserData(); try { obj2Type = obj2UserData.getInt("type"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //deal with things colliding with the player if(obj1Type==PLAYER_TYPE) { playerCollisionHandler(obj2Data); } else if(obj2Type==PLAYER_TYPE) { playerCollisionHandler(obj1Data); } } });
here is my playerCollisionHandler method:
private void playerCollisionHandler(Body secondBody) { JSONObject secondBodyData = null; if(secondBody.getUserData()!=null) { secondBodyData=(JSONObject) secondBody.getUserData(); } JSONObject userdata = (JSONObject) player.getUserData(); Body playerBody = null; try { playerBody = (Body) userdata.get("body"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } int objType = 0; try { if(secondBodyData!=null) objType = secondBodyData.getInt("type"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(objType == GROUND_TYPE) { if(playerBody.getLinearVelocity().y<0) { /* If the sprites y velocity is negative the sprite is jumping, * don't reset the values!!!*/ } else { if((isJumping)||(isFalling)) { //play landing sound AndEngineTestActivity.this.mLandSound.play(); isJumping = false; isFalling = false; //player.setPosition(player.getX(), GROUND_LEVEL-player.getHeight()); //animate landing player.animate(createFrameDurations(LAND_ANIM_FRAMES.length), LAND_ANIM_FRAMES, 0); } if(!rollSoundIsPlaying) { playRollSound(); } } } else if(objType == GRINDRAIL_TYPE) { Sprite grindRail=null; try { grindRail = (Sprite) secondBodyData.get("sprite"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } /*create a rectangle at the upper bound of the grind rail to test collision*/ grindRailUpperBound = new Rectangle(grindRail.getX(), grindRail.getY(), mGrindRailTextureRegion.getWidth(), COLLISION_BOUNDS_PIXEL_ACCURACY); playerLowerBound = new Rectangle(player.getX(), player.getY()+player.getHeight(), player.getWidth(), COLLISION_BOUNDS_PIXEL_ACCURACY); grindRailUpperBound.setColor(1.0f, 0f, 0f,1f); playerLowerBound.setColor(1.0f, 1.0f, 0f,1f); mScene.attachChild(playerLowerBound); mScene.attachChild(grindRailUpperBound); if(grindRailUpperBound.collidesWith(playerLowerBound)) { if(!isGrinding) { mScene.detachChild(grindRailUpperBound); mScene.detachChild(playerLowerBound); grindPlayer(player); } } if(!isGrinding) { /* if it reaches this point and the custom rectangle bounds did not collide * it means the player has collided with the grind rail another way, so we hurt the player*/ playerHitByObject(); destroyObstruction(secondBody); } } else if(objType == OBSTRUCTION_TYPE) { playerHitByObject(); destroyObstruction(secondBody); } }
and here is the destroyObtruction method, which seems to be the culprit of the crashes (if I comment on my destroyObstruction calls, my code works fine, but I'm not sure why this method causes the crash ...):
private void destroyObstruction(Body obstructionBody) { obstructionBody.setActive(false); try{ JSONObject secondBodyData = null; if(obstructionBody.getUserData()!=null) { secondBodyData=(JSONObject) obstructionBody.getUserData(); } explodeObstruction(((IEntity) secondBodyData.get("sprite")).getX(),((IEntity) secondBodyData.get("sprite")).getY()); final PhysicsConnector obstructionPhysicsConnector = this.mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape((IShape) secondBodyData.get("sprite")); this.mPhysicsWorld.unregisterPhysicsConnector(obstructionPhysicsConnector); this.mPhysicsWorld.destroyBody(obstructionPhysicsConnector.getBody()); //this.mPhysicsWorld.destroyBody(obstructionBody); this.mScene.detachChild((IEntity) secondBodyData.get("sprite")); }catch(Exception e) { Log.d(TAG, "Exception:"+e); } catch(Error e) { Log.d(TAG, "Error:"+e); } } private void explodeObstruction(float pX, float pY) { PointParticleEmitter obstructionExplosion = new PointParticleEmitter(pX, pY); ParticleSystem ExplosionParticleSystem = new ParticleSystem(obstructionExplosion, 45, 60, 60, this.mCrateParticleTextureRegion); ExplosionParticleSystem.addParticleInitializer(new AlphaInitializer(1f)); ExplosionParticleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE); ExplosionParticleSystem.addParticleInitializer(new VelocityInitializer(-175, 175, -175, 175)); ExplosionParticleSystem.addParticleInitializer(new RotationInitializer(0.0f, 360.0f)); ExplosionParticleSystem.addParticleInitializer(new RotationInitializer(0f, -20f)); ExplosionParticleSystem.addParticleModifier(new ScaleModifier(1.0f, 0.5f, 0, MAX_PARTICLE_LIFE/2)); ExplosionParticleSystem.addParticleModifier(new AlphaModifier(1, 0.35f, 0, MAX_PARTICLE_LIFE)); ExplosionParticleSystem.addParticleModifier(new ExpireModifier(MAX_PARTICLE_LIFE, MAX_PARTICLE_LIFE)); this.mScene.attachChild(ExplosionParticleSystem); }