FiveFeathers – Multiplayer Pirate Game


We’re back! After two long years, a new game has been developed by (old and new) members of the Impossibru team! It’s still a DEMO version, but we are proud of what we accomplished in these four months of development.


We, three students studying Interactive Media and Digital Arts at University of Applied Sciences Hagenberg, implemented a multiplayer game to be played on state-of-the-art smartphones and tablets. We decided on a pirate theme, where the players would take the roles of a pirate crew on a ship, and guide them through the seas, overcoming various obstacles on their way. There should be different tasks on the ship, which need to be completed by the players in order to survive and reach land. The total number of these tasks has to be at least 1 higher than the number of players, so every player has to do different tasks at different times, and not the same task all the time.

The multiplayer gameplay should take place locally, players would need to be in the same location while playing the game and coordinate with each other without in-game chat services.

For the project to be interesting from a technical point, we wanted the number of players in the game to be able to change dynamically, which means all players, including the one who started the game can enter and leave the game at any time. The difficulty, frequency and amount of different tasks which have to be completed by the players should scale dynamically with the number of players.


  • Mobile multiplayer game (2-5 players)
  • Cross-platform (Android, iOS, Windows Phone, Windows, Linux, OS X)
  • Real-time multiplayer
  • Local connection (WLAN)
  • Players can enter/leave at any time
  • No global game state (server)
  • 2D graphics
  • Touchscreen & sensor controls

Implementation Experiences

Multi-platform, 1 codebase

To avoid having to implement the game for multiple mobile platforms, a multi-platform game engine was needed. We decided to use the Qt platform and V-Play Game Engine, because it specializes in 2D games.


With V-Play, games are implemented mainly in QML (Qt Meta/Modeling Language) and JavaScript, but also C++ can be used for low-level and performance critical tasks (for example, the UDP messages needed to be sent and received with C++).

Find games in local network

To detect other players in local network, a system using UDP broadcast was implemented. This way, the players only have to be in the same network (using WLAN für mobile devices) to find each other.

A UDP package is sent to a well-defined port to all devices in the local network. When the game is running on one of these devices, it will receive the package and send an answer, so the sender knows where the game is running also.

Additionally, meta-data about the game, like how many players are connected, can be sent via the broadcast package.

The actual connections between players are down using Qt’s WebSockets over HTTP, sending JSON messages.


Synchronize actions to each connected player

To avoid having a global game server, which manages the game state, a decentralized approach was implemented. It is an adaptation of the “Lock-Step” system implemented in the first Age of Empires game (see here for details – special thanks to a certain awesome brother who suggested this approach to us!).

Every connected player knows about the whole game state at all time, and when an action occurs from one player, it is sent to all other players and executed at the same time on all devices. This way, all players share exactly the same game state at all times.

The “Lock-Step” approach ensures that these actions are executed in the same order at the same in-game time, by assigning an ID number to the current game step, and only accepting and executing actions coming from this time step, and only advancing the time step when a message from all other players has been received. This also implies that when only one players has a slow connection, all other players also have to wait for them.

Allow pirates to find their way on the ship without getting stuck

To allow players to select any location on the ship and have their pirate automatically walk there, we have implemented a pathfinding algorithm, which works similar to what is implemented in the Elders Scrolls Series from the third installment onwards.

A graph with connected nodes describes possible path on the ship, with each node containing a list of its neighbours. Each neighbour has to be reachable in a straight line, without any obstacles. To find a path from point A to B, the nearest, non obstructed node to each point is selected, and then Dijkstra’s algorithm is used to find the shortest path between those nodes in the graph, which is then followed by the controlled pirate.

However, if point A and B can be connected via a straight line, no pathfinding occurs and the pirate simply walks there. To check, if two points can be connected without obstruction, a raycast using the Box2D pyhsics engine is performed, to detect any colliders along the desired path. Since there are no dynamic obstacles on the ship, this simple approach leads to fast and lightweight path finding.


Synchronize an arbitrary amount of minigame states

Since we have planned quite a few mini games, which all have different states that need to be synchronized, we needed to come up with a way to encapsulate each state and query them, so the states can be sent to each new player and updated, if anything changes.

To do this, each minigame is represented by a mini game entity, which can easily be collected via the supplied V-Play entity manager and each of those entities can serialize the current state into a json object. This object is, along with the id of the mini game, sent to each player and processed by the corresponding mini game entity to update the state for each player. This ensures we do not need to know the amount of minigames and how their state is made up, as each entity manages serialization and deserialization on its own.

Additionally, when a new player connects to the game, the current states of all minigames are sent to this player as part of the “welcome” message.


Minigame Design

Our initial plan was for the game to include multiple minigames for the players to complete while on their trip with the pirate ship. It turned out harder than we thought, to design these minigames to be challenging and fun at the same time for multiple players.

We then strengthened our efforts for 3 of the planned minigames, to be able to implement them fully. Unfortunately, this did take a lot of our time, so we had to drop all other minigames for this semester’s project.

The three games which did get implemented are the cannon, where one player has to fight the attacking kraken with cannon balls, the storage room, where one player can retrieve cannon balls to recharge the cannons, and the crow’s nest, where one player can spot attacking enemies.


We had ideas for other mini games, but did not have time to implement them, including a sea map, where hazards for the ship can be spotted, a steering wheel, to circumvent these hazards, the sails which needed to be taken down when a storm would hit the ship, the ability to repair the ship when it got damaged, and more.

The fact that only three minigames were implemented means that no more than two players could play the game at one time, so it would still be challenging, despite the fact that the game was initially planned to be played by two to five players. If more minigames would be added at a later time, also the maximum number of players could be set higher, as the basic system for dynamic number of players is already implemented.

Lockstep sync interval limits

Due to the fact, that on each sync step, every player has to send and receive a message to/from each player, the bandwidth and complexity increases drastically with each player (number of connections is proportional to number of players squared).

This forced a maximum amount of synchronizations per second, that we could achieve during a five player game. For our game situation, we used 10 messages per second, which mostly worked out fine, but a noticeable lag between a player action and the games reaction could be observed, if one or more players miss a sync step due to network or performance issues, if the sync interval is set too short (player cannot keep up) or too long (the time until the next step is too long).

Lessons learned

More prototypes and tests during pre-production

We have created about six prototypes during pre production, which have been tested by a few players to some extent. It turned out, that we should have created more of them and let more users try them, to generate more feedback and catch any game mechanics that are boring or serve no real purpose earlier during development. Reworking or completely rethinking some of the mini games late in development lead us to cutting the amount of games back to three.

Pros/Cons of decentralized multiplayer

Decentralized multiplayer helps maintaining a shared game state across multiple devices without the need for a global game state manager. Every player, including the first one to create the game can leave at any time and the game can still be continued.

However, it introduces a lot of managing overhead to the programming of the game, which needs to be considered. It took us about one third of the whole time we had for the project to finish the network layer, before we could start implementing the actual game.

On the plus side, this network module could also be used as stand-alone module for a new project, if it fits the requirements of a low number of players and good connection (preferably local network).



Currently, the DEMO version of the game can be played on Windows machines. Download here:

The game needs to be played by 2 players connected via local network (LAN) – if you’re alone, it will be pretty lonely on the pirate ship 😉

The DEMO will also be available in Google Play Store, where we are currently beta testing. If you have an Android device and would like to test, send us a quick message!

As we are still developing, feedback is always welcome!