colyseus.js
Version:
Colyseus Multiplayer SDK for JavaScript/TypeScript
207 lines (161 loc) • 7.26 kB
HTML
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<style>
body { font-family: Tahoma, Geneva, sans-serif; }
</style>
<script src="colyseus.js"></script>
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.min.js"></script>
</head>
<body>
<script type="text/javascript">
class Part4Scene extends Phaser.Scene {
constructor() {
super({ key: "part4" });
this.playerEntities = {};
this.inputPayload = {
left: false,
right: false,
up: false,
down: false,
tick: undefined,
};
this.elapsedTime = 0;
this.fixedTimeStep = 1000 / 60;
this.currentTick = 0;
}
preload() {
// update menu background color
this.cameras.main.setBackgroundColor(0x000000);
// preload demo assets
// this.load.image('ship_0001', 'assets/ship_0001.png');
this.load.image('ship_0001', 'https://cdn.glitch.global/3e033dcd-d5be-4db4-99e8-086ae90969ec/ship_0001.png?v=1649945243288');
}
async create() {
this.cursorKeys = this.input.keyboard.createCursorKeys();
this.debugFPS = this.add.text(4, 4, "", { color: "#ff0000", });
// connect with the room
await this.connect();
this.room.state.players.onAdd((player, sessionId) => {
const entity = this.physics.add.image(player.x, player.y, 'ship_0001');
this.playerEntities[sessionId] = entity;
// is current player
if (sessionId === this.room.sessionId) {
this.currentPlayer = entity;
this.localRef = this.add.rectangle(0, 0, entity.width, entity.height);
this.localRef.setStrokeStyle(1, 0x00ff00);
this.remoteRef = this.add.rectangle(0, 0, entity.width, entity.height);
this.remoteRef.setStrokeStyle(1, 0xff0000);
player.onChange(() => {
this.remoteRef.x = player.x;
this.remoteRef.y = player.y;
});
} else {
// listening for server updates
player.onChange(() => {
//
// we're going to LERP the positions during the render loop.
//
entity.setData('serverX', player.x);
entity.setData('serverY', player.y);
});
}
});
// remove local reference when entity is removed from the server
this.room.state.players.onRemove((player, sessionId) => {
const entity = this.playerEntities[sessionId];
if (entity) {
entity.destroy();
delete this.playerEntities[sessionId]
}
});
// this.cameras.main.startFollow(this.ship, true, 0.2, 0.2);
// this.cameras.main.setZoom(1);
this.cameras.main.setBounds(0, 0, 800, 600);
}
async connect() {
// add connection status text
const connectionStatusText = this.add
.text(0, 0, "Trying to connect with the server...")
.setStyle({ color: "#ff0000" })
.setPadding(4)
const client = new Colyseus.Client("ws://localhost:2567");
try {
this.room = await client.joinOrCreate("my_room", {});
// connection successful!
connectionStatusText.destroy();
} catch (e) {
// couldn't connect
connectionStatusText.text = "Could not connect with the server.";
}
}
update(time, delta) {
// skip loop if not connected yet.
if (!this.currentPlayer) { return; }
this.elapsedTime += delta;
while (this.elapsedTime >= this.fixedTimeStep) {
this.elapsedTime -= this.fixedTimeStep;
this.fixedTick(time, this.fixedTimeStep);
}
this.debugFPS.text = `Frame rate: ${this.game.loop.actualFps}`;
}
fixedTick(time, delta) {
this.currentTick++;
// const currentPlayerRemote = this.room.state.players.get(this.room.sessionId);
// const ticksBehind = this.currentTick - currentPlayerRemote.tick;
// console.log({ ticksBehind });
const velocity = 2;
this.inputPayload.left = this.cursorKeys.left.isDown;
this.inputPayload.right = this.cursorKeys.right.isDown;
this.inputPayload.up = this.cursorKeys.up.isDown;
this.inputPayload.down = this.cursorKeys.down.isDown;
this.inputPayload.tick = this.currentTick;
this.room.send(0, this.inputPayload);
if (this.inputPayload.left) {
this.currentPlayer.x -= velocity;
} else if (this.inputPayload.right) {
this.currentPlayer.x += velocity;
}
if (this.inputPayload.up) {
this.currentPlayer.y -= velocity;
} else if (this.inputPayload.down) {
this.currentPlayer.y += velocity;
}
this.localRef.x = this.currentPlayer.x;
this.localRef.y = this.currentPlayer.y;
for (let sessionId in this.playerEntities) {
// interpolate all player entities
// (except the current player)
if (sessionId === this.room.sessionId) {
continue;
}
const entity = this.playerEntities[sessionId];
const { serverX, serverY } = entity.data.values;
entity.x = Phaser.Math.Linear(entity.x, serverX, 0.2);
entity.y = Phaser.Math.Linear(entity.y, serverY, 0.2);
}
}
}
const config = {
type: Phaser.AUTO,
fps: {
target: 60,
forceSetTimeOut: true,
smoothStep: false,
},
width: 800,
height: 600,
// height: 200,
backgroundColor: '#b6d53c',
parent: 'phaser-example',
physics: {
default: "arcade"
},
pixelArt: true,
scene: [Part4Scene],
};
const game = new Phaser.Game(config);
</script>
</body>
</html>