Introduction
This blog post primarily explains how I created “Head Shot” and how I implemented the rollback.
Head Shot is a small online game developed for the SAE Institute.
Head Shot is a “Head-soccer like” game, 2 players can shoot a ball and score goals with it. A game lasts 1:30 minutes at the end of the time the player having the highest score wins.
The project was done in the scope of 1 month.
A match played in real conditions
Goals
Make a realtime responsive online multiplayer game.
Implement a rollback engine.
Using
Head Shot uses:
- The raylib library to render and to play sounds.
- The Bark physics engine developped by myself to simulate the physics.
- The Photon library for the netorking
Architecture
The main application handles the networking, the rollback, the game logic and the rendering.
The rollback engine has access to the current game and handles the confirm game.

Game Logic
General
Instead of creating complex architecture for the game logic I decided to include all the needed elements into the game class directly.
It made my life a lot easier when I started implementing the rollback engine.
Here are some examples, the details are in the comments:


Inputs
To handle the inputs, I store them in a single byte using bit-shifting, it makes the input packets smaller to send them to the other player.

Then with some basic logic I process the inputs retrieved each frame.

Copy method
For the rollback to work properly I have to copy the confirm game state into the current game state before doing a rollback.
To ensure that all needed data is copied properly I copy it manually.
Because the contact listener handles a pointer to the logic I have to set it again each time, otherwise it makes the game non deterministic for both players.

Networking

I overrided all the needed functions from the photon lib, here I will show the ones that I use for the netcode of the game.
ReceiveEvent
When a client received a packet, it stores it in a queue.
Then, at the start of a frame the client loops throught all the packets, handles them and pops them.

joinRoomEventAction
When the first player joins a room (rooms are entirely handled by photon), his id is set to 0.
When the second player joins a room, his id is set to 1, the game can start for both player and the rollback engine is setup aswell.

Rollback engine
To implement the rollback engine, I decided to implement the rollback first and then add the confirm frame to it
Rollback
Here is the implementation of my rollback method.

When running the simulation, after some time the game started to lag a lot.
It was due to the lack of the confirm frame.
In fact, when I profiled the sim, the game was rollbacking each frame from the very first frame of the game.

Confirm frame
Here is the implementation of my method to confirm the frame.

After adding the logic to confirm the frame and stop rollbacking from the very first frame, the game stopped lagging and I could test the simulation until the end.
After fixing some really small bugs, I couldn’t make a single crash happen !!! I’m pretty sure my implementation is fine !
Here we can see that the game rollbacked trice within a frame and that the program handles it without problems and can handle a lot more.

I calculated that my program can handle approximatively 16 seconds of rollback.
Yes it is overkill but it proves it works well !!
Rendering
I thought that making the game playable in a web browser could be a good idea, that is why I chose raylib to render my game because it is compatible with empscripten and seamed easy to use.
The web build still needs to be done.
Conclusion
In conclusion, creating “Head Shot” was a rewarding experience that showcased the integration of raylib, Bark, and Photon libraries.
Implementing the rollback engine and confirm frame was crucial for maintaining smooth, real-time gameplay and resolving performance issues.
The game runs without significant lags or crashes, indicating a successful and stable rollback mechanism.
The next step is to finalize the web build and to maybe add some fun features :)
Thank you for reading so far !!!
I honestly hope, you enjoyed it :)