From 0f8edbe0b2c0bd09cd40872f06993c08e67f26cb Mon Sep 17 00:00:00 2001 From: Mike Vink Date: Thu, 15 Jul 2021 11:52:28 +0200 Subject: refactor(client/api): need to debug! --- client/src/GameState.ts | 31 ++++++++++++++++++ client/src/app.ts | 44 +++++++++++++++++++++++++ client/src/client.ts | 58 +++++++++++++++++++++++++++++++++ client/src/events.ts | 9 ++++++ client/src/game.ts | 80 ++++++++++++++++++++++++---------------------- client/src/messageTypes.ts | 4 +++ client/src/player.ts | 33 +++++++++++++++++++ client/src/scene.ts | 1 + client/src/session.ts | 10 ++++++ client/src/socket.ts | 40 +++++++++++++++++++++++ 10 files changed, 272 insertions(+), 38 deletions(-) create mode 100644 client/src/GameState.ts create mode 100644 client/src/app.ts create mode 100644 client/src/client.ts create mode 100644 client/src/events.ts create mode 100644 client/src/messageTypes.ts create mode 100644 client/src/player.ts create mode 100644 client/src/scene.ts create mode 100644 client/src/session.ts create mode 100644 client/src/socket.ts (limited to 'client/src') diff --git a/client/src/GameState.ts b/client/src/GameState.ts new file mode 100644 index 0000000..def867f --- /dev/null +++ b/client/src/GameState.ts @@ -0,0 +1,31 @@ +import Player from './player'; +import type { Event } from './events'; + +export default class GameState { + + static instance: GameState; + + currentPlayer: Player | undefined; + remotePlayers: { [name: string]: Player } | undefined + + static getInstance() { + if (GameState.instance) return GameState.instance; + else { + GameState.instance = new GameState(); + return GameState.instance; + } + } + + setCurrentPlayer(player: Player) { + this.currentPlayer = player; + } + + posUpdate(receivedState: GameState) { + console.log("--> Game is updating positions"); + if (this.currentPlayer === undefined) { + console.log("--> getting current player object"); + console.log(receivedState.currentPlayer!); + this.currentPlayer = new Player(receivedState.currentPlayer!); + } + } +} diff --git a/client/src/app.ts b/client/src/app.ts new file mode 100644 index 0000000..784fed8 --- /dev/null +++ b/client/src/app.ts @@ -0,0 +1,44 @@ +// import Phaser from 'phaser'; +import GameState from './GameState'; +import Socket from './socket'; +import Client from './client'; +import Player from './player'; + +const url = 'ws://localhost:8080'; +const session = Socket.getInstance('ws://localhost:8080', {name: "", password: ""}); +const client = Client.getInstance(); +client.setSession(session); + +import AkkamonStartScene from './game'; + +const config: Phaser.Types.Core.GameConfig & Phaser.Types.Core.RenderConfig = { + type: Phaser.AUTO, + backgroundColor: '#125555', + width: 800, + height: 600, + pixelArt: true, + scene: AkkamonStartScene, + physics: { + default: "arcade", + arcade: { + gravity: { y: 0 } + } + } +}; + +function delay(ms: number) { + return new Promise( resolve => setTimeout(resolve, ms) ); +} + +async function startGame() { + while (true) { + console.log(GameState.getInstance().currentPlayer); + if (GameState.getInstance().currentPlayer) { + const game: Phaser.Game = new Phaser.Game(config); + break; + } + await delay(1000); + } +} + +startGame(); diff --git a/client/src/client.ts b/client/src/client.ts new file mode 100644 index 0000000..ecd15fc --- /dev/null +++ b/client/src/client.ts @@ -0,0 +1,58 @@ +import type { + Event, +} from './events'; +import type AkkamonSession from './session'; +import GameState from './GameState'; + + +export default class Client +{ + static instance: Client + session: AkkamonSession | undefined; + + static getInstance() { + if (Client.instance) return Client.instance; + else { + Client.instance = new Client(); + return Client.instance; + } + } + + setSession(akkamonSession: AkkamonSession) { + this.session = akkamonSession; + } + + in(eventString: string) { + let event: Event = JSON.parse(eventString); + console.log("-> client is handling incoming event:"); + console.log(event); + switch (event.type) { + case 'updatePos': + GameState.getInstance().posUpdate(event.gameState!); + break; + } + } + + out(event: Event) { + console.log("-> client is now sending out message:"); + console.log(event) + if (this.session) { + this.session.send(JSON.stringify(event)); + } + } + + login(user: {name:string, password: string}) { + console.log("Sending the login message"); + if (this.session) { + this.session.send(JSON.stringify( + { + type: 'login', + user: { + name: user.name, + password: user.password + } + } + )); + } + } +} diff --git a/client/src/events.ts b/client/src/events.ts new file mode 100644 index 0000000..89cadaf --- /dev/null +++ b/client/src/events.ts @@ -0,0 +1,9 @@ +import Phaser from 'phaser'; +import type Player from './player'; +import type GameState from './GameState'; + +export interface Event { + type: string + gameState?: GameState +} + diff --git a/client/src/game.ts b/client/src/game.ts index daaf5d9..369e7e6 100644 --- a/client/src/game.ts +++ b/client/src/game.ts @@ -1,10 +1,21 @@ import Phaser from 'phaser'; +import type Player from './player'; +import Client from './client'; +import GameState from './GameState'; -export default class Demo extends Phaser.Scene +type Sprite = Phaser.Types.Physics.Arcade.SpriteWithDynamicBody; + +type Input = { + cursors: Phaser.Types.Input.Keyboard.CursorKeys, +} + + +export default class AkkamonStartScene extends Phaser.Scene { + remotePlayers: Array = new Array(); constructor () { - super('demo'); + super('akkamonStartScene'); } preload () @@ -49,12 +60,15 @@ export default class Demo extends Phaser.Scene // Create a sprite with physics enabled via the physics system. The image used for the sprite has // a bit of whitespace, so I'm using setSize & setOffset to control the size of the player's body. - player = this.physics.add + + let player = this.physics.add .sprite(spawnPoint.x as number, spawnPoint.y as number, "atlas", "misa-front") .setSize(30, 40) .setOffset(0, 24); - this.physics.add.collider(player, worldLayer); + GameState.getInstance().currentPlayer!.setSprite(player); + + // this.physics.add.collider(player, worldLayer); // Create the player's walking animations from the texture atlas. These are stored in the global // animation manager so any sprite can access them. @@ -90,7 +104,8 @@ export default class Demo extends Phaser.Scene camera.startFollow(player); camera.setBounds(0, 0, map.widthInPixels, map.heightInPixels); - cursors = this.input.keyboard.createCursorKeys(); + let cursors = this.input.keyboard.createCursorKeys(); + GameState.getInstance().currentPlayer!.input = { cursors }; // Debug graphics this.input.keyboard.once("keydown_D", (event: Event) => { @@ -117,23 +132,36 @@ export default class Demo extends Phaser.Scene } update(time: Number, delta: Number) { + let player = GameState.getInstance().currentPlayer!.sprite as Sprite; + let input = GameState.getInstance().currentPlayer!.input; + + const speed = 175; const prevVelocity = player.body.velocity.clone(); // Stop any previous movement from the last frame player.body.setVelocity(0); + if (input) { + this.moveSprite(player, input, speed, prevVelocity) + } + + // this.drawRemotePlayers(); + } + + moveSprite(player: Sprite, input: Input, speed: number, prevVelocity: {x: number, y:number}) { + // Horizontal movement - if (cursors.left.isDown) { + if (input.cursors.left.isDown) { player.body.setVelocityX(-speed); - } else if (cursors.right.isDown) { + } else if (input.cursors.right.isDown) { player.body.setVelocityX(speed); } // Vertical movement - if (cursors.up.isDown) { + if (input.cursors.up.isDown) { player.body.setVelocityY(-speed); - } else if (cursors.down.isDown) { + } else if (input.cursors.down.isDown) { player.body.setVelocityY(speed); } @@ -141,13 +169,13 @@ export default class Demo extends Phaser.Scene player.body.velocity.normalize().scale(speed); // Update the animation last and give left/right animations precedence over up/down animations - if (cursors.left.isDown) { + if (input.cursors.left.isDown) { player.anims.play("misa-left-walk", true); - } else if (cursors.right.isDown) { + } else if (input.cursors.right.isDown) { player.anims.play("misa-right-walk", true); - } else if (cursors.up.isDown) { + } else if (input.cursors.up.isDown) { player.anims.play("misa-back-walk", true); - } else if (cursors.down.isDown) { + } else if (input.cursors.down.isDown) { player.anims.play("misa-front-walk", true); } else { player.anims.stop(); @@ -158,29 +186,5 @@ export default class Demo extends Phaser.Scene else if (prevVelocity.y > 0) player.setTexture("atlas", "misa-front"); } } -} - -const config = { - type: Phaser.AUTO, - backgroundColor: '#125555', - width: 800, - height: 600, - pixelArt: true, - scene: Demo, - physics: { - default: "arcade", - arcade: { - gravity: { y: 0 } - } - } -}; -let cursors: Phaser.Types.Input.Keyboard.CursorKeys; -let player: Phaser.Types.Physics.Arcade.SpriteWithDynamicBody; - -const socket = new WebSocket('ws://localhost:8080'); -socket.addEventListener('open', (e: Event) => {socket.send('Hello Server!');}); -socket.addEventListener('close', (e: Event) => {socket.send('Goodbye!');}); -// socket.send("bye"); - -const game = new Phaser.Game(config); +} diff --git a/client/src/messageTypes.ts b/client/src/messageTypes.ts new file mode 100644 index 0000000..eae45dc --- /dev/null +++ b/client/src/messageTypes.ts @@ -0,0 +1,4 @@ +export interface Message { + type: 'login' +} + diff --git a/client/src/player.ts b/client/src/player.ts new file mode 100644 index 0000000..1be85dd --- /dev/null +++ b/client/src/player.ts @@ -0,0 +1,33 @@ +import type Phaser from 'phaser'; + +type Sprite = Phaser.Types.Physics.Arcade.SpriteWithDynamicBody; + +type PlayerConfig = { + name: string, + position: {x: number, y: number} +} + +type Input = { + cursors: Phaser.Types.Input.Keyboard.CursorKeys, +} + +export default class Player +{ + name: string + position: {x:number, y: number} + sprite: Sprite | undefined; + input: Input | undefined; + + constructor({name, position}: PlayerConfig) { + this.name = name; + this.position = position + } + + setSprite(sprite: Sprite) { + this.sprite = sprite; + } + + setInput(input: Input) { + this.input = input; + } +} diff --git a/client/src/scene.ts b/client/src/scene.ts new file mode 100644 index 0000000..4ac2a3f --- /dev/null +++ b/client/src/scene.ts @@ -0,0 +1 @@ +import type Player from './player'; diff --git a/client/src/session.ts b/client/src/session.ts new file mode 100644 index 0000000..bbefd66 --- /dev/null +++ b/client/src/session.ts @@ -0,0 +1,10 @@ +import type Player from './player'; + +export default interface AkkamonSession extends WebSocket { + user?: User +} + +interface User { + name: string + password: string +} diff --git a/client/src/socket.ts b/client/src/socket.ts new file mode 100644 index 0000000..cfd8ce3 --- /dev/null +++ b/client/src/socket.ts @@ -0,0 +1,40 @@ +import Phaser from 'phaser'; +import Client from './client' +import type AkkamonSession from './session' + +export default class Socket extends WebSocket implements AkkamonSession +{ + static instance: AkkamonSession; + + static getInstance(url: string, user: {name: string, password: string}) { + if (Socket.instance) return Socket.instance; + else { + Socket.instance = new Socket(url, user); + return Socket.instance; + } + } + + constructor(url: string, user: {name: string, password: string}) { + super(url); + + let client = Client.getInstance(); + + let session = this; + + this.onopen = function echo(this: WebSocket, ev: Event) { + console.log("opening socket"); + console.log("this is the websocket"); + console.log(this); + console.log("logging in the session to the server"); + client.login(user); + } + + this.onmessage = function incomingMessage(this: WebSocket, ev: MessageEvent) { + console.log("received message from the server!"); + console.log("-> " + ev.data); + console.log("calling client.in:"); + client.in(ev.data); + } + } + +} -- cgit v1.2.3