ฉันกำลังมองหาการสร้างการเคลื่อนไหวของรถที่สมจริงโดยใช้เวกเตอร์


12

ฉันรู้วิธีการทำอย่างนี้และพบhttp://www.helixsoft.nl/articles/circle/sincos.htmนี้ฉันไปแล้ว แต่ฟังก์ชั่นส่วนใหญ่ที่แสดงไม่ทำงานฉันเพิ่งได้รับข้อผิดพลาด เพราะพวกเขาไม่อยู่ ฉันได้ดูฟังก์ชัน cos และ sin แต่ไม่เข้าใจวิธีใช้หรือวิธีการทำให้การเคลื่อนที่ของรถยนต์ทำงานอย่างถูกต้องโดยใช้เวกเตอร์ ฉันไม่มีรหัสเพราะฉันไม่แน่ใจว่าจะทำอย่างไรขอโทษ

ความช่วยเหลือใด ๆ ที่ชื่นชม

แก้ไข:

ฉันมีข้อ จำกัด ที่ฉันต้องใช้เอ็นจิ้น TL สำหรับเกมของฉันฉันไม่ได้รับอนุญาตให้เพิ่มเอนจิ้นฟิสิกส์ประเภทใด จะต้องตั้งโปรแกรมใน c ++ นี่คือตัวอย่างของสิ่งที่ฉันได้จากการพยายามติดตามสิ่งที่ทำในลิงก์ที่ฉันให้ไว้

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);

ตรวจสอบไซต์นี้เพื่อหาพฤติกรรมการบังคับเลี้ยว: red3d.com/cwr/steer
MichaelHouse

คุณต้องกำหนด "การเคลื่อนไหวของรถที่สมจริง"
Maik Semder

1
ฉันคิดว่ามุมของคุณมาจากพวงมาลัยบางที ความยาวควรเป็นขนาดของความเร็วของคุณ ดังนั้นข้อมูลโค้ดที่ผ่านมาอาจจะมีบางสิ่งบางอย่างในสายของ: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);นอกเหนือจากนั้นโปรดบอกสิ่งที่ป้อนข้อมูลของคุณและวิธีการที่รถควรประพฤติ ตอนนี้มันควรจะบังคับในระนาบพื้น แต่อีกครั้งนี่ไม่ใช่เรื่องทั่วไป มีคุณเพียงแค่ทำให้เราของขั้นตอนที่บูรณาการออยเลอร์น้ำมันดิบ ..
teodron

คำตอบ:


23

มันไม่ยากเลยที่จะสร้างการเคลื่อนไหวของรถที่ค่อนข้างดี (แต่โพสต์นี้จะค่อนข้างยาว) คุณจะต้อง "จำลอง" แรงพื้นฐานสองสามอย่างเพื่อให้รถเคลื่อนที่มีเหตุผล

(ตัวอย่างโค้ดทั้งหมดคือ 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))

ว้าวนี่เป็นคำตอบที่ยอดเยี่ยม!
ezolotko

0

ตัดสินจากคำถามของคุณฉันจะถือว่าคุณค่อนข้างใหม่กับการเขียนโปรแกรม (ซึ่งเป็น a-ok btw!) ฉันขอแนะนำให้ใช้เฟรมเวิร์กที่มีอยู่เนื่องจากการจำลองรถจริงเป็นหนึ่งในแง่มุมที่ยากที่สุดของฟิสิกส์ในการทำให้ถูกต้อง

คุณไม่ได้พูดถึงข้อ จำกัด 2D / 3D ดังนั้นฉันจะไปข้างหน้าและแนะนำให้คุณดาวน์โหลด Havok SDK (ฟรีสำหรับการใช้ที่ไม่ใช่เชิงพาณิชย์) และรับการสาธิตง่าย ๆ และทำงาน (จริง ๆ แล้วพวกเขามีการสาธิตที่หมดกล่อง เรียบเรียงในระบบของคุณโค้ดทั้งหมดอยู่ที่นั่น] คุณไม่ต้องทำอะไรเลยเพื่อให้คอมไพล์ ... เพียงแค่เปิดโปรเจ็กต์และกดบิลด์)

