2012-02-15 22 views
7

के साथ आंदोलन बलों की गणना करें मैं एक छोटा अंतरिक्ष शूटर गेम बना रहा हूं। अंतरिक्ष भौतिकी में आने पर मैंने गणित की समस्या पर कभी भी स्टब किया है।वेक्टर, अधिकतम गति

शब्दों के साथ इसका वर्णन निम्न है: अधिकतम गति है। तो यदि आप पूर्ण पूर्ण गति देते हैं तो आप पुराने एस्टरॉयड गेम की तरह स्क्रीन पर बार-बार स्क्रीन पर आगे बढ़ेंगे। यदि रॉकेट बूस्ट जारी करते हैं तो आपको स्क्रीन पर उस गति के साथ आगे बढ़ना चाहिए।

फिर मुश्किल हिस्सा जहां मैं अभी अटक गया।

यदि आप किसी भी कोण को घुमाते हैं और फिर से बढ़ावा देते हैं तो जहाज को इस दिशा तक पहुंचने की कोशिश करनी चाहिए और जब यह कितनी तेज़ी से चल रहा है, तो अधिकतम गति को कभी भी तेज नहीं किया जाना चाहिए। तो मेरा सवाल है। इस मुद्दे के लिए किसी के पास एक अच्छा विचार सूत्र है? ऐसा लगता है कि अगर आप जानते हैं कि क्या देखना है तो इससे पहले किया गया है। :)

बीमार कुछ छोटी वेक्टर गणनाओं के साथ किए जाने की कोशिश करने के लिए इस छोटी छवि को जोड़ें। Max speed movement with force

लाल अंगूठी: अधिकतम गति

ग्रीन लाइन: वर्तमान जहाज दिशा।

ब्लैक लाइन: दिशा (ओं) और एक्स और वाई में जहाज कितनी तेज़ी से आगे बढ़ रहा है।

काला अंगूठी: आंदोलन की उत्पत्ति।

इसे समझा सकता है लेकिन इसके लिए एक अच्छा गणित समाधान ढूंढना मुश्किल है। :)

संपादित

इस कोड को हर फ्रेम में अभी उपयोग कर इम है। यह जहाज को आंदोलन देता है लेकिन जहाज को रोकने या धीमा करने के लिए उपयोगकर्ता को अपने रॉकेट बूस्टर के साथ प्रतिबिंबित करने के लिए आंदोलन की शक्ति नहीं देती है। इसके साथ ही यह तुरंत बंद हो जाता है कि आप जहाज के लिए तेज गति को छोड़ देते हैं।

//Calculates ship movement rules 
var shipVelocityVec = GetVectorPosByAngle(shipMoveSpeed, shipRotationAngle); 
var shipUnitVec =$V([Math.cos(shipRotationAngle),Math.sin(shipRotationAngle),0]); 
var rawAccel = shipAccelSpeed/shipMass; 
var scale = (shipUnitVec.dot(shipVelocityVec))/(shipTopSpeed * shipTopSpeed); 
var v1 = shipUnitVec.subtract(shipVelocityVec.multiply(scale)); 
var finalAccelVec = v1.multiply(rawAccel); 
console.log(finalAccelVec); 

//move ship according to rules 
var shipPosVector = $V([shipxPos, shipyPos, 0]); 
var movementVector = shipPosVector.add(finalAccelVec); 
shipxPos = movementVector.elements[0]; 
shipyPos = movementVector.elements[1]; 

त्वरण गति देने के लिए उपयोगकर्ता को बटन दबाया जाना है। उदाहरण के लिए उपयोगकर्ता बटन को रिलीज़ करता है, त्वरण शून्य पर सेट होता है और अधिकतम त्वरण थ्रॉटल देने के लिए फिर से बढ़ावा देना होता है।

समाधान मिला! यहां पोस्ट किया गया यह कैसे किया गया था।

+2

मुझे लगता है कि यह 2 डी चीज है? अलग एक्स और वाई वेग संकेतक रखें। यदि आप कोण पर जोर दे रहे हैं, तो एक्स और वाई घटकों में एंग्लेड जोर डालें, जिससे आप जहाज के एक्स/वाई वेग घटकों को अलग-अलग समायोजित कर सकते हैं। प्रत्येक गति समायोजन पर, जहाज की गति की जांच करें और यदि आप अधिकतम पहुंच गए हैं तो समायोजन रोकें। –

+0

कृपया मुझे सही करें मैं गलत तरीके से हूं, लेकिन छवि # 3 में लाल अंगूठी की तुलना में गति की तुलना में संयुक्त वेक्टर नहीं है? – pimvdb

+0

नहीं, क्योंकि एक्स और वाई दोनों ने कहा था कि सर्कल अधिकतम आंदोलन के बराबर है। हरी रेखा लंबी हो सकती है। # 3 में हरी रेखा सर्कल के व्यास की पूरी लंबाई होनी चाहिए। –

उत्तर

1

@ ब्लूराजा का समाधान काम करना चाहिए, हालांकि जब आप अधिकतम गति को दबाते हैं तो आपको व्यवहार में अचानक परिवर्तन मिलेगा।

