Building a multiplayer game in Phoenix LiveView
Over the past two months, I’ve been working on learning the Phoenix LiveView framework by building a complex multiplayer online game. In this post, I’ll talk a bit about the benefits of this framework, and give a quick overview of the game architecture and processes I’ve developed.
What is Phoenix LiveView?
The Phoenix LiveView framework offers a couple of major benefits for both application users and developers:
- Performance: WebSockets create a bi-directional, always-open connection between the browser and the server, which means that information can be sent back and forth with very low latency.
- Developer productivity: Rather than writing a complex frontend and a server API (with all of the associated documentation and protocols), the developer can focus entirely on writing and polishing server-side code. Reliance on the server also eliminates duplication of business logic between the server and frontend, which means less room for error and inconsistency in the way interactions are handled.
Learning Phoenix LiveView
To learn Phoenix LiveView, I decided to build a clone of an existing real-time multiplayer game. I settled on replicating generals.io, a strategy game with a simple visual interface and the following logic and rules:
- There are between two and eight players per game.
- The game waits for players to join before starting. Play begins when either (1) there are eight players, (2) there are two or more players who’ve been waiting for 2+ minutes, or (3) there are two or more players and any player requests to start the game.
- Players move around a grid to capture territory and accumulate points; there are different types of grid cells, with a range of values. Capturing another player’s “home base” cell results in the acquisition of all of their territory.
- Each player has a limited view of the grid cells surrounding their current location.
- Any player can leave at any time, either by formally surrendering or by leaving the browser window.
- Standings are tracked on a leaderboard; once the game starts, all players will remain on the leaderboard, even if they leave the game.
- Player movements are controlled with keyboard and mouse interactions, and positions are updated every 400ms.
Here’s a simple diagram showing the architecture I used to replicate the game:
In this example, there are four players who’ve been allocated to two different games. The two games are completely isolated — each has its own state, including the grid configuration, points, and leaderboard.
If a new player were to sign in, the “game manager” would determine whether there was an existing game that that player could join; if all games were already in progress, the manager would create a new game for the new player. If a player were to leave, the “observer” would receive that player’s data and update the game to account for the departure.
Within each game, interactions proceed through the following set of steps:
- Say I want to move left. I press “A” on the keyboard, which sends a message to the browser; the browser then sends information about the requested move to the server
- The player process (running on the server) determines whether the move is allowed in the game logic (i.e., it checks to determine whether I’m moving into an obstacle or off the board).
- If the move is allowed, the game state is updated accordingly, and the new state is broadcast to each player process.
- The browser receives the updated state and adjusts each player’s view to account for the change. Depending on their perspective, players may or may not see a visible change in the board.
I’ve put about 80 total hours into developing my version of generals.io, and it’s close to feature-complete — players can join, choose paths, and surrender, and player stats are updated continuously on the leaderboard. Building the game has been a great experience, and required me to learn (or re-learn) a variety of languages and technologies. I’ve also felt very focused and productive working exclusively with server-side code.
Personally, I’m looking forward to continuing to work in Phoenix LiveView. I’d like to add features to my version of generals.io, including user authentication, an admin interface, tournament hosting, and potentially even native mobile support. I’d also like to experiment with building more multiplayer and single-player games using this framework.
More generally, I expect we’ll see increased adoption of Phoenix LiveView and similar frameworks across all areas of development. This technology has the potential to significantly change the economics of building browser-based applications — not only games, but also any other application (issue trackers, social feeds, etc.) that benefits from real-time updates.