6

मैं एक साधारण एंडइंजिन गेम पर काम कर रहा हूं जिसमें एफएफ शामिल है। स्प्राइटएंड्रॉइड एंडइंजिन: कोलिशन डिटेक्शन को ठीक से संभालना

क) टैंक ख) सैनिकों ग) बम

मैं एक ऐसी ही सवाल यहाँ स्थित है:।।। Android AndEngine: Simple sprite collision

क्या खेल की तरह दिखता है:

enter image description here

हालांकि प्रारंभिक समस्या को ठीक करने पर, एक और समस्या उत्पन्न हुई:

जब बम (जहां विमान वर्तमान में चालू होता है और माउस क्लिक के माध्यम से लक्ष्य या मंजिल तक पहुंच जाता है तब तक लंबवत हो जाता है) एक सैनिक कहते हैं, सैनिक स्प्राइट को अलग करना चाहिए और इसके पीछे एक रक्त स्पैटर छोड़ना चाहिए 1 सेकंड के लिए स्प्राइट, साथ ही बम से एक विस्फोट स्प्राइट। हालांकि, गेम फोर्स इंडेक्सऑटबाउंडबॉर्टर देने से बंद हो जाता है। मैं समझता हूं कि यह शायद बम और उसके लक्ष्य के बीच स्प्राइट गिनती की एक विसंगति हो सकती है जिससे बाध्य सरणी त्रुटि हो सकती है, लेकिन logCat बिल्कुल मदद नहीं कर रहा है।

09-22 11:13:37.585: E/AndroidRuntime(735): FATAL EXCEPTION: UpdateThread 
09-22 11:13:37.585: E/AndroidRuntime(735): java.lang.IndexOutOfBoundsException: Invalid index 5, size is 5 
09-22 11:13:37.585: E/AndroidRuntime(735): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251) 
09-22 11:13:37.585: E/AndroidRuntime(735): at java.util.ArrayList.get(ArrayList.java:304) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.Entity.onManagedUpdate(Entity.java:1402) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.Entity.onUpdate(Entity.java:1167) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.Entity.onManagedUpdate(Entity.java:1402) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.scene.Scene.onManagedUpdate(Scene.java:284) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.entity.Entity.onUpdate(Entity.java:1167) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.engine.Engine.onUpdateScene(Engine.java:591) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.engine.Engine.onUpdate(Engine.java:586) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.engine.Engine.onTickUpdate(Engine.java:548) 
09-22 11:13:37.585: E/AndroidRuntime(735): at org.andengine.engine.Engine$UpdateThread.run(Engine.java:820) 

के रूप में यहाँ देखा, Logcat मेरे कोड पर एक त्रुटि दे रही है नहीं है, लेकिन AndEngine पर ही है, और है कि ज्यादातर शायद नहीं मामला है।

मेरा नया कोड है कि onCreateScene अद्यतन हैंडलर में (लिंक किए गए पिछले समस्या के साथ मदद के अनुसार इसके बाद के संस्करण) चलाता है:

protected void checkSoldierCollision() { 
    // TODO Auto-generated method stub 

    int numBombs = bombGroup.getChildCount(); 
    int numTroops = troopsGroup.getChildCount(); 
    final ArrayList<Sprite> toBeDetached = new ArrayList<Sprite>(); 
    for (int i = 0; i < numBombs; i++) { 
     Sprite s = (Sprite) bombGroup.getChildByIndex(i); 
     for (int j = 0; j < numTroops; j++) { 
      Sprite s2 = (Sprite) troopsGroup.getChildByIndex(j); 

      if (s.collidesWith(s2)) { 

       /*Sprite splat = createSplat(); 
       splat.setPosition(s.getX(), s.getY()); 
       getEngine().getScene().attachChild(splat);*/ 

       Sprite splode = createExplosion(); 
       splode.setPosition(s.getX(), s.getY()); 
       getEngine().getScene().attachChild(splode); 

       // WARNING: cannot detach from the list 
       //while looping through the list 
       toBeDetached.add(s); 
       toBeDetached.add(s2); 

      } 
     } 
    } 
    runOnUpdateThread(new Runnable() { 
     @Override 
     public void run() { 
      for (Sprite s : toBeDetached) { 
       s.detachSelf(); 
       Sprite splode = createExplosion(); 
       splode.setPosition(s.getX(), s.getY()); 
       getEngine().getScene().attachChild(splode); 

      } 
      toBeDetached.clear(); 
     } 
    }); 

} 

