กลไกการย้อนเวลาในเกม


10

ฉันสงสัยว่ากลไกการจัดการเวลาในเกมได้รับการออกแบบโดยทั่วไปอย่างไร ฉันมีความสนใจเป็นพิเศษในการย้อนเวลา (เรียงลำดับเหมือนใน SSX ล่าสุดหรือ Prince of Persia)

เกมดังกล่าวเป็นเกมยิงจากบนลงล่าง 2D

กลไกที่ฉันพยายามออกแบบ / นำไปใช้มีข้อกำหนดดังต่อไปนี้:

1) การกระทำของเอนทิตีนอกเหนือจากตัวละครของผู้เล่นนั้นกำหนดขึ้นอย่างสมบูรณ์

  • การกระทำที่เอนทิตีทำจะขึ้นอยู่กับเฟรมที่ดำเนินไปตั้งแต่ระดับเริ่มต้นและ / หรือตำแหน่งของผู้เล่นบนหน้าจอ
  • หน่วยงานจะเกิดในเวลาที่กำหนดในระหว่างระดับ

2) Time reverse ใช้งานได้โดยย้อนกลับแบบเรียลไทม์

  • การกระทำของผู้เล่นจะถูกย้อนกลับมันจะย้อนกลับในสิ่งที่ผู้เล่นทำ ผู้เล่นไม่มีการควบคุมในช่วงเวลาถอยหลัง
  • ไม่มีการ จำกัด เวลาที่ใช้ในการย้อนกลับเราสามารถย้อนกลับไปจนถึงจุดเริ่มต้นของระดับได้ถ้าต้องการ

ตัวอย่างเช่น:

เฟรม 0-50: ผู้เล่นเคลื่อนที่ foward 20 หน่วยในเวลานี้ศัตรู 1 วางไข่ที่เฟรม 20 ศัตรู 1 ย้ายซ้าย 10 หน่วยระหว่างเฟรม 30-40 ผู้เล่นยิงกระสุนที่เฟรม 45 กระสุนเดินทาง 5 foward (45-50) และสังหารศัตรู 1 ที่ กรอบ 50

การย้อนกลับนี้จะเล่นแบบเรียลไทม์: ผู้เล่นย้ายไปข้างหลัง 20 ยูนิตในช่วงเวลานี้ศัตรู 1 ฟื้นขึ้นมาที่เฟรม 50 กระสุนปรากฏขึ้นอีกครั้งที่เฟรม 50 กระสุนเคลื่อนไปข้างหลัง 5 และหายไป (50-45) ศัตรูเคลื่อนย้ายออกไป 10 (40-30) กรอบ 20

เพียงแค่ดูการเคลื่อนไหวที่ฉันมีความคิดบางอย่างเกี่ยวกับวิธีการบรรลุเป้าหมายนี้ฉันคิดว่ามีอินเทอร์เฟซที่เปลี่ยนพฤติกรรมเมื่อเวลากำลังจะมาถึงหรือย้อนกลับ แทนที่จะทำสิ่งนี้:

void update()
{
    movement += new Vector(0,5);
}

ฉันจะทำสิ่งนี้:

public interface movement()
{
    public void move(Vector v, Entity e);
}

public class advance() implements movement
{
    public void move(Vector v, Entity e)
    {
            e.location += v;
    }
}


public class reverse() implements movement
{
    public void move(Vector v, Entity e)
    { 
        e.location -= v;
    }
}

public void update()
{
    moveLogic.move(new vector(5,0));
}

อย่างไรก็ตามฉันตระหนักว่าสิ่งนี้จะไม่ได้ประสิทธิภาพที่ดีที่สุดอย่างชาญฉลาดและจะกลายเป็นความซับซ้อนอย่างรวดเร็วสำหรับการกระทำที่ก้าวหน้ากว่า (เช่นการเคลื่อนไหวที่ราบรื่นไปตามเส้นทางโค้ง ฯลฯ )


1
ฉันไม่ได้ดูทั้งหมดนี้ (YouTube ตัวสั่นคลอน 1.5 ชั่วโมง)แต่บางทีอาจมีความคิดบางอย่างเกี่ยวกับ Jonathan Blow ที่ทำงานในเกม Braid ของเขา
MichaelHouse

สำเนาซ้ำที่เป็นไปได้ของgamedev.stackexchange.com/questions/15251/…
Hackworth

คำตอบ:


9

คุณอาจต้องการที่จะดูที่รูปแบบคำสั่ง

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

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

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

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

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


