Long time Ruby/Rails developer who has been working on a strategy multiplayer game in Unity.
I’ve got a use case here using a very simplified game idea and wanted to see if Elixir/Phoenix would work for some or all of it. I broke it out into sections to hopefully allow me to articulate the various use cases in a meaningful and objective way.
Imagine a game that is Chess but massive-multiplayer - that is to say, you could have 1000 players playing on the same chess board against each other. Each player has their own set of pieces (rook, king, queen, etc). Each player would start somewhere on a large-enough board (so imagine a 1000x1000 grid).
Ignoring the obvious difficulties with modifying the ubiquitous chess rules to support this, the only mechanic you need to understand is this:
- all 1000 players will submit a move within 30 seconds to the game server (aka a round)
- at the 30 second mark, the game server will process every submitted move and calculate the result and update the state of the game
- the game server will send the result back to all clients and the clients will be responsible for the ensuing animations and so forth
As an aside - the mechanic above is often referred to as “simultaneous turn” which is in the middle of the spectrum between turn-based and real-time. I could have used tic-tac-toe, connect 4 or any number of games out there as an example, so please don’t get caught up on this.
Section 1: Multiplayer usual suspects - login, chat, lobby, etc.
I don’t think this will be contentious in any way - but user authentication, chatting, lobby, game finding shouldn’t pose any issue for Phoenix/Elixir.
Section 2: Client/Server communication and scale
The client would be Unity (C#) and it could simply use https and json to submit their moves to the server. Or web sockets or anything else. The move could be as simple as “Player #234, move Knight to E23”.
Note that the move will be persisted into the database to be processed later (Section 3 below).
I don’t think there would be any issue with using Phoenix/Elixir, even if you had to scale to 10,000 players or 100,000 players.
Section 3: Game server - processing user moves and calculating the result
This is really the crux of my question. Things to note:
- The state of the chess board would be stored in the database.
- As users submit their moves, they would get persisted to the database.
- When the 30 seconds are up, the server will process all available moves (in the database) against the state of the chess board and generate a result set.
- The state of the chess board will be updated in the database.
- The result set will be sent back to all clients.
This is where the rules of the game need to be codified in Elixir using functional programming rather than traditional OOP.
The calculation of the outcome for the round in this game would probably be CPU and definitely memory intensive. Not only would you need to store the state of the chess board in memory, you would also need to access the data objects of all the units on this board as they impact the calculations.
Section 4: Game server - AI implementation
There are two cases here:
- for players who do not successful submit a move in the 30 seconds then a move will be generated for you.
- computer players can also be one of the 1000 players playing
Again, this would be CPU and memory intensive. Looking at traditional AI, you would have in-memory representations of the game state to help calculate the best move based on some sort of score/criteria.
Section 5: Game server - Performance and Scaling for multiple concurrent games
I’m guessing but perhaps the best approach here to support 3 or 4 concurrent games with 1000 players each would be to have a “instanced server” for each.
When a game starts, you would fire up a new server instance with its own micro-database to store the state of the game as it plays out. Clients would access this server directly.
Is this possible with phoenix? I guess it might not be a phoenix question but more of a dev-ops/docker/container question.
And that’s it… if you made it this far, thanks for being patient!