मैं क्या देखा है कि यह केवल या तो एक सूचक या इसके लिए एक विस्फोट नहीं किया जा सकता एक त्रुटि है। अगर दोनों विभाजन और विस्फोट टक्कर पर दृश्य को पॉप्युलेट करना था, तो एक त्रुटि होती है।

इसके अलावा

, भले ही बम न सैनिकों को मारा (लेकिन अभी भी अलग करने और एक विस्फोट बादल जब मंजिल से टकराने के साथ प्रतिस्थापित) यह भी एक समान त्रुटि देता है:

मेरे createBomb समारोह:

public Sprite createBomb(float x, float y) { 
    Sprite bombSprite = new Sprite(x, y, this.mBombTextureRegion, 
      getVertexBufferObjectManager()); 

    MoveYModifier downModBomb = new MoveYModifier(1, 60, FLOOR); 

    downModBomb.addModifierListener(new IModifierListener<IEntity>() { 

     @Override 
     public void onModifierStarted(IModifier<IEntity> pModifier, 
       IEntity pItem) { 

     } 

     @Override 
     public void onModifierFinished(IModifier<IEntity> pModifier, 
       final IEntity pItem) { 
      pItem.detachSelf(); 
      AnimatedSprite explodeSprite = createExplosion(); 
      explodeSprite.setPosition(pItem.getX(), FLOOR); 
      getEngine().getScene().attachChild(explodeSprite); 
     } 
    }); 

    bombSprite.registerEntityModifier(downModBomb); // register action 
    return bombSprite; 
} 

मेरे onCreateScene बम समारोह और टक्कर updateHandler:

scene.setOnSceneTouchListener(new IOnSceneTouchListener() { 

     @Override 
     public boolean onSceneTouchEvent(Scene pScene, 
       TouchEvent pSceneTouchEvent) { 
      if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) { 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         Sprite bomb = createBomb(f16Sprite.getX(), 
           f16Sprite.getY()); 
         bombGroup.attachChild(bomb); 
        } 
       }); 

       return true; 
      } 
      return false; 
     } 
    }); 

    // periodic checks 
    scene.registerUpdateHandler(new IUpdateHandler() { 

     @Override 
     public void onUpdate(float pSecondsElapsed) { 
      // checkTankCollision(); 
      // checkSoldierBackCollision(); 
      checkSoldierCollision(); 
     } 

     @Override 
     public void reset() { 
     } 
    }); 

मेरे createExplosion विधि:

  public AnimatedSprite createExplosion() { 
    AnimatedSprite boomSprite = new AnimatedSprite(0, 0, 
      this.mExplodeTextureRegion, getVertexBufferObjectManager()); 

    DelayModifier delay = new DelayModifier(.3f); // delay in seconds, can 
                // take float numbers .5 
                // seconds 
    delay.addModifierListener(new IModifierListener<IEntity>() { 

     @Override 
     public void onModifierStarted(IModifier<IEntity> pModifier, 
       IEntity pItem) { 
      ((AnimatedSprite) pItem).animate(new long[] { 100, 100, 100 }, // durations/frame 
        new int[] { 1, 2, 3 }, // which frames 
        true); // loop 
     } 

     @Override 
     public void onModifierFinished(IModifier<IEntity> pModifier, 
       final IEntity pItem) { 
      ((AnimatedSprite) pItem).detachSelf(); 
     } 
    }); 

    boomSprite.registerEntityModifier(delay); // register action 
    return boomSprite; 
} 

