यह एक अच्छा कार आंदोलन बनाने के लिए कठिन नहीं है (लेकिन यह पोस्ट बहुत लंबी होगी)। कार को भौतिक रूप से गतिशील बनाने के लिए आपको कुछ बुनियादी ताकतों को "अनुकरण" करना होगा।
(सभी कोड नमूने स्यूडोकोड हैं।)
त्वरण
सबसे पहले, आपको स्पष्ट रूप से त्वरण की आवश्यकता होगी। निम्नलिखित पंक्ति के रूप में कुछ सरल होगा:
acceleration_vector = forward_vector * acceleration_input * acceleration_factor
forward_vector
- कार के समान दिशा में एक वेक्टर इंगित करता है।
acceleration_input
- इनपुट अंतराल में होना चाहिए [-1, 1]।
acceleration_factor
- त्वरण का मान (पिक्सेल / सेकंड ^ 2, या जो भी आपकी इकाइयाँ हैं)।
स्टीयरिंग
स्टीयरिंग भी काफी सरल है। सिद्धांत रूप में, आप क्या करेंगे कार के आगे वेक्टर को घुमाने के लिए इसे किसी अन्य दिशा में इंगित करने के लिए।
steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)
हालाँकि, आप यहाँ एक जटिलता का सामना कर सकते हैं। यदि आपका इनपुट कीबोर्ड के माध्यम से है, तो इसका मूल्य -1 या 1 होगा, जिसका अर्थ है कि आपकी कार तुरंत बदल जाएगी। आप इसे एक बहुत ही सरल रैखिक प्रक्षेप (लेरिंग) का उपयोग करके ठीक कर सकते हैं:
amount = time_since_last_frame * steer_lerp_factor
forward_vector = lerp(forward_vector, new_forward_vector, amount)
राशि इस तरह के समय पर निर्भर होनी चाहिए कि आपका आंदोलन आपके फ्रेम दर पर निर्भर न हो। यह राशि [0, 1] के बीच होनी चाहिए और यह जितनी छोटी होगी, पुराने और नए वैक्टर के बीच संक्रमण उतना ही कम होगा।
(इस बिंदु पर आप पाएंगे कि कार खड़ी रहेगी भले ही वह खड़ी हो। इसे रोकने के लिए, गुणा steer_angle
करके current_speed / max_speed
, जहाँ max_speed
आपके द्वारा परिभाषित किया गया है।)
चलती
अब हम त्वरण लागू करेंगे और कार को उसके वेग, त्वरण और स्टीयरिंग के आधार पर निश्चित संख्या में पिक्सेल ले जाएँगे। हम कार की गति को भी सीमित करना चाहते हैं, ताकि यह अनंत तेजी से आगे बढ़ न जाए।
current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
velocity_vector += acceleration_vector * time_since_last_frame
}
position_vector += velocity_vector * time_since_last_frame
आपकी कार अब फिसलने लगी है
यदि मैं सही हूं, तो आपकी कार अब फिसलती हुई दिखाई देनी चाहिए जब आप मोड़ रहे हों जैसे कि वह बर्फ पर थी। ऐसा इसलिए है क्योंकि कोई घर्षण नहीं है। एक असली कार पर एक उच्च पार्श्व घर्षण होता है (पहियों के बग़ल में घूमने में सक्षम नहीं होने के कारण: पी)।
आपको पार्श्व वेग को कम करने की आवश्यकता होगी। इसे पूरी तरह से कम न करके आप कार को बहती हुई भी बना सकते हैं।
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
चूँकि हम घर्षण के बारे में बात कर रहे हैं, आप एक बल (घर्षण का) भी चाहते हैं जो आपके वेग को कम कर दे, जैसे कि जब आप तेजी को रोकते हैं, तो आपकी कार अंततः बंद हो जाएगी।
backwards_friction = -velocity_vector * backwards_friction_factor
कार को स्थानांतरित करने के लिए आपका कोड अब इस तरह दिखना चाहिए:
// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame
current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
velocity_vector += acceleration_vector * time_since_last_frame
}
position_vector += velocity_vector * time_since_last_frame
नोट बंद करना
मैंने उल्लेख किया कि आपको स्टीयरिंग पर लेरिंग कैसे लागू करना चाहिए; मुझे लगता है कि आपको त्वरण के लिए एक ही काम करने की आवश्यकता हो सकती है और संभवतः स्टीयर कोण के लिए भी (आपको पिछले फ्रेम से उनके मूल्यों को संग्रहीत करना होगा और उसी से एलआरपी करना होगा)। कार के सापेक्ष सभी वैक्टर (आगे, दाएं, ऊपर) की लंबाई 1 होनी चाहिए।
इसके अलावा, घर्षण थोड़ा अधिक जटिल है जितना मैंने यहां दिखाया है। आपको हमेशा यह सुनिश्चित करना चाहिए कि इसकी लंबाई कार स्टॉप बनाने के लिए आवश्यक त्वरण से अधिक नहीं है (अन्यथा घर्षण कार को विपरीत दिशा में ले जाएगा)। तो आपके पास कुछ ऐसा होना चाहिए:
dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))