My exploration of multiplayer web-based game development as a non-game developer

Nov 30, 2024

What's it all about?

I always admired how games like agar.io and slither.io are simple yet successful at retaining players. As my main stack being JS/TS, I wanted to see if I can develop a multiplayer game.

The thing I imagine

I'm a total stranger to game design and development and I'm only interested in the tech part. So it can be a silly and unbalanced game, but I wanted to achieve:

  • A lobby logic
  • A real-time game experience
  • A canvas where players interact with each other or other elements

I started see what I can start with. My best guess at that moment for the requirements were:

  • A game server and a client
  • Server should
    • store a collection of ongoing game sessions, each element relating a game ID and the state of the corresponding game session
    • there should be a game loop that should only be executed for the game sessions started, ticking nearly at 16.67ms for a 60FPS game experience
    • the game loop should update a game according to the inputs collected from each game client, evaluate non-player mechanics with them and calculate the new state
    • send the calculated game state back to the clients
    • cleans up the game sessions if all players leave or the game is over
  • Client should
    • Request to create/join game sessions
    • Render the game state received from the server
    • Collect user inputs and send them to the server

Colyseus: Multiplayer game server framework

After some experiments with Express.js, I decided that it will be cumbersome to discover and test with all the work I need to do and found Colyeus.

It is a nice framework that can be used for various needs, from turn-based to real-time and can handle most of the boring stuff eg. game room logic, game loops, and types for TypeScript.

Phaser: JavaScript game framework

I could also work with a plain HTML canvas, a plain JS client and consume a Colyseus backend easily. I'm already using Cursor, so I could feed the Colyseus docs into a doc index, open the composer, type "consume this game backend" and voi la!

In fact, I did that exact thing and it was OKish, but not that great. Using assets from a stripe images was basically hell. Fast-moving elements was flashing, adding any effect was slowing it down, simulating slow networks with Chrome DevTools caused a disaster, and although Cursor composer is quite successful at coming up with a solution for the each visual effect I prompted, they were not consistent in style.

Then I found this cross-tutorial, exactly what I sought for.

In the second part I'll dive into the implementation. Spoiler: I wired them inside a Turbo monorepo.

But first I probably need to add remark-gfm support to this Next.js MDX blog starter so that I have proper highlighting for all the code.