Çarpışma meydana geldiğinde bir box2d gövdesi nasıl kaldırılır?


10

Java ve android programlamaya hala yeniyim ve çok fazla sorun yaşıyorum Çarpışma olduğunda bir nesneyi kaldırma. Web'e baktım ve çarpışma tespiti (kişi dinleyicisi) sırasında asla BOX2D gövdelerinin kaldırılmasıyla uğraşmamam gerektiğini buldum ve nesnelerimi bir arrayliste eklemeli ve silmek veya işlemek ve işlemek için gövdenin Kullanıcı Verileri bölümünde bir değişken ayarlamalıyım bir güncelleme işleyicisindeki kaldırma eylemi. Ben de bunu yaptım: İlk olarak biri ArrayLists'i biri yüzler diğeri de bedenler için tanımlıyorum:

ArrayList<Sprite> myFaces = new ArrayList<Sprite>();
ArrayList<Body> myBodies = new ArrayList<Body>();

Sonra bir yüz oluşturup bu yüzü vücuduna bağladığımda bunları ArrayList'lerine şöyle ekliyorum:

face = new AnimatedSprite(pX, pY, pWidth, pHeight, this.mBoxFaceTextureRegion);
Body BoxBody = PhysicsFactory.createBoxBody(mPhysicsWorld, face, BodyType.DynamicBody, objectFixtureDef);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face, BoxBody, true, true));

myFaces.add(face);
myBodies.add(BoxBody);

şimdi bir kişi dinleyicisi ve onloadscene'de böyle bir güncelleme işleyicisi ekliyorum:

this.mPhysicsWorld.setContactListener(new ContactListener() {
private AnimatedSprite face2;
@Override
public void beginContact(final Contact pContact) {
}
@Override
public void endContact(final Contact pContact) {
}
@Override
public void preSolve(Contact contact,Manifold oldManifold) {

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



scene.registerUpdateHandler(new IUpdateHandler() {


@Override
public void reset() { }

@Override
public void onUpdate(final float pSecondsElapsed) {

}
});

Planım, gövdenin kullanıcı verileri bölümündeki bir değişkeni kontrol ederek kişi dinleyicisinde hangi iki gövdenin çarpıştığını tespit etmek, sayılarını dizi listesine almak ve son olarak bu gövdeleri kaldırmak için güncelleme işleyicisini kullanmaktır.

Sorular: Arraylist'i doğru kullanıyor muyum? Kullanıcı Verilerine bir değişken nasıl eklenir (lütfen kod). Bu güncelleme işleyicisindeki bir gövdeyi kaldırmayı denedim, ancak yine de bana NullPointerException atıyor, bu yüzden bir güncelleme işleyicisi eklemenin doğru yolu nedir ve nereye eklemeliyim. Bunu yapmak için başka herhangi bir tavsiye harika olurdu. Şimdiden teşekkürler.

Yanıtlar:


7

JBox2d'de, doğru zamanda kaldırmak için:

public class Main
{
    World world;
    ...

    public void update() //your game loop
    {
        ... //do all actual update loop stuff, including detection of collision/death/destruction
        for (Entity entity : manager.entitiesToRemove)
        {
            world.destroyBody(entity.body); //this might be all you need -- adapt to your own purposes. but you will still need a list such that you remove only at the end of each tick.
        }

        manager.entitiesToRemove.clear();
    }
}

public class Entity
{
    Body body; //body representing this Entity
    EntityManager manager; //set ref via Entity constructor
    ...

    //Call from your contact listener when the entity expires
    //body.userData is set to the Entity representing that body
    //so you can get access to the Entity from the Body, as vice versa.
    public void die()
    {
        manager.removeEntity(this);
    }
    ...
}   

public class EntityManager
{
    public List<Entity> entities = new ArrayList<Entity>(); //extant entities
    public List<Entity> entitiesToAdd = new ArrayList<Entity>(); //forthcoming entities
    public List<Entity> entitiesToRemove = new ArrayList<Entity>(); //erstwhile entities <-- the important one for you.
    ...
    public void remove()
    {
        if (!stage.entitiesToRemove.contains(entity))
            stage.entitiesToRemove.add(entity);
            //or just use a Set<Entity>, as dual additions are implicitly prevented.
    }
    ...
    //also add(), and other utility functions for managing entities.
}   

Kullanım body.getUserData()ve body.setUserData()okuma ve yazma için userDataüzerinde Body.


1

Ben hafta önce benzer bir sorun var ama C ++ ve internet üzerinden çözüm bulmak! İşte Box2D dünya-> Adım sonra kullandığım yöntem kodu ve çalışıyor:

void physics::clean_up() {
std::vector<b2Body *> to_nuke;

b2Body * body = _world->GetBodyList();
for(; body; body = body->GetNext()) {
    gx::sprite * sprite = (gx::sprite *)body->GetUserData();
    if(sprite->is_killed()) {
        to_nuke.push_back(body);
    }
}

std::sort(to_nuke.begin(), to_nuke.end());
// destroying, but skip duplicates!
uint i = 0;
uint size = to_nuke.size();
while(i < size) {
    b2Body * b = to_nuke[i++];
    while(i < size && to_nuke[i] == b) {
        ++i;
    }
    _world->DestroyBody(b);
    b = 0;
}

Taşıma ile iyi şanslar ve iyi günler. Umarım bu yardım ile zaman kazanırsınız;)

edit: sprite-> is_killed () yöntemi sprite ve fiziksel gövdesinin kaldırılmaya hazır olup olmadığını kontrol eder.


1
-1, soru Java ile ilgilidir ve bu farklı dillerde oldukça farklı bir görevdir. Ayrıca çok iyi C ++ değil - bir std :: set veya std :: unordered_set kullanmayı deneyin ve yıkımı da ele almak için bir STL algoritması veya en azından daha iyi bir döngü koşulu kullanırım.

1

Bir eklemek istiyorsanız isDeadKullanıcı verilerinize bayrak eklemek istiyorsanız, bunu oluştururken kullanıcı verileriniz olarak belirlediğiniz her şeye ekleyin Body.

GameObject box = new GameObject(face, boxBody);
boxBody.setUserData(box);

Sonra endContact()ölü olarak ölmek istediğiniz bedenleri işaretleyin:

if( a collision happens ) {
    ((GameObject) bodyA.getUserData()).setDead(true);
    ((GameObject) bodyB.getUserData()).setDead(true);
}

Ardından içindeki ölü nesneleri çıkardığınızdan emin olun update(). PhysicsWorld güncellenirken bunu yapmayın:

foreach(GameObject go : gameObjects) {
    if(go.isDead()) {
         destroyGameObject(go);
         go.onDestroyed();
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.