2
โปรดทราบว่าการย้อนกลับของการกระทำในเกมอาจเป็นเรื่องที่น่าประทับใจอย่างมากเนื่องจากปัญหาความแม่นยำจุดลอยตัวตัวแปรเวลา ฯลฯ การบันทึกสถานะนั้นปลอดภัยกว่าการสร้างขึ้นใหม่ในสถานการณ์ส่วนใหญ่
Steven Stadnicki

@StevenStadnicki บางที แต่เป็นไปได้แน่นอน จากด้านบนของหัวฉันนายพล C&C ทำเช่นนี้ มันมีรีเพลย์นานหลายชั่วโมงที่มีผู้เล่นสูงสุด 8 คนชั่งน้ำหนักที่ไม่กี่ร้อย kB ที่เลวร้ายที่สุดและเป็นวิธีที่ฉันเดาได้มากที่สุดถ้าไม่ใช่เกม RTS ทุกเกมที่ทำแบบผู้เล่นหลายคน: คุณไม่สามารถถ่ายทอดสถานะเต็มของเกมได้ ของหน่วยทุกเฟรมคุณต้องปล่อยให้เครื่องยนต์ทำการอัพเดท ดังนั้นใช่มันเป็นไปได้อย่างแน่นอน
Hackworth

3
Replay เป็นมากสิ่งที่แตกต่างจากการย้อนกลับเพราะการดำเนินงานที่มีอย่างต่อเนื่องไปข้างหน้าทำซ้ำได้ (เช่นการหาตำแหน่งที่กรอบ n, x_n โดยเริ่มต้นด้วย x_0 = 0 และการเพิ่มสันดอน v_n สำหรับแต่ละขั้นตอน) ไม่จำเป็นต้องย้อนกลับไปทำซ้ำ ; (x + v_n) -v_n ไม่เท่ากับ x ในคณิตศาสตร์เลขทศนิยม และง่ายที่จะพูดว่า 'หลีกเลี่ยงมัน' แต่คุณกำลังพูดถึงการยกเครื่องที่สมบูรณ์แบบรวมถึงการไม่สามารถใช้ห้องสมุดภายนอกจำนวนมากได้
Steven Stadnicki

1
สำหรับเกมบางเกมที่แนวทางของคุณอาจเป็นไปได้ แต่ AFAIK เกมส่วนใหญ่ที่ใช้การย้อนเวลาเนื่องจากกลไกกำลังใช้บางสิ่งบางอย่างใกล้เคียงกับแนวทาง Memento ของ OriginalDaemon ที่มีการบันทึกสถานะที่เกี่ยวข้องสำหรับทุกเฟรม
Steven Stadnicki

2
สิ่งที่เกี่ยวกับการกรอกลับโดยการคำนวณขั้นตอน แต่บันทึกเฟรมสำคัญทุกสองวินาที? ข้อผิดพลาดของคะแนนลอยไม่น่าจะสร้างความแตกต่างที่สำคัญในเพียงไม่กี่วินาที (ขึ้นอยู่กับความซับซ้อนแน่นอน) มันยังแสดงให้เห็นถึงการทำงานในการบีบอัดวิดีโอ: P
Tharwen

1

คุณสามารถดูรูปแบบของที่ระลึก; ความตั้งใจหลักของมันคือการดำเนินการเลิกทำ / ทำซ้ำโดยย้อนกลับสถานะวัตถุ แต่สำหรับเกมบางประเภทมันควรจะเพียงพอ

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


0

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

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


0

ในขณะนี้เป็นความคิดที่น่าสนใจ ฉันอยากจะแนะนำกับมัน

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

(1.1 + 3 - 3) == 1.1

ใน C และ C ++ อย่างน้อยจะส่งคืนค่าเท็จ ในขณะที่ความแตกต่างอาจมีขนาดเล็กลองนึกภาพว่าข้อผิดพลาดจำนวนมากสามารถสะสมที่ 60fps ในเวลา 10 วินาทีของนาที จะมีกรณีที่ผู้เล่นเพียงแค่พลาดอะไรบางอย่าง แต่มันฮิตในขณะที่เกมเล่นซ้ำไปข้างหลัง

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

หากเกมของคุณไม่ซับซ้อนเกินไปเพียงเก็บคีย์เฟรมของเกม 30 ครั้งต่อวินาทีและเล่นข้างหลัง หากคุณมีวัตถุ 15 ชิ้นที่มีตำแหน่ง 2D มันจะใช้เวลา 1.5 นาทีในการรับสูงถึง MB โดยไม่ต้องบีบอัด คอมพิวเตอร์มีหน่วยความจำกิกะไบต์

ดังนั้นอย่าซับซ้อนมากเกินไปมันจะไม่ง่ายที่จะเล่นเกมย้อนหลังและจะทำให้เกิดข้อผิดพลาดมากมาย

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