Dev Blog #3: ExileLord Rants
So one thing I’ve wanted to talk to the community about for a while is the new input system we’re working on in PNH. So before I go into detail on that, let me talk about the input system in Clone Hero, Guitar Hero, Rock Band, and pretty much every other game there is. I’m also just going to say Clone Hero from now on instead of “every other game out there” for the sake of brevity.
Now Clone Hero’s input system is frame based. That is, every frame, the input system is polled and that result is used for the hit logic. Awesome! So now what happens is, if you have a bad computer or just had a particularly bad lag spike, you have less frames to hit notes. This might be easier to visualize with a clip.
On the left, the game is running at 60fps and manages to process every input acceptably. On the right, the game is running at 10fps and you can see that in addition to dropping some inputs, it also appears to be lagging behind the game on the left. This means the left can do up to 60 inputs per seconds while the right can only do up to 10 inputs per second. That means it’s nearly impossible for the right side to hit any strumming faster than five notes per second and impossible to hit anything faster than ten notes per second. A frame dip like this is almost a guaranteed miss and that sucks.
So our input system in PNH isn’t frame based. It’s interrupt based. That is, every time you push a button on your controller, it doesn’t matter if you’re at the beginning or end of a frame, that input and the time it was pressed is immediately logged and put into an input queue. What this means is the game can process more inputs per second than there are frames per second. Inputs won’t be missed or dropped (unless your controller sucks but we can’t fix your controller, sorry). When the game has multiple inputs to process during a frame, it will execute the hit logic multiple times so multiple notes can be hit in a single frame.
Decoupling the game logic from frames also lets us do some other really cool things. Since we are recording the time each input takes place, we can also tell the game to play those inputs again. This is called the replay system and it’s something a few people have been asking for. This gives us three things that I’m gonna talk about.
The first is that users will be able to download/share their own replays on songs in case they weren’t a big time streamer who records every Soulless 5 attempt. So now instead of people complaining that you have no proof you can point to your perfect replay they’ll complain that you didn’t have a hands cam instead! But really, this is mostly just a little icing on the cake. Getting all this stuff is mostly a side effect of the more important things we get out of it. I wasn’t really heading out to design a full replay system for people to swap replays but we basically get it for free so there you go.
The second is that the server / leaderboards will be able to verify scores. When you submit a score to a leaderboard, the server will take your replay file and simulate it. It can do this because replay files are just a series of timed inputs and produce the same score every time. Then it will finalize your score on the leaderboard and provide a download for your replay so other people can judge you. This won’t stop someone extremely dedicated to cheating (Foiling a perfect “HelgaBot” would be difficult) but it will make it much more difficult than forging packets, running cheat engine, and similar. Plus we still have the replays so we can still take down bot scores if we’re sure that they’re bots! It beats the hell out of unreliable leaderboards right?
The third is that we can leverage this logic for online. One of the problems with Guitar Hero III and other rhythm games was that if you had laggy friends (or were simply going for a top coop score), you just couldn’t get great scores because it was impossible to activate “Star Power™” at the same time because of latency. This might be a bit hard to explain so I’ll try to use a diagram to help. Let’s say you and your friend xXx_BluSmoke_xXx are trying to get the top score on Slow Ride. Now what happens is you can both hit your notes perfectly but in the end it doesn’t matter because latency will prevent you from ever activating starpower at the right time. You and Smoke might activate at the same time but since you won’t see his activation until his slow packets get to you that means your activations are out of sync. This means some squeezes and activations were just impossible to hit unless you were physically sitting next to the person you were playing with. Now depending on the game, this could actually result in scores that are otherwise impossible (such as Guitar Hero III) which is obviously undesirable since lag should never have that big of an impact on a game.
Now that we have replays though, we can simply “rewind” our game and replay the laggy inputs we just got from our friend. Even if the packets were sent 200ms in the past, we can rewind our game and simulate them as if we received them in the past, ensuring that both of our games are perfectly in sync outside of the 200ms lag window where our games will temporarily have different states. Online co-op teams won’t have subpar scores compared to local co-op teams. All inputs are recorded and all inputs can be replayed.
To give a more concrete explanation let’s say that in our game, either player can activate starpower and it applies starpower to both players (this behavior was seen in Rock Band). At 60,000ms, you hit five notes, netting you 1,000 more points. At 60,200ms, you receive a packet from your buddy that he activated starpower at 59,995ms. Now your client rewinds unhitting those five notes you hit at 60,000ms. Your buddy Smoke’s starpower activation is processed applying starpower on your highway. Your five inputs at 60,000ms are re-simulated netting you 2,000 points instead of 1,000 since you were under starpower. Pretty cool right? The best part is that this logic is all generic and any new instruments we decide to add (keyboard, double guitar, etc.) don’t have to worry about managing rewinding and developing slower and being more error prone as a result. The logic just runs silently in the background.
Progress has been slow and steady but I hope the community can realize that we’re trying to make something new and better rather than Just Another Rhythm Game™. We’ve been keeping tight lipped since there isn’t a whole lot of cool stuff to demo like fancy graphics. I somehow doubt the community would be as excited as me to see unit tests passing but we have a lot of cool shit under the hood. There’s a lot of other cool stuff we’re working on that we don’t want to make promises about yet (we’re promising drums for example but we’re not sure about vocals since they’re non-trivial and I’m a bad singer).
Until next time,