การสร้าง Plattformer - จะทราบได้อย่างไรว่าผู้เล่นได้รับอนุญาตให้กระโดดได้หรือไม่?


16

ฉันกำลังสร้างเกม Plattformer Jump n 'Run Style ง่ายๆ ฉันไม่ได้ใช้ไทล์ - ฉันมีรูปทรงเรขาคณิตสำหรับเอนทิตีระดับของฉัน (และผู้เล่นก็เป็นหนึ่งเดียวกัน) ฉันเสร็จรหัสตรวจจับการชนกันของฉันและทุกอย่างทำงานได้ดีจนถึงตอนนี้

ต่อไปฉันอยากจะกระโดด เพียงตรวจสอบว่าผู้เล่นกดคีย์ที่เหมาะสมและเพิ่มความเร็วขึ้น ทำงานได้ดี แต่มันใช้งานได้แม้ว่าผู้เล่นจะอยู่ในอากาศซึ่งไม่ใช่สิ่งที่ฉันต้องการ ;-)

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

ขอบคุณ!

คำตอบ:


14

สปริงสองทางเลือก:

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

การตรวจสอบตามปกติดูเหมือนจะเป็นความคิดที่ดีสำหรับฉัน ขอบคุณสำหรับการโพสต์ที่
Christopher Horenstein

+1 สำหรับการตรวจสอบตามปกติ สิ่งนี้ทำให้มั่นใจได้ว่าพื้นสามารถเปลี่ยนเป็นผนังได้อย่างราบรื่นโดยไม่ทำให้เกิดปัญหาใด ๆ
Soviut

1
+1 ตรวจสอบการชนกันตามปกติอย่างแน่นอน การมีรูปทรงเรขาคณิตโลกชนิดต่าง ๆ นั้นใช้ได้และช่วยให้การออกแบบในระดับที่ยืดหยุ่นมากขึ้น แต่ก็ไม่ได้ช่วยแก้ปัญหาหลักของคุณ "กำแพง" อาจเป็นประเภท "พื้นดิน" ก็ได้ขึ้นอยู่กับว่าคุณกำลังวิ่งหรือยืนบนพื้น นั่นคือสิ่งที่การปะทะกันปกติจะช่วยได้
bummzack

ฉันพบวิธีแก้ปัญหาปกติดีมากและจะแก้ปัญหาของฉัน แม้แต่คำตอบอันดับสูงอื่น ๆ ก็ดีและก็เช่นกัน - แต่นี่ตอบคำถามของฉันได้ดีกว่า ขอบคุณ wkerslake ของคุณ!
Malax

8

แน่นอนคุณควรใช้พื้นผิวบางประเภท ลองคิดดูสิคุณจะจัดการอย่างไรถ้าคุณปีนขึ้นบันไดได้ถ้าคุณไม่รู้ว่าตัวละครของคุณเพิ่งชนกำแพงหรือบันได? คุณสามารถใช้ OOP เพื่อจัดการลำดับชั้นของประเภทโดยใช้เฮอริเทจ แต่ฉันขอแนะนำให้คุณใช้ "หมวดหมู่" ที่ดำเนินการโดยใช้ประเภทที่ระบุ:

นี่คือแนวคิด: การระบุ "การชน" มีธงสำหรับแต่ละหมวดหมู่ ตัวอย่างเช่น:

namespace Collisions
{
    enum Type
    {
        None   = 0,
        Floor  = 1 << 0,
        Ladder = 1 << 1,
        Enemy  = 1 << 2,
        ... // And whatever else you need.

        // Then, you can construct named groups of flags.
        Player = Floor | Ladder | Enemy
    };
}

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

void Player::Collided( Collisions::Type group )
{
   if ( group & Collisions::Ladder )
   {
      // Manage Ladder Collision
   }
   if ( group & Collisions::Floor )
   {
      // Manage Floor Collision
   }
   if ( group & Collisions::Enemy )
   {
      // Manage Enemy Collision
   }
}

