2012-03-19 15 views
9

पर दुश्मनों के द्रव्यमान को निर्देशित करते हुए मैं एक साधारण 2 डी गेम पर काम कर रहा हूं जहां कई दुश्मन लगातार पाइथन + पायगमेम में खिलाड़ी या खिलाड़ियों का पीछा करते हैं और पीछा करते हैं। एक समस्या जिसमें मैंने भाग लिया, और इस तरह के गेम को प्रोग्राम करने वाले कई लोगों ने भाग लिया है कि दुश्मन बहुत जल्दी से अभिसरण करते हैं। मैंने इस समस्या के साथ एक अस्थायी समाधान किया है जो किसी भी दो दुश्मनों को यादृच्छिक रूप से अलग करता है यदि वे एक दूसरे के बहुत करीब हैं। यह अच्छी तरह से काम करता है लेकिन ओ (एन^2) एल्गोरिदम के बारे में है जो हर फ्रेम चलाता है और उच्च दुश्मनों पर प्रोग्राम धीमा होने लगता है।एक बार

जब मेरा प्रोग्राम इस फ़ंक्शन के साथ चलता है तो दुश्मन गोल ऑब्जेक्ट बनाने के लिए प्रतीत होते हैं जिसे मैंने "क्लंप" नाम दिया है। क्लंप आमतौर पर ग्रहण प्रतीत होता है लेकिन वास्तव में अधिक जटिल (सममित नहीं) हो सकता है क्योंकि खिलाड़ी चलता है क्योंकि दुश्मनों को विभिन्न दिशाओं में खींचा जा रहा है। मैं इस तरह के संघर्ष के तरीके की तरह करता हूं, हालांकि मैं सोच रहा हूं कि इसकी गणना करने का एक और अधिक प्रभावी तरीका है या नहीं। वर्तमान में टक्कर में हर दुश्मन (अक्सर> 100) पहले खिलाड़ी की दिशा में स्थानांतरित हो जाता है, और फिर अलग हो जाता है। अगर वहां की आकृति की गणना करने का एक तरीका था जो क्लंप बनाता है, और यह कैसे चलता है तो यह बहुत अधिक गणना को बचाएगा।

मुझे बिल्कुल यकीन नहीं है कि समस्या से कैसे संपर्क करें। यह गणना करना संभव हो सकता है कि आंकड़े की सीमा कहां चलती है, और फिर यह सुनिश्चित करने के लिए इसका विस्तार करें कि क्षेत्र वही रहता है।

इसके अलावा मेरे दो कार्य वर्तमान में ले जाने के लिए इस्तेमाल किया जा रहा दुश्मनों:

def moveEnemy(enemy, player, speed): 
    a = player.left-enemy.left 
    b = player.top-enemy.top 
    r = speed/math.hypot(a,b) 
    return enemy.move(r*a, r*b) 

def clump(enemys): 
    for p in range(len(enemys)): 
     for q in range(len(enemys)-p-1): 
      a = enemys[p] 
      b = enemys[p+q+1] 
      if abs(a.left-b.left)+abs(a.top-b.top)<CLUMP: 
       xChange = (random.random()-.5)*CLUMP 
       yChange = ((CLUMP/2)**2-xChange**2)**.5 
       enemys[p] = enemys[p].move(int(xChange+.5), int(yChange + .5)) 
       enemys[p+q+1] = enemys[p+q+1].move(-int(xChange+.5),-int(yChange+.5)) 
    return enemys 

संपादित करें: कैसे पुंज लग रहा है के कुछ स्क्रीन शॉट्स: http://imageshack.us/photo/my-images/651/elip.png/ http://imageshack.us/photo/my-images/ 832/newfni.png/

http://imageshack.us/photo/my-images/836/gamewk.png/

पुंज वर्तमान मुद्दों, ज्यादातर एक गोल वस्तु सिर्फ फैला (ग्रहण की तरह है, लेकिन कई दिशाओं में फैला हो सकता है) हो रहा है लेकिन यह आयताकार दुश्मनों के कारण सीधे किनारों की किनारों पर है।

+0

सीमा के लिए कोड के बारे में कैसे? क्या वह दूरी की जांच कर रहा है? यह बड़ी संख्या में इकाइयों के लिए बहुत महंगा हो सकता है। –

+3

इसके अलावा, यह हर फ्रेम को न करें बल्कि प्रत्येक एक्स फ्रेम करें। मैंने इसी समस्या को इसी तरह हल किया, हालांकि मैंने कुछ ओवरलैप की अनुमति दी। यह बड़े पैमाने पर झुंड को और अधिक खतरनाक लग रहा है! –

+1

आपके द्वारा यहां दिए गए उत्तरों की गुणवत्ता के आधार पर, आप http://gamedev.stackexchange.com/ पर यह पूछने का प्रयास भी कर सकते हैं। –

