6 ms·
This is how the time travel mechanics of Braid were implemented. Record the events, apply those events in a deterministic manner, and then reverse the events to
by hartror 11y ago
This is how the time travel mechanics of Braid were implemented. Record the events, apply those events in a deterministic manner, and then reverse the events to go backwards in time.
More generally this is pretty much the event sourcing pattern: http://martinfowler.com/eaaDev/EventSourcing.html http://martinfowler.com/eaaDev/EventSourcing.html
- jblow 11y agoNot true, mostly. I recorded world state, not events. The one exception is world 5 where I record events so that your shadow-universe guy can do things. Event recording has a fair bit of history in games, especially as a debugging technique, but I did not want to use it for rewind, considering it too fragile and annoying, and probably too expensive and complicated (you would have had to store world state anyway, to have something nearby to delta from so that you don't start from the beginning of time every frame, so now you have TWO systems: world state recording and event recording. Better to stick with one.)
- Negative1 11y agoCan you elaborate on the distinction between world state and events? As in, you don't capture user inputs but rather track all object positions and states at all times? seems very inefficient that way. Also, big fan! Great work on the new language/compiler livecasts and can't wait for The Witness.
- jblow 11y agoExactly: I record the positions of all objects every frame (and other state variables), not the inputs that generated them. It is more expensive in terms of the amount of memory required, but it is much less expensive in terms of the amount of CPU required, and CPU was ultimately the biggest problem, so it seems I made the right decisions. Even on a limited-memory console like the Xbox 360 you can rewind most levels for 30-45 minutes before running out of buffer. That is more than anyone ever wants to do as a practical gameplay interaction. Working on The Witness... it will be done ... someday not too long from now.
- baddox 11y agoOut curiosity, what happens if you run out of buffer?
- nightpool 11y agoTheoretically, you probably just want to kick the stuff at the end out. (i.e. you lose the earliest state you can)
- seanmcdirmid 11y agoThat would be a cool game mechanic: you can freeze time and fine tune your behavior over a small window of the immediate past(e.g. the last two seconds), with the ability to see how the game changes over that window "strobe style." Sort of like Sherlock Holmes (in the movie where he thinks everything through "what if" style).
- fho 11y agoThat's basically the mechanic in the game Frozen Synapse: http://www.frozensynapse.com/ http://www.frozensynapse.com/ Every player plans their movements for the next fraction of a second and all turns get executed simultaneously.
- seanmcdirmid 11y agoI was thinking of a one player game against the computer, so the player can actually see what the computer will do according to their planned action.
- jblow 11y agoIn most worlds, the oldest state just gets thrown out; you keep playing as usual, it's just that if you were then to try and rewind all the way to the beginning, there would be a limit on how far you can go. In world 4, though, where you can walk to the beginning of time just by walking to the leftmost part of the level, I actually kick the player out of the level when there's no more memory. I have never heard of anyone noticing this.
- frik 11y agoIt's efficient enough, given its a 2D plattform jump&run game. The developer wrote an extensive article how it works, it's really interesting, search for it. Game creator Jonathan Blow explains the rewind in a video (27min): http://www.youtube.com/watch?v=tSeYShR-OG0 http://www.youtube.com/watch?v=tSeYShR-OG0 And there is Gamasutra article about Rewind, in four parts: http://gamasutra.com/blogs/CameronLeBlanc/20130220/187036/Recreating_the_time_mechanics_of_Braid_Part_1.php http://gamasutra.com/blogs/CameronLeBlanc/20130220/187036/Re... and part 2-3: http://www.gamasutra.com/blogs/CameronLeBlanc/20130313/188444/Recreating_the_time_mechanics_of_Braid_Part_2.php http://www.gamasutra.com/blogs/CameronLeBlanc/20130313/18844...
- nightpool 11y agoYou're replying to jonathan blow ;) EDIT: to be clear, the GP of your comment is jblow, not the parent.
- seanmcdirmid 11y agoThis is how Glitch works (my programming model for time management): http://research.microsoft.com/en-us/people/smcdirm/managedtime.aspx http://research.microsoft.com/en-us/people/smcdirm/managedti... If you modify the past, events are recorded and replayed, however (just rewinding focuses on a different world state). This is all baked in directly to the programming model. Another thing we are able to do is capture deltas rather than do entire world checkpoints, which works out well since many states do not change on all time steps (except for that moving bullet, of course). So each cell has multiple entries of temporally scoped values (for values that change on every frame, they just have one for each frame).
- lectrick 11y agoIf you could make all events reversible (exactly), then why would you need to rewind to state 1 and play back to the requested time for every frame? Also, sweet game! I actually just introduced it to my gf last week.
- seanmcdirmid 11y agoSomeone has implemented a PL based on this circa 1982: https://78462f86-a-feb80ac8-s-sites.googlegroups.com/a/tetsuo.jp/www/ref/janus.pdf?attachauth=ANoY7cq1LCaz4ks62hzf1AqyYgcMhs09w7i91jLsYAGlL4cYcqDFwEBgLajcf29wkMIIkC4ckYqy92cV5veO3kSKns5xkaXKuiLmPRxHbBk7543SNrZZlm9zZU3y6xs4SODi2hvL-a0ngXaIMZnuftfwvHQrIzCHXDZoZEB1BrYUVPymJyUN4brpW9rqR5lErD4os9LB69CZ&attredirects=0 https://78462f86-a-feb80ac8-s-sites.googlegroups.com/a/tetsu... It is not very practical, however. Many operations that you'd want to do are not time reversible without saving things.
- jacquesm 11y agoThat's interesting. So, is a time-reversible language Turing complete? How would one write a trap-door function in a time-reversible language?
- seanmcdirmid 11y agoYes, but at a non trivial cost, see http://www.math.ucsd.edu/~sbuss/CourseWeb/Math268_2013W/Bennett_Tradeoffs.pdf http://www.math.ucsd.edu/~sbuss/CourseWeb/Math268_2013W/Benn...
- jblow 11y agoYou could do that, but then you aren't storing events any more, you're storing world state again. (That is what it means to make events reversible .. or at least that is the straightforward way I would think to do it.)
- lectrick 11y agoIt reminded me of Martin Fowler's "Event Sourcing" paper from the enterprise world http://martinfowler.com/eaaDev/EventSourcing.html http://martinfowler.com/eaaDev/EventSourcing.html So as a bluntly simple example, assume the entire world's state is just the number 100. Instead of storing 105 as the new state, you store {:increment, 5}, and somewhere, the reversible counterpart to increment is defined {:decrement, 5}. You're correct that a full global state would have to be stored at SOME point, but could you simply hold the initial state, and the current state, and work from either of those? Or just do what the mp4 video algorithm does and store so-called "keyframes" every N frames which store the entire state, but all intermediary frames are just diff frames. Many web apps end up needing a global event feed/stream that various processes hook into via publish/subscribe. In theory, these events are reversible. Of course, in practice, individual types of events may find difficulty, especially if they have side effects that are outside the control of the app developer
- hartror 11y agoI stand corrected! Could have sworn I'd read the eventing method was used but obviously not. Thanks for the comment Jonathan, big fan.
- Kiro 11y agoAre you just speculating or did you read this somewhere? You make it sound like fact until the creator of Braid comes in and says it ain't so.
- hartror 11y agoI thought I had read it somewhere, but obviously not.