วิธีการใช้การตั้งค่าสถานะบิตค่าบิตและตัวดำเนินการ "หรือ" บิตเพื่อให้แต่ละกลุ่มมีค่าแตกต่างกันขึ้นอยู่กับค่าไบนารีของประเภท วิธีนี้ใช้งานได้ดีและปรับขนาดได้อย่างง่ายดายเพื่อให้คุณสามารถสร้างกลุ่มการชนกันของศุลกากร แต่ละเอนทิตี (ผู้เล่น, ศัตรู, ฯลฯ ) ในเกมของคุณมีบางบิตที่เรียกว่า "ตัวกรอง" ซึ่งใช้เพื่อกำหนดสิ่งที่มันสามารถชนกันได้ รหัสการชนของคุณควรตรวจสอบเพื่อดูว่าบิตตรงกันและตอบสนองด้วยรหัสบางอย่างที่อาจมีลักษณะดังนี้:

void PhysicEngine::OnCollision(...)
{
    mPhysics.AddContact( body1, body1.GetFilter(), body2, body2.GetFilter() );
}

มีเหตุผลที่จะใช้ const int แทน enum หรือไม่? ในกรณีเลวลงของการตั้งค่าสถานะเดียวหรือกลุ่มที่มีชื่อประเภทที่แจกแจงสามารถอ่านได้มากขึ้นและคุณจะได้รับความสามารถในการตรวจสอบประเภทเพิ่มเติมในคอมไพเลอร์ส่วนใหญ่

ใช่แล้ว enum ไม่สามารถ (ฉันคิดว่า) ใช้ตัวดำเนินการไบนารีเพื่อสร้างกลุ่มแบบกำหนดเองใหม่ เหตุผลที่ฉันทำวิทยานิพนธ์เหล่านี้คือฉันใช้คลาส Config กับสมาชิกสแตติกสาธารณะเพื่อเหตุผลในการอ่านและการรักษาความปลอดภัยของพารามิเตอร์กำหนดค่า
Frédérick Imbeault

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

ฉันอัปเดตตัวอย่างโค้ดของคุณเพื่อใช้ประเภทที่ระบุ

บางทีมันอาจทำให้อ่านง่ายขึ้น ฉันเข้าใจการเปลี่ยนแปลงที่คุณทำวิธีที่ฉันใช้นั้นถูกต้อง แต่ฉันไม่ได้ปรับรหัสสำหรับการอธิบาย enouph ขอบคุณสำหรับการแก้ไข สำหรับเนมสเปซคุณค่อนข้างถูกต้อง แต่นี่ไม่เป็นความจริงสำหรับทุกภาษา (ภาษาสคริปต์สำหรับตัวอย่าง) "ความปลอดภัย" คือตัวเลือกการกำหนดค่าของฉันเป็นแบบคงที่ดังนั้นจึงไม่สามารถแก้ไขได้ แต่การใช้ enum จะป้องกันสิ่งนี้เช่นกัน
Frédérick Imbeault

1

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

ในรหัสหลอกหยาบ:

bool isOnGround(Character& chr)
{
   // down vector is opposite from your characters current up vector.
   // if you want to support wall jumps, animate the vecToFoot as appropriate.
   vec vecToFoot = -chr.up * chr.footDistanceFromCentre;

// if feet are moving away from any surface, can't be on the ground if (dot(chr.velocity, down) < 0.0f) return false;

// generate line from character centre to the foot position vec linePos0 = chr.position; vec linePos1 = chr.position + vecToFoot;

// test line against world. If it returns a hit surface, we're on the ground if (testLineAgainstWorld(line0, line1, &surface) return true;

return false; }


สิ่งนี้จะไม่ทำงานหากคุณต้องการเพิ่มคุณสมบัติเช่นการกระโดดสองครั้งหรือการกระโดดข้ามกำแพงที่ฉันคิดว่า?
Frédérick Imbeault

ฉันไม่เชื่อว่า OP กล่าวถึงการกระโดดสองครั้งหรือการกระโดดข้ามกำแพงใช่มั้ย
jpaver

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

นี่เป็นวิธีที่ยืดหยุ่นน้อยกว่าในการตรวจสอบการชนตามปกติ (มีความยืดหยุ่นน้อยลงเพราะคุณสามารถแยกความแตกต่างของกำแพงกระโดดจากพื้นกระโดดจากเพดานกระโดดเพียงแค่ตรวจสอบทิศทางของปกติ)

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