उत्तर

6

आपके गेम के आधार पर इसके बारे में जाने के कई तरीके हैं। प्रदर्शन में सुधार के लिए कुछ विचार यहां दिए गए हैं:

  1. कुछ ओवरलैप के लिए अनुमति दें।
  2. फ़्रेम की निश्चित संख्या के बाद अपनी दूरी की जांच को कम करें।
  3. अपनी दूरी जांच फ़ॉर्मूला में सुधार करें। यदि आप मानक दूरी सूत्र का उपयोग कर रहे हैं, तो इसे कई तरीकों से अनुकूलित किया जा सकता है। एक के लिए, वर्ग रूट से छुटकारा पाएं। प्रेसिजन कोई फर्क नहीं पड़ता, केवल सापेक्ष दूरी।
  4. प्रत्येक इकाई पास की इकाइयों की सूची का ट्रैक रख सकती है। केवल उस सूची में इकाइयों के बीच अपनी गणना करें। हर बार, सभी इकाइयों के खिलाफ जांच करके उस सूची को अद्यतन करें।
  5. आपका गेम कैसे सेट अप किया जाता है, इस पर निर्भर करते हुए, आप क्षेत्र को क्षेत्रों में विभाजित कर सकते हैं, जैसे क्वाड्रंट या सेल। इकाइयों को केवल उस सेल में अन्य इकाइयों के खिलाफ परीक्षण किया जाता है।

संपादित करें: जब इकाइयों को अपने लक्ष्य के करीब है, यह ठीक से कार्य न हो सकता है। मैं उन्हें दूर से सटीक लक्ष्य पर घर रखने के बजाए सुझाव दूंगा, कि वे वास्तव में एक यादृच्छिक पास के लक्ष्य की तलाश करते हैं। अपने असली लक्ष्य से ऑफसेट की तरह।

मुझे यकीन है कि इसे सुधारने के कई अन्य तरीके हैं, यह सब के बाद काफी खुला है। मुझे Boids और flocking भी इंगित करना चाहिए जो ब्याज का हो सकता है।

+0

आपकी सलाह के जवाब में प्रतिक्रिया के लिए धन्यवाद: 1. पहले से ही कुछ ओवरलैप की अनुमति है क्योंकि जब दुश्मन 5 इकाइयां अलग होते हैं तो वे वास्तव में ओवरलैप होते हैं क्योंकि वे 24 वर्ग 24 होते हैं। 2. एक अच्छा विकल्प लेकिन फिर दूरी को स्थानांतरित करने के लिए दूरी को बड़ा होना चाहिए, लेकिन फिर दुश्मन चारों ओर कूदते प्रतीत होते हैं। 3. बिंदु ले लिया मैं वर्ग रूट ले जाएगा। 4. एक अच्छा विकल्प लगता है। 5. मैं इसे आज़मा सकता हूं लेकिन मुझे लगता है कि मुझे केवल 4 या 5 की आवश्यकता होगी। मैं वास्तव में क्या देख रहा हूं (यदि संभव हो) एक बार में पूरे "क्लंप" की गणना करने का एक तरीका है। – enderx1x

+0

@ user1125600 मैं एक बार में पूरे क्लंप की गणना के लिए कुछ सैद्धांतिक एल्गोरिदम के साथ आ सकता हूं। यह एक कंटेनर में वस्तुओं की मात्रा को अधिकतम करने के समान होगा। लेकिन मुझे नहीं लगता कि यह वास्तविक समय के खेल के लिए एक अच्छा विचार है। –

4

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

क्लंप में शामिल होने की कोशिश करने वाली एक नई इकाई सबसे नि: शुल्क मुक्त स्लॉट की तरफ बढ़ेगी, और एक बार जब यह वहां पहुंच जाएगी तो यह "गठन में रहेगी", इसकी स्थिति हमेशा उस स्लॉट की स्थिति होगी जिस पर कब्जा कर लिया गया है। क्लंपों में एक इकाई से अधिक त्रिज्या होगा, अन्य क्लंप या ढीले इकाइयों को ओवरलैप करने से बचने के लिए स्थिति समायोजित करेगा जो क्लंप में शामिल होने की कोशिश नहीं कर रहे थे।

किसी बिंदु पर, आपको, हालांकि, क्लंप में अलग-अलग इकाइयों के लिए बातचीत के साथ सौदा करें, इसलिए मुझे यकीन नहीं है कि यह सार्थक है। मुझे लगता है कि ऑस्टिन हेनले के क्षेत्र को कोशिकाओं/क्षेत्रों में विभाजित करने का सुझाव और पास के कोशिकाओं में इकाइयों के खिलाफ परीक्षण सबसे व्यावहारिक दृष्टिकोण है।