मैं इसका समाधान कैसे करूं? लूपिंग तर्क पूरी तरह से मेरा मजबूत बिंदु नहीं है। मैं वैकल्पिक रूप से इसे कार्यान्वित करने के तरीके पर भी खुला हूं।

अपडेट: बस एहसास हुआ कि टक्कर का नतीजा या तो विभाजन या विस्फोट होता है, इससे कोई फर्क नहीं पड़ता, अगर खिलाड़ी स्पैमिंग बम रखता है (जैसे 4-5 बार) पूरे गेम फोर्स बंद हो जाता है।

-ऐसा लगता है कि जब कोई सोल्डर/टैंक का उदाहरण बनाया जाता है तो बमबारी की एक स्वीकार्य संख्या होती है। जब भी एक बम एक सैनिक को मारता है तो मैंने पहले विस्फोट विस्फोट बंद कर दिया है (इसलिए रक्तपात सिर्फ दोनों के बजाय इसके स्थान पर ही रहेगा)। यह ठीक काम करता है, लेकिन 4-6 बम से अधिक है और खेल बंद हो जाता है। जब एक नया सैनिक उदाहरण स्पॉन करता है (जिसका अर्थ है कि जब पुराने लोग स्क्रीन से अलग हो जाते हैं और अलग हो जाते हैं) तो खिलाड़ी बल को बंद करने से पहले 4-6 बम दिए जाते हैं।

उत्तर

4

समस्या तथ्य यह है कि आप runOnUiThread फोन करके यूआई धागे पर बम देते हैं, लेकिन आप अद्यतन थ्रेड पर टकराव की जांच की वजह से हो सकता है। RunOnUpdateThread के अंदर बम जोड़ने का प्रयास करें।

आम तौर पर, आप चीजों में हेरफेर करने के लिए उपयोग किए जाने वाले धागे के बारे में लगातार रखना चाहते हैं, अन्यथा अजीब कीड़े उत्पन्न होती हैं जो डीबग करने के लिए दर्द होती हैं।

एक तरफ ध्यान दें पर:

runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     Toast.makeText(GameActivity.this, "Hello!", Toast.LENGTH_SHORT).show(); 
    } 
}); 
+0

है मैंने अपने टोस्ट टेस्ट किया है कोड (माउस क्लिक घटना के दौरान टोस्ट रखा)। ऐसा प्रतीत होता है कि मेरे पास हमेशा बम समूह का 1 बच्चा होता है, क्योंकि जब भी यह मंजिल पर जाता है तो यह अलग हो जाता है। मेरे पास सेना का 1 उदाहरण भी है। साथ ही, मुझे बताएं कि आप क्या सुझाव दे रहे हैं; कि मैंने अपने रनऑनअपडेट थ्रेड पर बम उड़ाया? लेकिन क्या नहीं है कि अलग-अलग होना भी चाहिए? – Erasmus

+0

हां, आप अपडेट थ्रेड पर चल रहे स्पॉन्गिंग कोड भी चाहते हैं। यूआई थ्रेड एक विधि को कॉल कर सकता है जो अद्यतन थ्रेड को तोड़ देगा। निम्नलिखित स्थिति पर विचार करें - अद्यतन थ्रेड दृश्य पर सभी बच्चों की सूची में कुछ करता है। इस ऑपरेशन में बहुत समय लगता है और बच्चों के माध्यम से चलने वाली विधि उसी तरह से अपना नंबर प्राप्त करती है जैसे आप करते हैं और इसे स्मृति में संग्रहीत करते हैं। मान लें कि सात बच्चे हैं। जबकि लूप इसकी बात करता है, यूआई थ्रेड की एक विधि पांच निकायों और बैंग को हटा देती है, अपडेट थ्रेड की लूप विधि सीमा से बाहर हो जाती है। – JohnEye

+0

मैंने यूआई थ्रेड (जब एस 2 के साथ टकराया जाता है) के दौरान बम को उछालने में सक्षम होने के लिए अपना कोड अपडेट किया, साथ ही साथ RunOnUpdate (प्रत्येक लूप के अंदर) में बम स्पॉन किया। यह अभी भी काम नहीं करता है।जैसा कि मैंने उल्लेख किया है, दोनों बम समूह और सैनिक समूह का आकार 1 – Erasmus

