Why save replays?
I’ve personally spent a ton of time watching people play The Binding of Isaac (and a good many other games) on youTube, so I have a lot of fondness for the Let’s Play community. Eyes Open is a short game meant to be replayed multiple times in a row, and in my opinion it’s going to lend itself well to this genre of video.
There’s a problem though : you spend a lot of time with your eyes closed, which means for a lot of the game it’s tough to see what’s going on – and frustrating to watch. Spectator Mode was and is designed to alleviate this problem. We’re still in very experimental stages with the system; to be honest I’ve coded enough to be sure that it will work in the final game, and left it at that. There’s a lot more to do with the game, so I didn’t want to focus on it too early.
Basically, what Spectator Mode does is save a play-session in a format that can be replayed and re-recorded later. When the sessions are replayed, they can be rendered in a different view: one that doesn’t black out the screen when your eyes are closed and that could contain some additional information about the monsters and environments the player is going through.
It’s not a perfect solution, but it leaves a lot of flexibility to the recorder to edit, re-comment, splice the two views together, or just sync up their audio and use one view or the other.
I’d like to experiment with more support for actual streaming, maybe by taking a look at the Twitch.tv game API’s, but that’s a whole new area that I won’t venture into until Spectator Mode is working perfectly with its base functionality.
How does it work?
Rather than record what’s happening on the screen, we record the choices that the character makes. Then, when the session is restarted, we load up all of the data and re-simulate the level. In simpler terms, the engine saves what the player does, then when the replay is selected, it does it again.
We try and compress everything down to its most simple form when saving data – it helps keep space requirements down and makes the whole thing a lot easier for your computer to handle. What is the most basic choice that a player is making at any point during the game?
- to press a key or release a key.
Every single update-cycle of the game, we check to see what keys are down, which is very easy to do. We could save the what keys are down every single frame, but that would be wildly inefficient, so instead, the engine only records data when the keys that you press actively change.
Say that you start the game out and you press the up button to start traveling out of the room. A couple seconds later, you press the space button to close your eyes. Then lets say you release both buttons and just look around for a little while.
Our engine would record each of those events: At frame 1 up is pressed, at frame 80 space is pressed, at frame 130 up and space are released. If the engine later sticks you in the same situation and repeats those actions exactly, you’ll end up taking the same route and doing the same stuff, every time.
How does “random” work on a computer?
Of course, there’s one other thing we need to save called a seed. What this boils down to is that computers handle random numbers differently than people do. They try and find one single random element (usually it’s based on what the current time is when you start an application) that they can then use to extrapolate a whole bunch of other random numbers off of.
The gist of this is that if we save what that random element is (called a seed), then we can get the same random numbers two times in a row. If you’ve ever played a game like XCom or Battle For Wesnoth and had difficulty getting different results when you reload a save-game, it might have something to do with this: the game saves it’s seed to make it harder to cheat by just repeating the same action over and over and hoping to get a different result.
Our AI uses a mixture of randomness and player interaction to determine what it does. I’ve already talked about how we can repeat what a player does in the replay. If we save the seed that was used when the player started a game, we can also repeat the other element of the game: the randomness.
Put the two together and you have a saved playsession that is really tiny and easy to store, and can be re-rendered in just about any view the player wants.