Я занимаюсь скейтбордингом с препятствиями, через которые вам нужно прыгать, используя box2D и AndEngine. Я пытаюсь сделать так, чтобы, когда игрок сталкивался с объектом, объект удалялся и взрыв помещался в старое положение объектов, однако что-то в коде удаления спрайта замораживает мою программу, вызывая ее завершение (даже не Принудительное закрытие сообщения: оно просто закрывается и переходит к моему домашнему экрану), и в logcat не появляется информация об ошибках / исключениях, поэтому я понятия не имею, что ее вызывает! Вот некоторые фрагменты кода -
когда я создаю спрайты / границы, я присоединяю JSONObject к телу, содержащему спрайт и тип спрайта, и присоединяю аналогичный JSONOBject к спрайту с телом и типом:
/** method to construct our player (takes an x and y position)*/
private void constructPlayer(final float pX, final float pY) {
final Body body;
/* construct the sprite of our player and set the animation */
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);
//attach our player to the scene
this.mScene.attachChild(player);
}
private JSONObject makeUserDataForBody(int type, Object sprite)
{
JSONObject myObject = new JSONObject();
try {
myObject.put("type", type);
myObject.put("sprite", sprite);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return myObject;
}
private JSONObject makeUserDataForSprite(int type, Body body)
{
JSONObject myObject = new JSONObject();
try {
myObject.put("body", body);
myObject.put("type", type);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return myObject;
}
Мой код для построения спрайтов препятствий почти такой же, как и для создания игрока, но я установил скорость для его перемещения:
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);
//attach our Obstruction to the scene
this.mScene.attachChild(myObstruction);
}
Вот список контактов моего мира физики:
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);
}
}
});
вот мой метод playerCollisionHandler:
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);
}
}
и вот метод destroyObtruction, который, кажется, является виновником сбоев (если я закомментирую мои вызовы destroyObstruction, мой код работает нормально, но я не уверен, почему этот метод вызывает сбой ...):
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);
}