เมื่อคุณมีความคิดเกี่ยวกับด้านหลังของฉากของฟิสิกส์รถยนต์ (แม้ว่าคุณจะไม่เห็นการใช้งานจริงของฟิสิกส์ที่ซ่อนอยู่คุณจะได้เห็นอินเทอร์เฟซ) ฉันเชื่อว่าคุณจะอยู่ในตำแหน่งที่ดีขึ้น เพื่อทำให้ถูกต้องเมื่อคุณเริ่มด้วยตัวเอง

ฉันยังถามคำถามที่คล้ายกันเมื่อไม่นานมานี้ ลิงก์ในนั้นอาจช่วยได้เช่นกัน และนี่คือการเชื่อมโยงอื่น


หลังจากดูที่การแก้ไขของคุณดูเหมือนว่าคุณกำลังมองหาการเปลี่ยนความเร็วของรถโดยขึ้นอยู่กับมุมที่คำนวณได้ (ซึ่งไม่ใช่ btw ที่เหมือนจริงดังนั้นคุณควรเปลี่ยนคำถามเดิมเพื่อสะท้อนความคิดนั้น) หากมุมเป็นส่วนหนึ่งของคำถาม (ที่คุณไม่สามารถเปลี่ยนได้) และคุณต้องใช้มุมเพื่อคำนวณความเร็วใหม่ให้ไปกับสิ่งที่ @teodron ใส่ไว้ในความคิดเห็น

อีกวิธีคือใช้เวกเตอร์เท่านั้น มีหลายวิธีที่ใช้เวกเตอร์ฉันจะนำเสนอวิธีการหนึ่ง

ความเร็วคือทิศทาง * ขนาด (โดยขนาดคือความเร็วและทิศทางเป็นเวกเตอร์ที่ทำให้เป็นมาตรฐาน) คำนวณความเร็วและทิศทางของรถในปัจจุบัน หาทิศทางและเพิ่มเวกเตอร์ (เรียกมันว่าD') กับมันที่ตั้งฉากกับมัน นี่จะเปลี่ยนความเร็วของรถ ไม่มีมุมที่จะยุ่งเกี่ยวกับ (แม้ว่าคุณสามารถใช้มุมเพื่อกำหนดความยาวของเวกเตอร์ตั้งฉากซึ่งคุณสามารถเปลี่ยนปัจจัย [ดูด้านล่าง])

วิธีการคำนวณD' : เพื่อหาเวกเตอร์ตั้งฉากให้ใช้ทิศทางของความเร็วเดิมแล้วข้ามมันไปพร้อมกับเวกเตอร์ทิศทางที่พุ่งเข้าหาหน้าจอซึ่งคำสั่งที่คุณข้ามเวกเตอร์ไปนั้นเป็นตัวกำหนดทิศทางของเวกเตอร์ตั้งฉาก จากนั้นให้คูณปัจจัย perpedicular นี้ด้วยปัจจัยเลี้ยวซึ่งจะกำหนดว่ารถจะหมุนเร็วแค่ไหน


ฉันจะ แต่ฉันไม่ได้รับอนุญาตให้ใช้เอ็นจิ้นฟิสิกส์เกมเป็น 3D และสิ่งที่ฉันต้องเปลี่ยนก็คือเวกเตอร์ X และ Z ฉันแค่ต้องหาว่ามันคืออะไร
bobthemac

@bobthemac: นี่เป็นคำถามการบ้านหรือเปล่า ถ้าใช่แก้ไขคำถามของคุณเพื่อชี้ให้เห็นข้อ จำกัด ที่คุณมีและอาจโพสต์โค้ดที่เกี่ยวข้องเพื่อให้เรามีสิ่งที่จะสร้าง Btw, ลิงค์สุดท้ายอาจเป็นสิ่งที่คุณกำลังมองหาในแง่ของการทำความเข้าใจการทำงาน
Samaursa

ฉันได้เพิ่มข้อมูลที่คุณร้องขอและดูลิงก์ที่ให้ไว้ แต่ก็ยังไม่เข้าใจ
bobthemac

@bobthemac: ดูการแก้ไขของฉัน
Samaursa
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.