जब टकराव होता है तो बॉक्स 2 डी बॉडी को कैसे निकालें?


10

मैं अभी भी जावा और एंड्रॉइड प्रोग्रामिंग के लिए नया हूं और टकराव होने पर किसी वस्तु को हटाने में मुझे बहुत परेशानी हो रही है। मैंने वेब के चारों ओर देखा और पाया कि मुझे टकराव का पता लगाने (एक संपर्क श्रोता) के दौरान BOX2D निकायों को हटाने का काम कभी नहीं करना चाहिए और मुझे अपनी वस्तुओं को एक सरणी सूची में जोड़ना चाहिए और हटाने या न संभालने के लिए शरीर के उपयोगकर्ता डेटा अनुभाग में एक चर सेट करना चाहिए। एक अद्यतन हैंडलर में हटाने की कार्रवाई। इसलिए मैंने ऐसा किया: पहले मैंने दो ArrayLists को एक चेहरे के लिए और एक शरीर के लिए परिभाषित किया:

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

फिर जब मैं एक चेहरा बनाता हूं और उस चेहरे को उसके शरीर से जोड़ता हूं तो मैं उन्हें इस तरह अपने ArrayLists में जोड़ता हूं:

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

अब मैं एक संपर्क श्रोता और एक अद्यतन हैंडलर को इस तरह से onloadscene में जोड़ता हूं:

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

}
});

मेरी योजना यह पता लगाने की है कि शरीर के उपयोगकर्ता डेटा अनुभाग से एक चर की जाँच करके संपर्क श्रोता में कौन से दो शरीर टकराए, सरणी सूची में अपने नंबर प्राप्त करें और अंत में इन निकायों को हटाने के लिए अपडेट हैंडलर का उपयोग करें।

प्रश्न हैं: क्या मैं सही ढंग से एंज़लिस्ट का उपयोग कर रहा हूँ? उपयोगकर्ता डेटा (कृपया कोड) में एक चर कैसे जोड़ें। मैंने इस अपडेट हैंडलर में एक निकाय को हटाने की कोशिश की, लेकिन यह अभी भी मुझे NullPointerException देता है, इसलिए अपडेट हैंडलर जोड़ने का सही तरीका क्या है और मुझे इसे कहां जोड़ना चाहिए। ऐसा करने के लिए कोई अन्य सलाह महान होगी। अग्रिम में धन्यवाद।

जवाबों:


7

JBox2d में, सही समय पर निकालने के लिए:

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

का प्रयोग करें body.getUserData()और body.setUserData()पढ़ना और लिखना userDataपर Body


1

मुझे हफ्ते भर पहले इसी तरह की समस्या है, लेकिन सी ++ में और मुझे इंटरनेट पर समाधान मिल गया है! यहाँ विधि कोड है जो मैं Box2D दुनिया के बाद उपयोग कर रहा हूँ-> चरण और यह काम करता है:

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

पोर्टिंग के साथ शुभकामनाएं और एक अच्छा दिन है। मुझे उम्मीद है कि आप इसकी मदद से अपना समय बचाएंगे;)

संपादित करें: विधि स्प्राइट-> is_killed () जांचें कि क्या स्प्राइट और उसका भौतिक शरीर निकालने के लिए तैयार है।


1
-1, सवाल जावा की चिंता करता है और यह एक ऐसा कार्य है जो विभिन्न भाषाओं में बहुत अलग है। यह बहुत अच्छा नहीं है C ++ - एक std :: set या std :: unordered_set का उपयोग करने का प्रयास करें, और मैं विनाश को संभालने के लिए एक STL एल्गोरिथ्म का उपयोग करूँगा, या कम से कम एक बेहतर लूप स्थिति।

1

यदि आप isDeadअपने उपयोगकर्ता डेटा में एक ध्वज जोड़ना चाहते हैं , तो बस इसे बनाएँ जो आप अपने उपयोगकर्ता डेटा के रूप में सेट करते हैं जब आप इसे बनाते हैं Body

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

फिर endContact()झंडों में आप जिन शवों को मरना चाहते हैं:

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

फिर सुनिश्चित करें कि आप मृत वस्तुओं को हटा दें update()। PhysicsWorld अपडेट करते समय ऐसा न करें:

foreach(GameObject go : gameObjects) {
    if(go.isDead()) {
         destroyGameObject(go);
         go.onDestroyed();
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.