Skip to content

About

Fork of Defold's Platformer Multiplayer Game Sample using Colyseus 0.18

Resources

Stars

2 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

Colyseus Platformer Game Sample

A small multiplayer 3D platformer built with Defold and Colyseus 0.18, using the colyseus-defold SDK. The game server is authoritative over the game rules (coins, rounds, falling platforms), while each client simulates its own character with Defold's physics and streams its transform to the server.

Play it online — the hosted HTML5 build connects to wss://demos.colyseus.cloud/defold-platformer; the PLAY OFFLINE button works without any server.

See the platformer manual for information about game-specific features such as movement, camera behavior, animation, and rendering.

Colyseus features in use

Run the server

The authoritative server lives in server/ (TypeScript, Node.js 22+):

cd server
npm install
npm run dev

The server listens on ws://localhost:2567. While it runs:

  • http://localhost:2567/health — health check endpoint
  • http://localhost:2567/playground — Colyseus playground (dev only)
  • http://localhost:2567/monitor — Colyseus monitor (dev only)

npm run smoke boots a temporary server instance and exercises the whole protocol (matchmaking, transform streaming, coins, rounds, platforms) without the Defold client. npm run check type-checks.

Run the game

  1. Open the project in Defold and run Project -> Fetch Libraries once to download the dependencies.
  2. Start the server (see above).
  3. Run the game (Project -> Build).

The server endpoint is read from game.project under the [colyseus] section and defaults to ws://127.0.0.1:2567. To point a build at another server, change the endpoint setting, or override it per machine without touching the file:

--config=colyseus.endpoint=wss://your-server.example.com

Enter a room name to join or create that room; clients using the same room name play together (the platformer room type is partitioned by room name via filterBy). A username is generated randomly and can be edited.

You can also play without a server by clicking the PLAY OFFLINE button.

Build the HTML5 version

Build the HTML5 version (Project -> Build HTML5) to test it in a web browser, or serve a bundle (Project -> Bundle -> HTML5 Application) from the bundle directory, for example:

python3 -m http.server 8765 --bind 127.0.0.1 --directory dist/wasm-web/ColyseusPlatformer

Then open http://127.0.0.1:8765/ in the browser. After rebuilding, restart the HTTP server in the new bundle directory and hard-refresh the browser with Ctrl+Shift+R so that it does not load an older cached archive.

Note that pages served over https:// can only connect to wss:// endpoints, so a deployed HTML5 build needs a TLS-terminated server endpoint.

Rebuild the hosted demo (docs/)

GitHub Pages serves the build committed in docs/, which targets the shared demo server (pages.settings overrides the endpoint). To regenerate it headlessly with bob 1.13.1+:

java -jar bob.jar --archive --platform=wasm-web \
     --variant release --settings pages.settings \
     --bundle-output dist/pages resolve build bundle
rm -rf docs && cp -R dist/pages/ColyseusPlatformer docs

Diagnostics overlay

Press the L key to toggle the diagnostics overlay. It shows the room and session ids, player count, measured RTT and jitter, the patch interval, and the synchronized server clock.

Session startup

The connection flow is implemented in game/lobby/lobby.script:

  1. colyseus.Client(endpoint) creates the client.
  2. client:join_or_create("platformer", options, callback) joins (or creates) the room, passing the username, room name, and character variant as join options.
  3. The Defold game collection is created once the join callback fires — the full room state is already decoded at that point.

State synchronization

The server state is defined in server/src/schema/GameState.ts:

Object Fields Use
Player x, y, z, yaw Transform, streamed by the owning client, adopted by the server
Player anim Animation state; remote clients derive sounds and effects from its transitions
Player coins Confirmed score, incremented only by the server
Player username, variant Display name and character model, fixed at join
Coin available Visible and collectable state
Falling platform fell_at Server-clock timestamp of the step that armed the fall; 0 = armed
Game winner Session id of the round winner; "" = none

Each client streams its transform through the room's input channel (room:input(), 20 Hz); the server adopts the latest frame per tick into the player's state. The input channel also feeds the SDK's synchronized room clock (room.clock:server_now()), which the falling platforms animate against, and is the seam through which a later version can move movement simulation to the server.

Remote players are smoothed with the SDK's Predict lerp (120 ms render delay); position snaps instead of gliding on respawns. Coin and score changes reach clients through state callbacks (colyseus.callbacks(room)).

Messages

Transient events are plain room messages, validated on the server with zod:

Message Route Use
collect_coin Client → server Requests a coin pickup; the server checks availability and proximity
reach_flag Client → server Reports touching the goal flag; the server checks the score and proximity
platform_step Client → server Reports stepping on an armed falling platform; the server checks proximity
respawn Server → all clients Starts the next round; each client resets its own player

Coin collection is handled in game/prefabs/coin/coin.script. The collector hides the coin and plays the pickup sound immediately for responsiveness and sends collect_coin; the server validates the request, flips available, increments the collector's coins, and re-enables the coin six seconds later. Every client's coin visibility follows the replicated available state, bridged on the collector by the SDK's predicted event channel (a rejected or lost collect auto-expires after ~2× RTT).

Falling platforms animate a closed-form shake and fall off the replicated fell_at timestamp against the synchronized server clock, so all clients (including late joiners) see the same motion without further messages. The stepping client starts shaking right away from a predicted stamp; the authoritative fell_at takes over once the server confirms.

Winning and starting the next round

The server validates reach_flag against the player's confirmed coins value (15 to win). When the requirement is met it sets winner, waits five seconds, clears the winner, resets every player's coins, and broadcasts respawn. Each client responds by resetting the player it owns.

Credits

Assets used in the project by Kenney

About

Fork of Defold's Platformer Multiplayer Game Sample using Colyseus 0.18

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages