2012-11-08 3 views
1

미리 도움을 청하십시오!Box2D 바디를 제거하면 AndEngine이 충돌합니다.

나는 Arkanoid/Breakout 스타일의 게임을 제작 중이며 신체 제거로 인해 몇 가지 문제가 발생합니다 (적어도이 문제가 의심되는 부분). 내가 게임을 실행할 때, 대부분의 시간은 잘 작동하지만, 때때로 게임이 충돌합니다. 이 충돌 중에는 시체에 부착 된 모든 스프라이트가 사라지고 시체가없는 스프라이트는 화면에 남습니다. LogCat 오류는 없지만 FPS에는 과감한 속도 저하가 있습니다. 또한 연락처 리스너의 코드가 실행되기 전에 연락처가 두 번 등록되는 경우가 있습니다 (아래 ContactListener에서 로그 파일 출력을 구현하는 곳을 볼 수 있음).

게임에서 벽돌 대신 볼트를 사용하고 있으며 볼트를 생성하는 데 사용한 코드는 아래에 나열되어 있습니다. 그런 다음, ContactListener를 사용하는 방법을 보여주고, 그 후에 body/sprite 조합을 제거하는 코드를 제공합니다. 어떤 도움이나 제안이라도 대단히 감사합니다!

감사합니다,

아담

들이 연락을 할 때 제거됩니다 몸/스프라이트 항목을 작성.

//BOLTS 
    final FixtureDef boltFixtureDef = PhysicsFactory.createFixtureDef(1, 1.0f, 0.1f); 
    final Body[] boltBody=new Body[BOLT_NUMBER]; 
    final Sprite[] boltSprite=new Sprite[BOLT_NUMBER]; 
    final PhysicsConnector[] facePhysicsConnector= new PhysicsConnector[BOLT_NUMBER]; 
    String[] bodyNames=new String[BOLT_NUMBER]; 

     for(int i=0; i<BOLT_NUMBER; i++){ 
      boltSprite[i] = new Sprite(-100,-100, sceneManager.mBolt, sceneManager.activity.getVertexBufferObjectManager()); 
      boltSprite[i].setCullingEnabled(true); 
      boltBody[i] = PhysicsFactory.createBoxBody(mPhysicsWorld, boltSprite[i], BodyType.KinematicBody, boltFixtureDef); 
      mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(boltSprite[i], boltBody[i], true, true)); 
      bodyNames[i]="bolt"+Integer.toString(i); 
      boltBody[i].setUserData(bodyNames[i]); 
      facePhysicsConnector[i] = mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape(boltSprite[i]); 
      boltBody[i].setTransform(xLocations[i]/PMR, yLocations[i]/PMR, 0);} 

      for(int i=0; i<BOLT_NUMBER; i++){  
       scene.attachChild(boltSprite[i]);} 

ContactListener : 여기

final ContactListener contact = new ContactListener(){ 

    @Override 
    public void postSolve(Contact contact, ContactImpulse impulse) { 

     String a = (String) contact.getFixtureA().getBody().getUserData(); 
     String b = (String) contact.getFixtureB().getBody().getUserData(); 
     if(a != null && b != null) { 
      for(int i=0; i<BOLT_NUMBER; i++){ 
       if(a.equals("wrench") && b.equals(facePhysicsConnector[i].getBody().getUserData()) || 
          a.equals(facePhysicsConnector[i].getBody().getUserData()) && b.equals("wrench")) { 
           //boltCollision[i]=true; 
        Log.i("contact","bolt contact" + i); 
           myDestroyer(facePhysicsConnector[i], true); 
           Log.i("contact","bolt POSTcontact" + i);} 

       else if((a.equals("wrench") && b.equals("paddle")) || 
         (a.equals("paddle") && b.equals("wrench"))) { 
        Log.i("contact","paddle contact"); 
         SpringNoise=true;} 

       else if((a.equals("wrench") && b.equals("door")) || 
         (a.equals("door") && b.equals("wrench"))) { 
        Log.i("contact","door contact"); 
          WoodNoise=true;} 
      }} 

    } 
    @Override 
    public void endContact(final Contact contact) {} 

    @Override 
    public void beginContact(Contact contact) {} 

    @Override 
    public void preSolve(Contact contact, Manifold oldManifold) {} 
     }; 

