วิธีทำให้ผู้เล่นเลื่อนไปตามภูมิประเทศอย่างราบรื่น


11

แผนภาพ

ฉันทำเกมสามมิติ เมื่อผู้เล่นพยายามที่จะเดินแนวทแยงมุมเข้าไปในกำแพงฉันต้องการให้พวกเขาเลื่อนไปมาได้อย่างราบรื่นดังนั้นส่วนใดของการเคลื่อนไหวก็จะถูกใช้อย่างถูกกฎหมาย กำแพงอาจเป็นมุมใดก็ได้ไม่เพียงแค่แนวตั้งหรือแนวนอนและผู้เล่นมีการเคลื่อนไหว 360 องศา

ฉันรู้สึกว่าฉันเกือบจะอยู่ที่นั่น แต่ฉันไม่สามารถวางชิ้นสุดท้ายไว้ได้

อัพเดท: ข่าวดีสำหรับทุกคน! ฉันทำงานแล้ว แต่ ... ฉันสับสนนิดหน่อยว่าฉันควรทำอะไรให้เป็นปกติและไม่ดี ปกติก็ต้องเป็นเวกเตอร์หน่วยจริงไหม? แต่จากนั้นฉันกำลังผสมกับอินพุตของฉันดังนั้นฉันจึงทำให้เป็นปกติ - ฉันผิด

โดยวิธีการที่ฉันได้พบว่าฉันต้องผลักดันผู้เล่น 1 พิกเซลในทิศทางปกติเพื่อให้พวกเขาไม่ได้ติดอยู่กับสิ่งต่าง ๆ - ทำงานได้ดี

คำตอบ:


13

เพียงฉายเวกเตอร์การเคลื่อนที่ลงบนระนาบปกติแล้วลบผลลัพธ์จากเวกเตอร์การเคลื่อนที่ของคุณ

Vector undesiredMotion = normal * (dotProduct(input, normal));
Vector desiredMotion = input - undesiredMotion;

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


ขอโทษที่เขาควรจะอยู่หน้ากำแพงแนวตั้งตรงนั้น การวาดภาพที่น่ากลัว
Iain

1
ฉันสับสนเล็กน้อยเกี่ยวกับผลิตภัณฑ์ดอท ผลิตภัณฑ์จุดไม่ใช่สเกลาร์ใช่ไหม
Iain

1
ใช่ แต่คุณคูณมันด้วยเวกเตอร์ (ปกติ) เพื่อให้ได้เวกเตอร์ของการเคลื่อนไหวที่คุณไม่ต้องการ เวกเตอร์ (x, y, z) คูณด้วยสเกลาร์ทำให้คุณได้เวกเตอร์ (sx, sy, sz)
Chris Howe

เสร็จแล้วเปลี่ยนตัวแปรเพื่อให้ตรงกับไดอะแกรม :)
Chris Howe

@ ฉันเป็นจริงฉันพยายามที่จะเข้าใจวิธีการใช้คำตอบนี้ แต่ฉันไม่สามารถเข้าใจได้ เมื่อฉันสร้างรหัสที่แน่นอนนี้ฉันได้รับdesiredMotionผลลัพธ์ที่แปลกจริง ๆ คุณเคยทำงานนี้ไหม
ทดสอบ

1

ในขณะที่มันตรงไปข้างหน้าเพียงแค่ลบองค์ประกอบของการเคลื่อนไหวที่เป็นไปตามปกติมันอาจเหมาะกับการเล่นเกมของคุณเพื่อหมุนเวกเตอร์เคลื่อนไหวแทน ตัวอย่างเช่นในเกมแอ็คชั่นบุคคลที่ 3 อาจเป็นเรื่องง่ายที่จะวางสายบนกำแพงและขอบเขตอื่น ๆ เพื่อให้คุณสามารถคาดเดาสิ่งที่ผู้เล่นตั้งใจได้

// assume that 'normal' is unit length
Vector GetDesired(Vector input, Vector normal) {
   // tune this to get where you stop when you're running into the wall,
   // vs. bouncing off of it
   static float k_runningIntoWallThreshold = cos(DEG2RAD(45));

   // tune this to "fudge" the "push away" from the wall
   static float k_bounceFudge = 1.1f;

   // normalize input, but keep track of original size
   float inputLength = input.GetLength();
   input.Scale(1.0f / inputLength);

   float dot = DotProduct(input, normal);

   if (dot < 0)
   {
      // we're not running into the wall
      return input;
   }
   else if (dot < k_runningIntoWallThreshold)
   {
      Vector intoWall = normal.Scale(dot);
      intoWall.Scale(k_bounceFudge);

      Vector alongWall = (input - intoWall).Normalize();
      alongWall.Scale(inputLength);

      return alongWall;
   }
   else
   {
      // we ran "straight into the wall"
      return Vector(0, 0, 0);
   }
}

ดี แต่ถ้าคุณปรับขนาดตามปัจจัยที่เหลวไหลนั้นทำให้คุณชนกับกำแพงและเลื่อนไปตามนั้นหรือเป็นกรณีของการปรับแต่งมัน?
Chris Howe

ความคิดของฉันคือการที่คุณปรับแต่งให้ดูโอเค; แน่นอนถ้ามันมีขนาดใหญ่เกินไปมันจะดูเหมือนว่าคุณใหญ่ แต่ถ้ามันบอบบางพอมันจะทำให้คุณไม่ต้องงอบนพื้นผิวที่โค้งงอเล็กน้อย
dash-tom-bang
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.