1

इसे डीबग करने के लिए, आपको आउटपुट (लॉग के माध्यम से) द्वारा मॉनिटर करने की आवश्यकता है, वास्तव में bombGroup और troopsGroup में कितने जोड़े गए थे, और यह कितना होना चाहिए इसके साथ संगत होना चाहिए। getChildCount() और आपके i और j पैरामीटर के मान को आउटपुट करने का भी प्रयास करें।

एक जंगली अनुमान के लिए, इस प्रयास करें:

for (int i = 0; i < toBeDetached.size(); i++) { 

    toBeDetached.get(i).detachSelf(); 

    } 
+0

एचएम, बस स्पष्ट करने के लिए, इस स्निपेट को अद्यतन थ्रेड में रखा गया है हां? यदि ऐसा है, तो मुझे प्रत्येक – Erasmus

+0

के बजाय लूप को लूप में परिवर्तित करना होगा, लेकिन आप प्रत्येक लूप के लिए उपयोग नहीं कर रहे हैं, प्रत्येक के लिए (स्प्राइट एस: बमग्रुप) – Shark

1

श्री JohnEye की मदद से ठीक है, मैं अपने कोड में इस समस्या को ठीक कर लिया है: यूआई धागा Toasts दिखाने के लिए बहुत अच्छा है, इस उदाहरण देखें। निम्नलिखित स्निपेट पर विचार करें:

protected void checkSoldierCollision() { 
    // TODO Auto-generated method stub 

    int numBombs = bombGroup.getChildCount(); 
    int numTroops = troopsGroup.getChildCount(); 
    final ArrayList<Sprite> toBeDetached = new ArrayList<Sprite>(); 
    for (int i = 0; i < numBombs; i++) { 
     Sprite s = (Sprite) bombGroup.getChildByIndex(i); 
     for (int j = 0; j < numTroops; j++) { 
      Sprite s2 = (Sprite) troopsGroup.getChildByIndex(j); 

      if (s.collidesWith(s2)) { 

       Sprite splat = createSplat(); 
       splat.setPosition(s.getX(), s.getY()); 
       getEngine().getScene().attachChild(splat); 

       Sprite splode = createExplosion(); 
       splode.setPosition(s.getX(), s.getY()); 
       explodeGroup.attachChild(splode); 
       // getEngine().getScene().attachChild(splode); 

       // WARNING: cannot detach from the list 
       // while looping through the list 
       toBeDetached.add(s); 
       toBeDetached.add(s2); 

      } 
     } 
    } 
    runOnUpdateThread(new Runnable() { 
     @Override 
     public void run() { 
      for (Sprite s : toBeDetached) { 
       s.detachSelf(); 
       Sprite splat = createSplat(); 
       splat.setPosition(s.getX(), s.getY()); 
       getEngine().getScene().attachChild(splat); 

       Sprite splode = createExplosion(); 
       splode.setPosition(s.getX(), s.getY()); 
       explodeGroup.attachChild(splode); 
       // getEngine().getScene().attachChild(splode); 

      } 
      toBeDetached.clear(); 
     } 
    }); 

} 

मैं उल्लेख किया है, खेल 2 टकराने वस्तुओं के बीच गिनती में एक विसंगति की वजह से दुर्घटनाओं। यह स्थिति तब होती है जब श्री जॉनएई बताते हैं, यूआई थ्रेड में एक स्प्राइट पैदा होता है, लेकिन अपडेट थ्रेड में भी नहीं। इसके अलावा, मेरी createExplosion, createBomb और createSplat कार्यों पर विचार करें:

बनाएँ बम

