มันไม่ยากเลยที่จะสร้างการเคลื่อนไหวของรถที่ค่อนข้างดี (แต่โพสต์นี้จะค่อนข้างยาว) คุณจะต้อง "จำลอง" แรงพื้นฐานสองสามอย่างเพื่อให้รถเคลื่อนที่มีเหตุผล
(ตัวอย่างโค้ดทั้งหมดคือ pseudocode)
การเร่งความเร็ว
ก่อนอื่นคุณจะต้องเร่งความเร็ว บางสิ่งที่ง่ายเหมือนบรรทัดต่อไปนี้จะทำ:
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 ซึ่งหมายความว่ารถของคุณจะเปลี่ยนทันที คุณสามารถแก้ไขได้โดยใช้การแก้ไขเชิงเส้นที่ง่ายมาก (lerping):
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
รถของคุณกำลังเลื่อนอยู่
ถ้าฉันพูดถูกรถของคุณก็ควรที่จะเลื่อนเมื่อใดก็ตามที่คุณเลี้ยวราวกับว่ามันอยู่บนน้ำแข็ง นี่เป็นเพราะไม่มีแรงเสียดทาน ในรถจริงมีแรงเสียดทานด้านข้างสูง (เนื่องจากล้อไม่สามารถหมุนไปด้านข้าง: P)
คุณจะต้องลดความเร็วด้านข้าง คุณสามารถทำให้รถคันนั้นล่องลอยได้เช่นกัน
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
การปิดบันทึก
ฉันพูดถึงวิธีที่คุณควรใช้ lerping กับพวงมาลัย ฉันคิดว่าคุณอาจต้องทำสิ่งเดียวกันสำหรับการเร่งความเร็วและอาจเป็นไปได้สำหรับมุมบังคับ (เช่นคุณจะต้องเก็บค่าของพวกเขาจากเฟรมก่อนหน้าและ lerp จากนั้น) เวกเตอร์ทั้งหมดที่สัมพันธ์กับรถ (ไปข้างหน้าขวาขึ้น) ควรมีความยาว 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))