ship_unit_vec = [cos(ship_angle), sin(ship_angle)] 
raw_accel = (engine_thrust/ship_mass) 

scale = dot_product(ship_unit_vec, ship_velocity_vec)/max_speed^2 

final_accel_vec = raw_accel * (ship_unit_vec - scale * ship_velocity_vec) 

नोट्स::

आप कोई "संधियों" के साथ एक समाधान चाहते हैं, तो मैं तुम्हें क्या आप त्वरण के समायोजन की सही तरह जोड़कर देख रहे हैं कर सकते हैं, इस प्रकार का मानना ​​है

  • यदि |ship_velocity_vec|<<max_speed, scale * ship_velocity_vec घटक लापरवाह है।
  • यदि |ship_velocity_vec|==max_speed, scale * ship_velocity_vec घटक "गलत" दिशा में सभी अतिरिक्त त्वरण को रद्द करता है, और "दाएं" दिशा में त्वरण को सक्रिय करता है।
  • मैं इस बाहर की कोशिश की है कभी नहीं, इसलिए मैं नहीं जानता कि यह कैसे खिलाड़ी के लिए महसूस होगा ...

आम तौर पर, अगर वहाँ सिर्फ जहाज से त्वरण के और अधिक स्रोत हैं प्रणोदक, आप (, कहते हैं raw_accel_vec के रूप में) एक साथ उन सब को जोड़ सकते हैं, और सभी को एक बार ऊपर कार्रवाई करने:

scale_forall = dot_product(raw_accel_vec, ship_velocity_vec)/max_speed^2 
final_accel_vec = raw_accel_vec - scale_forall * ship_velocity_vec 
+0

उत्कृष्ट उदाहरण! जहाज को द्रव्यमान देने का कभी सोचा नहीं। केवल उन बलों के बारे में सोचा जो इस समय इसके लिए आवेदन किए गए थे और परिवर्तनों के आधार के रूप में इसका उपयोग करते थे। कल सुबह मेरे कोड में कुछ संशोधन करेंगे देखें कि ऐसा कुछ कैसे काम कर सकता है। –

+0

यह जवाब ठीक उसी तरह ड्रैग बल पेश करता है जैसा माइकल ने सुझाव दिया था। हालांकि, मुझे यकीन नहीं है कि आपने एक द्रव्यमान क्यों जोड़ा * (यह केवल निरंतर एकाधिक द्वारा त्वरण को प्रभावित करता है, इसलिए छोड़ा जा सकता है) *, और किसी कारण से आपने एकल, सुंदर वेक्टर समीकरण को एकाधिक में बदलने का फैसला किया है, और अधिक समेकित समीकरण। –

+0

एक अंतर है: यहां "ड्रैग" त्वरण और वेग के * वर्ग * के आनुपातिक है, और "बल" लागू किए बिना दिए गए 'max_speed' को उपज करने के लिए उचित रूप से स्केल किया गया है। – comingstorm

3

आप कुछ भ्रमित करने लगते हैं - अधिकतम गति तक वेग को कैप करने में कोई समस्या नहीं है, भले ही त्वरण एक अलग कोण पर हो, भले ही आप वैक्टर का सही ढंग से उपयोग कर रहे हों।

आपका सेटअप कुछ इस तरह दिखना चाहिए:

  1. आपका जहाज की स्थिति, एक वेग, और एक त्वरण होना चाहिए। इनमें से प्रत्येक को 2 डी वेक्टर के रूप में प्रदर्शित किया जा सकता है (अलग x और y घटकों के साथ)।
  2. प्रत्येक फ्रेम, स्थिति में वेग जोड़ें, और गति के त्वरण।
  3. प्रत्येक फ्रेम, जांचें कि speed कुछ अधिकतम से अधिक नहीं है।यदि ऐसा होता है, गति normalizing वेग वेक्टर द्वारा अधिकतम गति और इसे अधिकतम गति से गुणा करें।

यही है! विचार करने के लिए कोई विशेष मामला नहीं है - यह वेक्टर बीजगणित का जादू है!

+0

के साथ आरेख बनाने के लिए +1 स्थिति को वेग के लिए मात्रा * आनुपातिक *, * आनुपातिक * वेग के त्वरण के लिए जोड़ें। –

+0

@ माइकल: यह इकाइयों (पिक्सल/सेकेंड बनाम पिक्सेल/फ्रेम) पर निर्भर करता है। :) –

+0

वास्तव में नहीं। जब तक कि आपके फ्रेम सभी समय पर समान रूप से दूरी न हों, आप इकाइयों में स्थिरांक को अवशोषित नहीं कर सकते हैं। यह एक गणक समस्या है - यह एकीकरण के बारे में है, इसके अलावा नहीं। –

1

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

समग्र प्रभाव यह है कि स्पेसशिप तेजी से बढ़ने के साथ ही ड्रैग बल बढ़ता है, जिससे जहाज तेजी से बढ़ता है जब गति की दिशा में तेज़ी से बढ़ना मुश्किल हो जाता है। जब गति की दिशा का विरोध होता है तो यह त्वरण को भी आसान बनाता है।

