1
0
mirror of https://github.com/thib8956/tic-tac-toe-ws.git synced 2026-01-29 14:23:22 +00:00

feat: synchronize colors between clients

This commit is contained in:
2026-01-27 13:08:40 +01:00
parent d8733c48b3
commit eb6011fa9d
4 changed files with 28 additions and 18 deletions

View File

@@ -210,11 +210,11 @@ function init() {
canvasMsg = "connected as spectator"; canvasMsg = "connected as spectator";
// Initialize grid state // Initialize grid state
for (const [index, sym] of (msg.data as Spectate).grid.entries()) { for (const [index, sym] of (msg.data as Spectate).grid.entries()) {
if (sym === undefined) continue; if (!sym) continue;
grid[index] = { grid[index] = {
kind: sym, kind: sym.symbol,
hue: Math.floor(Math.random() * 255),
time: null, time: null,
hue: sym.hue,
} as Shape; } as Shape;
} }
break; break;
@@ -224,7 +224,7 @@ function init() {
const { x, y } = res.last; const { x, y } = res.last;
const shape: Shape = { const shape: Shape = {
kind: res.last.symbol, kind: res.last.symbol,
hue: Math.floor(Math.random() * 255), hue: res.last.hue,
time: null, time: null,
}; };
grid[y*3+x] = shape; grid[y*3+x] = shape;

View File

@@ -1,9 +1,12 @@
export type MessageKind = "click" | "hello" | "update" | "endgame" | "reset" | "spectate"; export type MessageKind = "click" | "hello" | "update" | "endgame" | "reset" | "spectate";
export interface Message { export type Message =
kind: MessageKind, | { kind: "click", data: Click }
data: Click | Update | Hello | EndGame | Reset | Spectate, | { kind: "hello", data: Hello }
} | { kind: "update", data: Update }
| { kind: "endgame", data: EndGame }
| { kind: "reset", data: Reset }
| { kind: "spectate", data: Spectate };
export interface Click { export interface Click {
x: number, x: number,
@@ -12,8 +15,10 @@ export interface Click {
export type Symbol = "x" | "o"; export type Symbol = "x" | "o";
export type SymbolWithHue = { symbol: Symbol, hue: number };
export interface Update { export interface Update {
last: { x: number, y: number, symbol: Symbol } last: { x: number, y: number, symbol: Symbol, hue: number}
} }
export interface Hello { export interface Hello {
@@ -27,8 +32,7 @@ export interface EndGame {
type Reset = undefined; type Reset = undefined;
export interface Spectate { export interface Spectate {
grid: (Symbol | undefined)[] grid: (SymbolWithHue | undefined)[]
} }

View File

@@ -1,7 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="en">
<head> <head>
<title>Hello websockets</title> <title>Hello websockets</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
</head> </head>
<body style="margin: 0; padding 0; overflow: hidden; background-color: #000000"> <body style="margin: 0; padding 0; overflow: hidden; background-color: #000000">
<canvas id="game" width="800" height="600"></canvas> <canvas id="game" width="800" height="600"></canvas>

View File

@@ -1,10 +1,11 @@
import { Message, Update, Hello, EndGame, Symbol } from "common.js" import { Message, Update, Hello, EndGame, Symbol, SymbolWithHue } from "common.js"
import { WebSocket, WebSocketServer, MessageEvent } from "ws"; import { WebSocket, WebSocketServer, MessageEvent } from "ws";
const port = 1234 const port = 1234
const wss = new WebSocketServer({ port }); const wss = new WebSocketServer({ port });
let grid = [0, 0, 0, 0, 0, 0, 0, 0, 0] let grid = [0, 0, 0, 0, 0, 0, 0, 0, 0];
let hues = [0, 0, 0, 0, 0, 0, 0, 0, 0];
let endGame = false; let endGame = false;
console.log(`waiting for connection on ws://localhost:${port}`); console.log(`waiting for connection on ws://localhost:${port}`);
@@ -30,13 +31,14 @@ wss.on("connection", (ws, req) => {
id += 1; id += 1;
if (clients.length === 2) { if (clients.length === 2) {
spectators.push(ws); spectators.push(ws);
const spectateData: (Symbol | undefined)[] = []; const spectateData: (SymbolWithHue | undefined)[] = [];
for (const playerId of grid) { for (const [i, playerId] of grid.entries()) {
if (playerId === 0) { if (playerId === 0) {
spectateData.push(undefined); spectateData.push(undefined);
} else { } else {
const sym = clients.find(c => c.id === playerId)!.symbol; const sym = clients.find(c => c.id === playerId)!.symbol;
spectateData.push(sym); const hue = hues[i];
spectateData.push({ symbol: sym, hue: hue });
} }
} }
const spectateMsg: Message = { const spectateMsg: Message = {
@@ -62,6 +64,7 @@ wss.on("connection", (ws, req) => {
ws.addEventListener("message", (event: MessageEvent) => { ws.addEventListener("message", (event: MessageEvent) => {
const message = JSON.parse(event.data as string); const message = JSON.parse(event.data as string);
const {x, y} = message; const {x, y} = message;
const hue = Math.floor(Math.random() * 255);
const player = clients.find(x => x.ws === ws); const player = clients.find(x => x.ws === ws);
if (!player) throw new Error("player not found"); if (!player) throw new Error("player not found");
console.log("received message", message, "player", player!.id, "currentPlayer", currentPlayer?.id); console.log("received message", message, "player", player!.id, "currentPlayer", currentPlayer?.id);
@@ -95,10 +98,11 @@ wss.on("connection", (ws, req) => {
if (grid[y*3+x] === 0) { if (grid[y*3+x] === 0) {
grid[y*3+x] = player.id; grid[y*3+x] = player.id;
hues[y*3+x] = hue;
const msg = JSON.stringify({ const msg = JSON.stringify({
kind: "update", kind: "update",
data: { data: {
last: { x, y, symbol: player.symbol } last: { x, y, symbol: player.symbol, hue: hue },
} as Update, } as Update,
} as Message); } as Message);