diff --git a/src/entities/RemotePlayer.ts b/src/entities/RemotePlayer.ts index a7621a0..5428770 100644 --- a/src/entities/RemotePlayer.ts +++ b/src/entities/RemotePlayer.ts @@ -2,12 +2,29 @@ import Phaser from "phaser"; export class RemotePlayer { sprite: Phaser.GameObjects.Rectangle; + label: Phaser.GameObjects.Text; targetX: number; targetY: number; - constructor(scene: Phaser.Scene, x: number, y: number, color: number) { + constructor( + scene: Phaser.Scene, + x: number, + y: number, + name: string, + color: number, + ) { this.sprite = scene.add.rectangle(x, y, 32, 32, color); + + this.label = scene.add + .text(x, y - 26, name, { + fontSize: "12px", + color: "#ffffff", + stroke: "#000000", + strokeThickness: 3, + }) + .setOrigin(0.5); + this.targetX = x; this.targetY = y; } @@ -18,12 +35,17 @@ export class RemotePlayer { } update() { - // магия сглаживания + // интерполяция позиции this.sprite.x = Phaser.Math.Linear(this.sprite.x, this.targetX, 0.15); this.sprite.y = Phaser.Math.Linear(this.sprite.y, this.targetY, 0.15); + + // ник всегда над игроком + this.label.x = this.sprite.x; + this.label.y = this.sprite.y - 26; } destroy() { this.sprite.destroy(); + this.label.destroy(); } } diff --git a/src/net/Socket.ts b/src/net/Socket.ts index 78a5e2c..fe98300 100644 --- a/src/net/Socket.ts +++ b/src/net/Socket.ts @@ -1,3 +1,13 @@ +declare global { + interface Window { + Telegram?: { + WebApp: { + initData: string; + }; + }; + } +} + export class GameSocket { private socket: WebSocket; playerId: string | null = null; @@ -6,6 +16,17 @@ export class GameSocket { constructor(url: string) { this.socket = new WebSocket(url); + this.socket.onopen = () => { + const initData = window.Telegram?.WebApp?.initData ?? ""; + + this.socket.send( + JSON.stringify({ + type: "auth", + initData, + }), + ); + }; + this.socket.onmessage = (e) => { const msg = JSON.parse(e.data); @@ -17,6 +38,10 @@ export class GameSocket { this.onState?.(msg.payload); } }; + + this.socket.onerror = (e) => { + console.error("WebSocket error", e); + }; } sendInput(dx: number, dy: number) { @@ -24,6 +49,7 @@ export class GameSocket { this.socket.send( JSON.stringify({ + type: "input", dx, dy, }), diff --git a/src/scenes/GameScene.ts b/src/scenes/GameScene.ts index 2b0c40c..d02e28a 100644 --- a/src/scenes/GameScene.ts +++ b/src/scenes/GameScene.ts @@ -1,7 +1,14 @@ +import Phaser from "phaser"; import { RemotePlayer } from "../entities/RemotePlayer"; import { TouchInput } from "../input/TouchInput"; import { GameSocket } from "../net/Socket"; +type ServerPlayerState = { + x: number; + y: number; + name: string; +}; + export class GameScene extends Phaser.Scene { players = new Map(); socket!: GameSocket; @@ -24,7 +31,8 @@ export class GameScene extends Phaser.Scene { } } - syncPlayers(serverPlayers: Record) { + syncPlayers(serverPlayers: Record) { + // добавление / обновление for (const id in serverPlayers) { const data = serverPlayers[id]; let player = this.players.get(id); @@ -32,13 +40,22 @@ export class GameScene extends Phaser.Scene { if (!player) { const isMe = id === this.socket.playerId; const color = isMe ? 0x00ff00 : 0xff4444; - player = new RemotePlayer(this, data.x, data.y, color); + + player = new RemotePlayer( + this, + data.x, + data.y, + data.name, // 👈 username от сервера + color, + ); + this.players.set(id, player); } player.setTarget(data.x, data.y); } + // удаление отключившихся for (const [id, player] of this.players) { if (!serverPlayers[id]) { player.destroy();