Phaser

Here is a very basic platformer made with Phaser and made multiplayer using Playroom Kit. You can either try it below or scan the QR code to play it on your phone.

Code for the above demo

Highlighted are the relevant multiplayer parts of the code for the above demo. You can also find the full code here (opens in a new tab):

import nipplejs from "nipplejs";
import Phaser from "phaser";
import { onPlayerJoin, insertCoin, isHost, myPlayer } from "playroomkit";
 
class Main extends Phaser.Scene {
  controls = {};
  players = []; 
 
  create() {
    // 1. Handle players joining and quiting.
    onPlayerJoin(playerState => this.addPlayer(playerState));
 
    // 2. Pass player input to Playroom.
    const joystick = nipplejs.create();
    joystick.on("plain", (e, data) => {
      myPlayer().setState("dir", data.direction);
    });
    joystick.on("end", () => {
      myPlayer().setState("dir", undefined);
    });
  }
 
  addPlayer(playerState) {
    const sprite = this.add.rectangle(
      Phaser.Math.Between(100, 500), 200, 50, 50, playerState.getProfile().color.hex);
    this.physics.add.existing(sprite, false);
    sprite.body.setCollideWorldBounds(true);
    this.players.push({
      sprite,
      state: playerState
    });
    playerState.onQuit(() => {
      sprite.destroy();
      this.players = this.players.filter(p => p.state !== playerState);
    });
  }
 
  update() {
    // 3. Pass your game state to Playroom.
    if (isHost()){
      for (const player of this.players) {
        const controls = player.state.getState("dir") || {};
        if (controls.x == "left") {
          player.sprite.body.setVelocityX(-160);
        }
        else if (controls.x == "right") {
          player.sprite.body.setVelocityX(160);
        }
        else{
          player.sprite.body.setVelocityX(0);
        }
    
        if (controls.y == "up" && player.sprite.body.onFloor()) {
          player.sprite.body.setVelocityY(-330);
        }
        player.state.setState("pos", {
          x: player.sprite.body.x,
          y: player.sprite.body.y,
        });
      }
    }
    else{
      for (const player of this.players) {
        const pos = player.state.getState("pos");
        if (pos){
          player.sprite.body.x = pos.x;
          player.sprite.body.y = pos.y;
        }
      }
    }
  }
}
 
const config = {
  type: Phaser.AUTO,
  width: 300,
  height: 480,
  parent: 'root',
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { y: 700 }
    }
  },
  scene: Main
};
 
// 4. Insert Coin! Start the game.
insertCoin().then(() => {
  const game = new Phaser.Game(config);
});