Ghost replay - การจัดเก็บและเวลา


11

ฉันกำลังเล่นเกมแข่งรถและเพิ่งใช้ผีสไปรต์เพื่อเล่นซ้ำการแข่งขันที่ผ่านมา ฉันใช้เครื่องมือฟิสิกส์และหลังจากอ่านมากฉันได้ข้อสรุปว่าวิธีที่ดีที่สุดในการจัดเก็บข้อมูลผีสำหรับการเล่นซ้ำจะเป็นการบันทึกตำแหน่งและการหมุนของรถตามเวลาที่ให้ไว้ตามตัวอย่างที่อธิบายไว้ที่นี่: https: // gamedev stackexchange.com/a/8380/26261

แต่จะเป็นวิธีที่ดีในการค้นหา timepoints เหล่านั้นในระหว่างการเล่นซ้ำอย่างไร ตัวอย่างจะเป็นบันทึกด้วยข้อมูลนี้:

time: +3.19932 (seconds since race start)
position:  180,40 (position at that time)
rotation: 30.4 (rotation at that time)

แต่ฉันมีปัญหาหลายประการ:

  1. เมื่อฉันเล่นซ้ำมันไม่น่าเป็นไปได้ที่ฉันจะได้รับไทม์พอยต์ที่แน่นอนที่ 3.19932 อีกครั้ง - มีโอกาสมากขึ้นที่ฉันจะมีไทม์พอยน์ประมาณ 3.1 และต้องค้นหาระเบียนที่ใกล้เคียงที่สุด เมื่อทำการสอดแทรกการจับคู่ที่ใกล้เคียงที่สุดที่อยู่ด้านบนและด้านล่าง ฟังดูไม่มีประสิทธิภาพและเสียเวลามาก?

  2. โครงสร้างรายการใดที่ฉันสามารถเก็บบันทึกเหล่านี้เพื่อเล่นซ้ำในภายหลัง อาร์เรย์หรือไม่ นั่นไม่ได้หมายความว่าเวลาค้นหาบันทึกที่ตรงกับเวลาที่แน่นอนจะเพิ่มการแข่งขันให้นานขึ้นหรือไม่?

  3. ฉันควรใช้ความถี่ใดสำหรับการจับเวลา แต่ละเฟรมจะเป็น - ฉันเดาว่า - มากไปหน่อย แต่ฉันควรบันทึกนั่นคือทุกเฟรมที่ n และการสอดแทรกระหว่างซึ่งทำให้คำถามที่เก็บใน 2 ยากขึ้น

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

ขอบคุณสำหรับความช่วยเหลือใด ๆ !

แก้ไข: ฉันรู้ว่าฉันควรอธิบายถึงสภาพแวดล้อมที่ฉันใช้: Cocos2D สำหรับ iPhone มีวิธีการupdate:(ccTime)deltaคือ ตามหลักการแล้ววิธีการนี้จะเรียกว่าทุกๆ 1/60 วินาที แต่ไม่มีการรับประกัน - deltaเป็นเวลาที่ผ่านไปจริงตั้งแต่เกมพนันสุดท้ายและอาจมากหรือน้อยกว่า 1/60 มันอยู่ในวิธีนี้ที่ฉันต้องการจะเก็บเกมมิ่งในปัจจุบัน


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

คำตอบ:


8

นั่นไม่ได้หมายความว่าเวลาค้นหาบันทึกที่ตรงกับเวลาที่แน่นอนจะเพิ่มการแข่งขันให้นานขึ้นหรือไม่?

ไม่ :)

สมมติว่าคุณจัดเก็บเป็นอาร์เรย์ (หมายเหตุภาพรวมอยู่ในลำดับตามลำดับ แต่ไม่เว้นระยะเท่ากัน):

snapshots = [
    {time: 0.0, position: {x,y,z}},
    {time: 0.41,    position: {x,y,z}},
    {time: 0.57,    position: {x,y,z}},
    {time: 1.10,    position: {x,y,z}},
    {time: 1.67,    position: {x,y,z}},
    {time: 2.05,    position: {x,y,z}},
    {time: 3.24,    position: {x,y,z}},
    {time: 3.86,    position: {x,y,z}},
    {time: 3.91,    position: {x,y,z}},
    {time: 5.42,    position: {x,y,z}},
    ...]

จากนั้นเมื่อเล่นซ้ำ / เกมเริ่มขึ้นคุณจะได้รับองค์ประกอบที่หนึ่งและสองจากอาร์เรย์:

nextIdx = 1
previousSnapshot = snapshots[nextIdx-1]
nextSnapshot = snapshots[nextIdx]

จากนั้นในแต่ละเฟรม ( currentTimeเป็นเวลาปัจจุบันในเกมใหม่นี้):

if currentTime > nextSnapshot.time
    nextIdx++
    previousSnapshot = snapshots[nextIdx-1]
    nextSnapshot = snapshots[nextIdx]

# Do your magic here, e.g.:
snapshotPairGap = nextSnapshot.time - previousSnapshot.time
ratio = (currentTime - previousSnapshot.time) / snapshotPairGap
ghostPosition = {
    x: previousSnapshot.position.x + ratio*(nextSnapshot.position.x - previousSnapshot.position.x)
    y: previousSnapshot.position.y + ratio*(nextSnapshot.position.y - previousSnapshot.position.y)
    z: previousSnapshot.position.z + ratio*(nextSnapshot.position.z - previousSnapshot.position.z)
}

แน่นอนว่าสิ่งนี้สามารถปรับให้เหมาะสมโดยการแคชการคำนวณบางอย่าง ไม่มีการค้นหาผ่านอาร์เรย์เพียงแค่ค้นหาดัชนีเฉพาะ


ใช่! ฉันต้องลองใช้ในภายหลัง แต่ดูเหมือนจะเป็นสิ่งที่ฉันกำลังมองหา ขอบคุณ !!
marimba

15

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

N | Time | Position | Rotation
1 | 0.05 | 1, 1, 1  | 0
2 | 0.15 | 1, 2, 1  | 0
3 | 0.25 | 1, 3, 2  | 30

ตอนนี้จินตนาการว่าคุณต้องการได้ตำแหน่งและการหมุน ณ เวลา 0.10 เนื่องจาก 0.10 อยู่ระหว่างคะแนน '1' (หมายถึง 0.05 เวลา) และ '2' (หมายถึง 0.15 เวลา) คุณจะต้องแก้ไขปัญหาเหล่านี้

timestamp = 0.10
factor = (timestamp - Time[1]) / (Time[2] - Time[1])
position = Lerp(Position[1], Position[2], factor)
rotation = Lerp(Rotation[1], Rotation[2], factor)

Lerpเป็นเพียงสอดแทรกเชิงเส้น

ลองเติมช่องว่างด้วยตัวอย่าง (*)

N | Time  | Position    | Rotation
1 | 0.05  | 1, 1,    1  | 0
* | 0.075 | 1, 1.25, 1  | 0
* | 0.10  | 1, 1.5,  1  | 0
2 | 0.15  | 1, 2,    1  | 0
* | 0.20  | 1, 2.5,  2  | 15
3 | 0.25  | 1, 3,    2  | 30

HTH


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

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

1
การค้นหาเชิงเส้นแบบง่าย ๆ อาจเหมาะกับคุณ แต่การค้นหาแบบไบนารี่จะดีกว่าเมื่อคุณมีอาร์เรย์ที่เรียงลำดับ: en.wikipedia.org/wiki/Binary_search_algorithm
Marcin Seredynski
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.