Replays

I worked on the sixth level this week, and got a surprising amount done — one or two weeks more at this rate and I should be on to the seventh level! Instead of showing that, I’m giving a huge ramble about implementing a replay system.

TL;DR

Bleed 2 might have replays, but it might not because they’re hard.

 

The Long Version

I think it’d be really cool if arcade mode runs got recorded and uploaded with your leaderboard entries. You could show off your moves, compare your play with your friends, or learn from high-level runs!

It’s hard to justify spending a lot of time on this, since 1: I’m not sure it’s a feature that really sells people or gets used much, and 2: it’s going to be difficult to implement — but that hasn’t stopped it from eating up a lot of my mental processes, because it’s such a fascinating puzzle to try to solve. I’ve done a bunch of research and planning on it, and here’s what I’ve got so far.

If replays were to be a thing, it would be the game recording your inputs every frame and saving them in a file. When it came time to play back the replay, it would run through the inputs stored in the file, essentially using them to play itself.

This presents two major hurdles, at least that I can see so far: the game would have to play the same way every time (to give the replays consistent results) and the input files would have to be kept as small as possible to avoid exploding peoples’ hard drives and internets.

Deterministic Gameplay

The first problem seems relatively easy… I’m sure it isn’t, but it seems that way right now. A random number generator (RNG) drives all of the random actions in Bleed. In case you’re not aware, an RNG is essentially (I believe) a mathematical formula. You give it a starting number, called a seed, and it uses the seed with the formula to create a giant sequence of numbers. The numbers seem random, but since it’s just a formula, using the same seed always results in the same set of numbers.

So, as long as you know what seed was used when the replay was recorded, you should be able to use it when playing back the replay to get the exact same numbers, to recreate the same sequence of events! Right? …right??

Storing Inputs

The second problem is more obviously tricky — you have to find the most optimized way to record every frame of input. In some cases it’s super easy — say, the jump button. It can only be either up or down every frame, so you can just use a boolean (a value holding “true” or “false”, 1 byte in memory) every frame for whether it’s being pressed or not.

But what about, say, the buttons that change weapons? You can hold as many weapons as you want in Bleed 2, in any order you want, so depending on your loadout, pressing “previous weapon” can have many different results. You can also switch loadouts mid-game, again changing the result of a “previous weapon” button press.

My solution is to give each weapon a unique number, and use that to remember which weapon the player is holding each frame. During replays, it’ll just assign the player the weapon that corresponds to that number. Easy! It also helps cut down on the replay file size, because instead of storing a boolean for “previous weapon” and “next weapon”, you only store one value for the current weapon — meaning you need 1 byte per frame instead of 2.

The final and most important optimization is for movement and shooting, using thumbsticks. Usually, thumbsticks are stored as a pair of decimal values — one value each for how far the thumbstick is pushed in the X and Y axis. The problem is that for two thumbsticks, this totals 16 bytes per frame — maybe not a ton, but I’d like to shrink it if I can.

Bleed 2 doesn’t care how far a thumbstick is pressed, only the direction it’s being pressed. If I think of the thumbstick’s direction as a degree on a circle, I only need a single, non-decimal number to store it, bringing the total memory usage from 16 bytes to 4 bytes per frame! It also means I can store PC inputs as well — I look at the direction Wryn is moving or shooting, and turn it into a degree-direction no matter what. Ta-daa!

Two ways of thinking about thumbstick directions.
Two ways of thinking about thumbstick directions. NOTE: Wow, I totally mislabeled the X and Y axis. I was pretty tired when I wrote this.

(One potential downside to this approach is that it limits the accuracy of the stored values. The smallest unit of measurement I can get this way is a 0.05th of a degree (aka one-twentieth of a degree)… which I really don’t think anyone will notice, but I guess you never know until you try it.)

The End

Ultimately, I can describe a frame of Bleed 2 input in 10 bytes, meaning even an hour-long replay would only take up about 2Mb, which seems like a reasonable size to me. Hopefully all this thought will pay off with a sick replay system, but I guess we’ll see if I have time to attempt putting it into practice!

Update: I continue working on replays in this post.