Predicting Players: Calculated Level Design in Action Henk

Action Henk is a speedrunning platformer game in which the goal is to race through short levels as fast as possible to set the best time. Because the entire game is about keeping momentum, maintaining a constant flow is a key part of a smooth experience.

All movement is physics-based, meaning there are no hardcoded speeds, only forces constantly being applied to the characters during play. Based on their control of the mechanics, different players can have hugely-varied velocities on the same levels. Our challenge when designing these levels was how to space the ramps, blocks, and gaps in such a way that both beginning and veteran players can complete a level while maintaining that nice flow.

Enter the Player Predictor. The Player Predictor is basically a player physics object that only exists in the editor. Unlike Unity’s rigid body system which needs a running game to move, Action Henk’s physics system is written from scratch using Unity’s raycast & spherecast system. This allows for physics updates to be simulated from within the editor. We give the Player Predictor a starting point and specific moments to execute certain inputs (jump, run, slide), and it will calculate the resulting player motion.

The Player Predictor is providing updates in real-time while we drag the level blocks

This basic version of the Predictor already allows us to see if jumps are possible while we build them, or how exact player input needs to be in order to clear the jump. This was very helpful when designing the insane-difficulty levels for the end of the game, as we could easily create jumps requiring near-perfect input execution from the player, but still ensure they were technically possible to clear.

However, what we ideally wanted to achieve was a system that could determine a jump’s outcome for all possible player types in a single calculation. We improved the Predictor, and simulated player skill by adding randomness to every input moment. For example, not every player knows they should jump at the end of a ramp for maximum height, so we add a percentage chance for the Predictor to execute this input or not. Each player will also have slightly different timing for each jump, so a random factor is added to the precision of their timing.

The Predictor can now simulate specific situations as many times as needed, showing us the possible results of a huge number of potential player inputs and choices. This is what one of the early jumps looks like after 250 simulations:

250 simulations of a jump showing various paths players might experience

The resulting plot gives a good indication of the possible inputs and outcomes different players might experience. It’s like testing the jump 250 times with 250 people in a matter of seconds! The plot also clearly shows areas players will almost never pass through, no matter how skilled (or not) they are. We can then add different level geometry in these areas, creating alternate paths for players to utilize as their skill increases. Here’s another simulation of that same jump but now with extra landing paths.

250 simulations of a jump with added landing paths

As shown in the image, the player now has an opportunity to land nicely every time. One route will take more overall time than the other, but the landing ramps are placed in such a way that no matter the skill of the player, they will always maintain their sweet butt-sliding flow!

Roel Ezendam
Roel Ezendam
Roel Ezendam is Game Programmer and Co-Founder of RageSquid, a young studio based in Utrecht, The Netherlands.

Related articles