Làm thế nào để loại bỏ một cơ thể box2d khi va chạm xảy ra?


10

Tôi vẫn chưa quen với lập trình java và Android và tôi gặp rất nhiều khó khăn khi xóa một đối tượng khi xảy ra va chạm. Tôi đã tìm kiếm trên web và thấy rằng tôi không bao giờ nên xử lý loại bỏ các bộ phận BOX2D trong khi phát hiện va chạm (trình nghe liên hệ) và tôi nên thêm các đối tượng của mình vào một danh sách mảng và đặt một biến trong phần Dữ liệu người dùng của cơ thể để xóa hoặc không xử lý hành động loại bỏ trong một trình xử lý cập nhật. Vì vậy, tôi đã làm điều này: Đầu tiên tôi xác định hai ArrayLists một cho các mặt và một cho các thân:

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

Sau đó, khi tôi tạo một khuôn mặt và kết nối khuôn mặt đó với cơ thể của nó, tôi thêm chúng vào ArrayLists của chúng như thế này:

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);

bây giờ tôi thêm một trình lắng nghe liên lạc và một trình xử lý cập nhật trong onloadscene như thế này:

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) {

}
});

Kế hoạch của tôi là phát hiện hai cơ quan nào va chạm vào bộ nghe tiếp xúc bằng cách kiểm tra một biến từ phần dữ liệu người dùng của cơ thể, lấy số của chúng trong danh sách mảng và cuối cùng sử dụng trình xử lý cập nhật để loại bỏ các bộ phận này.

Các câu hỏi là: Tôi có đang sử dụng danh sách mảng một cách chính xác không? Cách thêm một biến vào Dữ liệu người dùng (xin vui lòng mã). Tôi đã cố gắng loại bỏ phần thân trong trình xử lý cập nhật này nhưng nó vẫn ném cho tôi NullPulumException, vậy cách nào là đúng để thêm trình xử lý cập nhật và tôi nên thêm nó vào đâu. Bất kỳ lời khuyên nào khác để làm điều này sẽ là tuyệt vời. Cảm ơn trước.

Câu trả lời:


7

Trong JBox2d, để xóa vào đúng thời điểm:

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.
}   

Sử dụng body.getUserData()body.setUserData()để đọc và viết userDatatrên Body.


1

Tôi có vấn đề tương tự tuần trước nhưng trong C ++ và tôi tìm giải pháp qua internet! Đây là mã phương thức mà tôi đang sử dụng sau Box2D world-> Step và nó hoạt động:

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;
}

Chúc may mắn với porting và có một ngày tốt đẹp. Tôi hy vọng bạn sẽ tiết kiệm thời gian của bạn với sự giúp đỡ này;)

chỉnh sửa: phương thức sprite-> is_kiled () kiểm tra xem sprite và phần thân vật lý của nó đã sẵn sàng để loại bỏ chưa.


1
-1, câu hỏi liên quan đến Java và đây là một nhiệm vụ khá khác nhau trong các ngôn ngữ khác nhau. C ++ cũng không tốt lắm - hãy thử sử dụng std :: set hoặc std :: unordered_set và tôi sẽ sử dụng thuật toán STL để xử lý sự phá hủy, hoặc ít nhất là điều kiện vòng lặp tốt hơn.

1

Nếu bạn muốn thêm isDeadcờ vào dữ liệu người dùng của mình, chỉ cần thêm nó vào bất cứ thứ gì bạn đặt làm dữ liệu người dùng khi bạn tạo Body.

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

Sau đó, trong endContact()cờ các cơ thể bạn muốn chết như chết:

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

Sau đó hãy chắc chắn rằng bạn loại bỏ các đối tượng chết trong update(). Đừng làm điều này trong khi ChemistryWorld đang cập nhật:

foreach(GameObject go : gameObjects) {
    if(go.isDead()) {
         destroyGameObject(go);
         go.onDestroyed();
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.