public Sprite createBomb(float x, float y) { 
    Sprite bombSprite = new Sprite(x, y, this.mBombTextureRegion, 
      getVertexBufferObjectManager()); 

    MoveYModifier downModBomb = new MoveYModifier(1, 60, FLOOR); 

    downModBomb.addModifierListener(new IModifierListener<IEntity>() { 

     @Override 
     public void onModifierStarted(IModifier<IEntity> pModifier, 
       IEntity pItem) { 

     } 

     @Override 
     public void onModifierFinished(IModifier<IEntity> pModifier, 
       final IEntity pItem) { 
      runOnUpdateThread(new Runnable() { 
       @Override 
       public void run() { 
        pItem.detachSelf(); 
       } 
      }); 
      AnimatedSprite explodeSprite = createExplosion(); 
      explodeSprite.setPosition(pItem.getX(), FLOOR); 
      explodeGroup.attachChild(explodeSprite); 
      // getEngine().getScene().attachChild(explodeGroup); 
     } 
    }); 
    bombSprite.registerEntityModifier(downModBomb); 
    return bombSprite; 
} 

बनाएँ विस्फोट

public AnimatedSprite createExplosion() { 
    AnimatedSprite boomSprite = new AnimatedSprite(0, 0, 
      this.mExplodeTextureRegion, getVertexBufferObjectManager()); 

    DelayModifier delay = new DelayModifier(.3f); // delay in seconds, can 
                // take float numbers .5 
                // seconds 
    delay.addModifierListener(new IModifierListener<IEntity>() { 

     @Override 
     public void onModifierStarted(IModifier<IEntity> pModifier, 
       IEntity pItem) { 
      ((AnimatedSprite) pItem).animate(new long[] { 100, 100, 100 }, // durations/frame 
        new int[] { 1, 2, 3 }, // which frames 
        true); // loop 
     } 

     @Override 
     public void onModifierFinished(IModifier<IEntity> pModifier, 
       final IEntity pItem) { 
      runOnUpdateThread(new Runnable() { 
       @Override 
       public void run() { 
        ((AnimatedSprite) pItem).detachSelf(); 
       } 
      }); 
     } 
    }); 

    boomSprite.registerEntityModifier(delay); // register action 
    return boomSprite; 
} 

बनाएं SPLAT

public Sprite createSplat() { 
    Sprite splatSprite = new Sprite(0, 0, this.mSplatTextureRegion, 
      getVertexBufferObjectManager()); 

    DelayModifier delay = new DelayModifier(.3f); // delay in seconds, can 
                // take float numbers .5 
                // seconds 
    delay.addModifierListener(new IModifierListener<IEntity>() { 

     @Override 
     public void onModifierStarted(IModifier<IEntity> pModifier, 
       IEntity pItem) { 

     } 

     @Override 
     public void onModifierFinished(IModifier<IEntity> pModifier, 
       final IEntity pItem) { 
      runOnUpdateThread(new Runnable() { 
       @Override 
       public void run() { 
        pItem.detachSelf(); 
       } 
      }); 
     } 
    }); 

    splatSprite.registerEntityModifier(delay); // register action 
    return splatSprite; 
} 

सूचना है कि उन सभी को अलग/उत्पन्न RunOnUpdate धागे में अन्य sprites। खेल मेरे पहले के रन-थ्रू में दुर्घटनाग्रस्त हो गया क्योंकि मैंने रनऑनअपडेट क्लास पर इन सभी sprites को अलग/उत्पन्न नहीं किया था।

+0

आप कहते हैं कि 'यूआई थ्रेड में एक स्प्राइट पैदा हुआ है, लेकिन अपडेट थ्रेड में भी नहीं। इसे दोनों पर उत्पन्न होने की जरूरत है। यह वास्तव में सही नहीं है, इसे केवल अद्यतन थ्रेड में ही किया जाना है। आप इसे बदलना चाहेंगे ताकि इस प्रश्न के लिए भविष्य के आगंतुकों को भ्रमित न किया जा सके। बीटीडब्लू, क्या आपने बकाया के बारे में अपना मन बदल दिया? – JohnEye

+0

ओह, पूरी तरह से भूल गए, यहां आप जॉनई जाते हैं! – Erasmus

+0

बहुत बहुत धन्यवाद, दोस्त! – JohnEye

संबंधित मुद्दे