एक बिंदु जहां यह आपके विवरण से अलग हो जाता है यह है कि स्पेसशिप हमेशा के लिए अधिकतम गति पर जारी नहीं रहेगी, यह धीमा हो जाएगा। हालांकि, यह रोक नहीं पाएगा, क्योंकि ड्रैग बल गिरता है क्योंकि जहाज धीमा हो जाता है। यह निरंतर गति पर हमेशा के लिए जारी जहाज की तुलना में क्षुद्रग्रहों की मेरी याददाश्त से मेल खाता है, लेकिन यह काफी समय से चल रहा है क्योंकि मैंने खेला है।

+0

हां, यह सही है। ड्रैग फोर्स भी आईएम के बाद और अनुकरण करने का इरादा रखता है। मैंने इसे ड्रॉप ड्रैग फोर्स से बाहर कर दिया ताकि यह समझाने में आसान हो सके कि मैं किसके साथ शुरू करने के बाद था। –

+0

हालांकि इस ड्रैगफोर्स को वर्तमान दिशात्मक बल जहाजों द्वारा धीरे-धीरे संशोधित करने में सक्षम होना चाहिए। सही? –

+0

@ जोनास: ऐसा प्रतीत होता है कि आपको अपने [वेक्टर गणित] (http://channel9.msdn.com/coding4fun/articles/2D-Game-Primer-Visual-C) पर ब्रश करने की आवश्यकता है। यहां पर विचार करने के लिए कोई विशेष मामला नहीं है - वेक्टर स्वतंत्र रूप से जोड़ते हैं, ताकि आप आसानी से प्रत्येक फ्रेम के वेग में ड्रैग-त्वरण जोड़ सकें, फिर बिना किसी समस्या के उपयोगकर्ता इनपुट के कारण त्वरण को जोड़ दें। –

0

मैंने किया! आपके सहयोग के लिए धन्यवाद।

अंततः समाधान मिला। समस्या यह थी कि जब मैं गति की बात करता हूं तो जहाजों के वर्तमान आंदोलन को संशोधित करने की कोशिश कर रहा था और फिर इस "ड्रैग" बलों की गणना करता है जो इस आंदोलन का उत्पाद होगा जब उपयोगकर्ता ने दूसरी दिशा में जाने की कोशिश की थी। समाधान @ ब्लूराजा और @ कॉमिंगस्टॉर्म जैसा था। आंदोलन की बात आती है जब सभी बलों को एक साथ जोड़ा जाना चाहिए। यह तब होना चाहिए जब जहाजों की स्थिति बदल जाए। वर्तमान आंदोलन जहाजों में जोड़ा नहीं जाना चाहिए। आप वर्तमान आंदोलन को प्रभावित करने में सक्षम हो सकते हैं लेकिन फिर आपको इसे अलग-अलग करना होगा। तो मैंने सोचा कि मैं इसके लिए अपना समाधान कैसे साझा करता हूं।

यह फ़ंक्शन हर बार चलाता है जब उपयोगकर्ता जहाज को तेज़ करता है।

function CalcShipMovement() { 
//Calculates ship movement rules 
shipPosVector = $V([shipxPos, shipyPos, 0]); 
var shipVelocityVec = GetVectorPosByAngle(shipAccelSpeed, shipRotationAngle); 
var shipUnitVec = $V([Math.cos(shipRotationAngle), Math.sin(shipRotationAngle), 0]); 

if(currentShipMoveVector != null && Get2DVectorLength(currentShipMoveVector) > 0) { 
    var nextMove = currentShipMoveVector.add(shipVelocityVec); 
    var nextSpeed = Get2DVectorLength(nextMove); 
    //check if topspeed of movement should be changed 
    if(nextSpeed > shipTopSpeed) { 
     var scale = nextSpeed/shipTopSpeed; 
     currentShipMoveVector = DevideVector(nextSpeed, scale); 
    } else { 
     currentShipMoveVector = currentShipMoveVector.add(shipVelocityVec); 
    } 
} 
if(currentShipMoveVector != null && Get2DVectorLength(currentShipMoveVector) == 0) { 
    currentShipMoveVector = currentShipMoveVector.add(shipVelocityVec); 
}} 

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

function SetShipMovement() { 
if(currentShipMoveVector != null && Get2DVectorLength(currentShipMoveVector) > 0) { 
    shipMoveSpeed = Get2DVectorLength(currentShipMoveVector); 
    shipPosVector = shipPosVector.add(currentShipMoveVector); 
    shipxPos = shipPosVector.elements[0]; 
    shipyPos = shipPosVector.elements[1]; 
    //Makes the ship slow down if no acceleration is done for the ship 
    if(shipAccelSpeed == 0) { 
     currentShipMoveVector = currentShipMoveVector.subtract(DevideVector(currentShipMoveVector, 50)); 
    } 
} else { 
    currentShipMoveVector = $V([0, 0, 0]); 
}}