그리고 몸/스프라이트 콤보 제거 할 수있는 코드 :

private void myDestroyer(final PhysicsConnector facePhysicsConnector2, final Boolean bodyToo){ 
      if(killingInProcess == false){ 
        killingInProcess = true; 
        //final PhysicsConnector facePhysicsConnector2 = mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape(myShape); 
        sceneValue.engine.registerUpdateHandler(new IUpdateHandler(){ 
          @Override 
          public void onUpdate(float pSecondsElapsed) { 
           sceneValue.engine.unregisterUpdateHandler(this); 
           sceneValue.engine.runOnUpdateThread(new Runnable(){ 
                @Override 
                public void run() { 
                 Log.i("contact","removing bolt"); 
                  mPhysicsWorld.unregisterPhysicsConnector(facePhysicsConnector2); 
                  Vibrator v = (Vibrator) sceneValue.activity.getSystemService(Context.VIBRATOR_SERVICE); 
                  //myFixture.getBody().destroyFixture(myFixture); 
                if(bodyToo == true){ 
                    mPhysicsWorld.destroyBody(facePhysicsConnector2.getBody()); 
                } 
                facePhysicsConnector2.getShape().registerEntityModifier(new ParallelEntityModifier(new RotationModifier(3,180,0), 
                new ScaleModifier(3, 1, 0))); 
                sceneValue.mBlockSound.play(); 
                v.vibrate(75); 

                //mScene.detachChild(mySprite); 
                System.gc(); 
                killingInProcess = false; 
                } 
              }); 
          } 
          @Override 
          public void reset() { 
          } 
        });  
      }} 

답변

1

나는 충돌의 문제에 대한 확실하지 않다,하지만 내가 할 왜 시체를 제거하는 것이 너무 늦게 발생했는지 알 수 있습니다.

방법 postSolve은 UpdaeThread에서 호출 한입니다. 하지만 그곳에서 시체를 제거하는 대신 다른 업데이트 처리기를 등록합니다 (코드가 다음 게임 업데이트에서 실행 됨). 그리고이 코드에서 runOnUpdateThread에 또 다른 코드를 실행하여 다음 게임 업데이트에서 다시 실행합니다 (). 당신은 아무 이유없이 2 업데이트를 생략 :)이 문제를 만들 수 있습니다 (이것은 아마도 않습니다)

나는 당신이이 문제를 해결하는 것이 좋습니다,이 (이것은 심각하고 쉽게 해결 될 수 있음)

+0

제안에 감사드립니다! EndCollision()에서 logCat에 두 개의 충돌을 등록 했으므로 endCollision()에서 postSolve()로 모든 것을 이동했지만 postColision()에서는 하나만있었습니다. 이것이 왜 있는지 아십니까? 감사합니다 – user1809357

+0

여기서'ContactListener' 콜백에 대해 읽었습니다 : http://code.google.com/p/andenginephysicsbox2dextension/source/browse/src/com/badlogic/gdx/physics/box2d/ContactListener.java 필요가있는 것처럼 보입니다. 'beginContact'를 사용하십시오. – Jong

+0

감사합니다.하지만 불행히도 beginContact()를 사용하면 본문이 제대로 서로 바운스하지 않고 서로를 통해 실행됩니다. – user1809357

1

나는 '또 다른 문제를 찾아 확실하지는 않지만 문제는 스프라이트 제거에있을 수 있다고 생각합니다. 나는이 문제를 만났으므로 이제 update handler에서 body를 죽이려고한다. (update 메서드는 IUpdateHandler에서 onUpdate이다) :

   final PhysicsConnector physicsConnector = physicsWorld 
         .getPhysicsConnectorManager().findPhysicsConnectorByShape(
           body); 
       body.clearEntityModifiers(); 
       physicsWorld.unregisterPhysicsConnector(physicsConnector); 
       physicsWorld.destroyBody(physicsConnector.getBody()); 
       scene.detachChild(body); 
       activity.getEngine().unregisterUpdateHandler(this); 
관련 문제