From b82b13e35195c56fd527938eaf5fc052ca5c934a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 4 Jun 2020 18:54:34 +0200 Subject: [PATCH] Finalizing strict mode fixes --- .../{PlayableCharacter.ts => Character.ts} | 79 ++++++++++++++- front/src/Phaser/Entity/RemotePlayer.ts | 38 ++++++++ front/src/Phaser/Entity/SpeechBubble.ts | 4 +- front/src/Phaser/Game/GameManager.ts | 2 +- front/src/Phaser/Game/GameScene.ts | 25 ++--- front/src/Phaser/Login/LoginScene.ts | 2 +- .../src/Phaser/Login/SelectCharacterScene.ts | 2 +- front/src/Phaser/Player/Player.ts | 95 +------------------ .../Phaser/Reconnecting/ReconnectingScene.ts | 2 +- 9 files changed, 139 insertions(+), 110 deletions(-) rename front/src/Phaser/Entity/{PlayableCharacter.ts => Character.ts} (64%) create mode 100644 front/src/Phaser/Entity/RemotePlayer.ts diff --git a/front/src/Phaser/Entity/PlayableCharacter.ts b/front/src/Phaser/Entity/Character.ts similarity index 64% rename from front/src/Phaser/Entity/PlayableCharacter.ts rename to front/src/Phaser/Entity/Character.ts index 99b4d631..ec0167eb 100644 --- a/front/src/Phaser/Entity/PlayableCharacter.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -24,14 +24,31 @@ export const PLAYER_RESOURCES: Array = [ {name: "Female8", img: "resources/characters/pipoya/Female 16-4.png"/*, x: 128, y: 128*/} ]; -export class PlayableCharacter extends Phaser.Physics.Arcade.Sprite { +interface AnimationData { + key: string; + frameRate: number; + repeat: number; + frameModel: string; //todo use an enum + frameStart: number; + frameEnd: number; +} + +export abstract class Character extends Phaser.Physics.Arcade.Sprite { private bubble: SpeechBubble|null = null; private readonly playerName: BitmapText; public PlayerValue: string; public PlayerTexture: string; - constructor(scene: Phaser.Scene, x: number, y: number, texture: string, name: string, frame?: string | number) { + constructor(scene: Phaser.Scene, + x: number, + y: number, + texture: string, + name: string, + direction: string, + moving: boolean, + frame?: string | number + ) { super(scene, x, y, texture, frame); this.PlayerValue = name; @@ -51,6 +68,64 @@ export class PlayableCharacter extends Phaser.Physics.Arcade.Sprite { this.setDepth(-1); this.scene.events.on('postupdate', this.postupdate.bind(this)); + + this.initAnimation(); + this.playAnimation(direction, moving); + } + + private initAnimation(): void { + this.getPlayerAnimations(this.PlayerTexture).forEach(d => { + this.scene.anims.create({ + key: d.key, + frames: this.scene.anims.generateFrameNumbers(d.frameModel, {start: d.frameStart, end: d.frameEnd}), + frameRate: d.frameRate, + repeat: d.repeat + }); + }) + } + + private getPlayerAnimations(name: string): AnimationData[] { + return [{ + key: `${name}-${PlayerAnimationNames.WalkDown}`, + frameModel: name, + frameStart: 0, + frameEnd: 2, + frameRate: 10, + repeat: -1 + }, { + key: `${name}-${PlayerAnimationNames.WalkLeft}`, + frameModel: name, + frameStart: 3, + frameEnd: 5, + frameRate: 10, + repeat: -1 + }, { + key: `${name}-${PlayerAnimationNames.WalkRight}`, + frameModel: name, + frameStart: 6, + frameEnd: 8, + frameRate: 10, + repeat: -1 + }, { + key: `${name}-${PlayerAnimationNames.WalkUp}`, + frameModel: name, + frameStart: 9, + frameEnd: 11, + frameRate: 10, + repeat: -1 + }]; + } + + protected playAnimation(direction : string, moving: boolean): void { + if (moving && (!this.anims.currentAnim || this.anims.currentAnim.key !== direction)) { + this.play(this.PlayerTexture+'-'+direction, true); + } else if (!moving) { + /*if (this.anims.currentAnim) { + this.anims.stop(); + }*/ + this.play(this.PlayerTexture+'-'+direction, true); + this.stop(); + } } move(x: number, y: number) { diff --git a/front/src/Phaser/Entity/RemotePlayer.ts b/front/src/Phaser/Entity/RemotePlayer.ts new file mode 100644 index 00000000..36911bb6 --- /dev/null +++ b/front/src/Phaser/Entity/RemotePlayer.ts @@ -0,0 +1,38 @@ +import {GameScene} from "../Game/GameScene"; +import {PointInterface} from "../../Connection"; +import {Character} from "../Entity/Character"; + +/** + * Class representing the sprite of a remote player (a player that plays on another computer) + */ +export class RemotePlayer extends Character { + userId: string; + previousDirection: string; + wasMoving: boolean; + + constructor( + userId: string, + Scene: GameScene, + x: number, + y: number, + name: string, + PlayerTexture: string, + direction: string, + moving: boolean + ) { + super(Scene, x, y, PlayerTexture, name, direction, moving, 1); + + //set data + this.userId = userId; + + //the current player model should be push away by other players to prevent conflict + //this.setImmovable(false); + } + + updatePosition(position: PointInterface): void { + this.playAnimation(position.direction, position.moving); + this.setX(position.x); + this.setY(position.y); + this.setDepth(position.y); + } +} diff --git a/front/src/Phaser/Entity/SpeechBubble.ts b/front/src/Phaser/Entity/SpeechBubble.ts index 6a696b66..f2385290 100644 --- a/front/src/Phaser/Entity/SpeechBubble.ts +++ b/front/src/Phaser/Entity/SpeechBubble.ts @@ -1,5 +1,5 @@ import Scene = Phaser.Scene; -import {PlayableCharacter} from "./PlayableCharacter"; +import {Character} from "./Character"; export class SpeechBubble { private bubble: Phaser.GameObjects.Graphics; @@ -11,7 +11,7 @@ export class SpeechBubble { * @param player * @param text */ - constructor(scene: Scene, player: PlayableCharacter, text: string = "") { + constructor(scene: Scene, player: Character, text: string = "") { let bubbleHeight = 50; let bubblePadding = 10; diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts index c4c4c981..7eef49b4 100644 --- a/front/src/Phaser/Game/GameManager.ts +++ b/front/src/Phaser/Game/GameManager.ts @@ -139,7 +139,7 @@ export class GameManager { return this.playerName; } - getPlayerId(): string { + getPlayerId(): string|null { return this.ConnectionInstance.userId; } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 27052e77..934831e1 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -4,10 +4,10 @@ import { MessageUserMovedInterface, MessageUserPositionInterface, PointInterface, PositionInterface } from "../../Connection"; -import {CurrentGamerInterface, GamerInterface, hasMovedEventName, Player} from "../Player/Player"; +import {CurrentGamerInterface, hasMovedEventName, Player} from "../Player/Player"; import { DEBUG_MODE, ZOOM_LEVEL, POSITION_DELAY } from "../../Enum/EnvironmentVariable"; import {ITiledMap, ITiledMapLayer, ITiledTileSet} from "../Map/ITiledMap"; -import {PLAYER_RESOURCES} from "../Entity/PlayableCharacter"; +import {PLAYER_RESOURCES} from "../Entity/Character"; import Texture = Phaser.Textures.Texture; import Sprite = Phaser.GameObjects.Sprite; import CanvasTexture = Phaser.Textures.CanvasTexture; @@ -15,6 +15,7 @@ import {AddPlayerInterface} from "./AddPlayerInterface"; import {PlayerAnimationNames} from "../Player/Animation"; import {PlayerMovement} from "./PlayerMovement"; import {PlayersPositionInterpolator} from "./PlayersPositionInterpolator"; +import {RemotePlayer} from "../Entity/RemotePlayer"; export enum Textures { Player = "male1" @@ -29,11 +30,11 @@ export class GameScene extends Phaser.Scene { Terrains : Array; CurrentPlayer: CurrentGamerInterface; MapPlayers : Phaser.Physics.Arcade.Group; - MapPlayersByKey : Map = new Map(); + MapPlayersByKey : Map = new Map(); Map: Phaser.Tilemaps.Tilemap; Layers : Array; Objects : Array; - mapFile: ITiledMap|null; + mapFile: ITiledMap; groups: Map; startX = 704;// 22 case startY = 32; // 1 case @@ -198,7 +199,7 @@ export class GameScene extends Phaser.Scene { // FIXME: entry should be dictated by a property passed to init() path += '#'+url.hash; } - window.history.pushState({}, null, path); + window.history.pushState({}, 'WorkAdventure', path); } private getExitSceneUrl(layer: ITiledMapLayer): string|undefined { @@ -234,6 +235,9 @@ export class GameScene extends Phaser.Scene { */ private loadNextGame(layer: ITiledMapLayer, mapWidth: number, tileWidth: number, tileHeight: number){ let exitSceneUrl = this.getExitSceneUrl(layer); + if (exitSceneUrl === undefined) { + throw new Error('Layer is not an exit scene layer.'); + } let instance = this.getExitSceneInstance(layer); if (instance === undefined) { instance = this.instance; @@ -340,7 +344,6 @@ export class GameScene extends Phaser.Scene { //initialise player //TODO create animation moving between exit and start this.CurrentPlayer = new Player( - null, // The current player has no id (because the id can change if connection is lost and we should check that id using the GameManager.) this, this.startX, this.startY, @@ -415,7 +418,7 @@ export class GameScene extends Phaser.Scene { // Let's move all users let updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time); updatedPlayersPositions.forEach((moveEvent: HasMovedEvent, userId: string) => { - let player : GamerInterface | undefined = this.MapPlayersByKey.get(userId); + let player : RemotePlayer | undefined = this.MapPlayersByKey.get(userId); if (player === undefined) { throw new Error('Cannot find player with ID "' + userId +'"'); } @@ -452,11 +455,11 @@ export class GameScene extends Phaser.Scene { let currentPlayerId = this.GameManager.getPlayerId(); // clean map - this.MapPlayersByKey.forEach((player: GamerInterface) => { + this.MapPlayersByKey.forEach((player: RemotePlayer) => { player.destroy(); this.MapPlayers.remove(player); }); - this.MapPlayersByKey = new Map(); + this.MapPlayersByKey = new Map(); // load map usersPosition.forEach((userPosition : MessageUserPositionInterface) => { @@ -480,7 +483,7 @@ export class GameScene extends Phaser.Scene { return; } //initialise player - let player = new Player( + let player = new RemotePlayer( addPlayerData.userId, this, addPlayerData.position.x, @@ -514,7 +517,7 @@ export class GameScene extends Phaser.Scene { } updatePlayerPosition(message: MessageUserMovedInterface): void { - let player : GamerInterface | undefined = this.MapPlayersByKey.get(message.userId); + let player : RemotePlayer | undefined = this.MapPlayersByKey.get(message.userId); if (player === undefined) { throw new Error('Cannot find player with ID "' + message.userId +'"'); } diff --git a/front/src/Phaser/Login/LoginScene.ts b/front/src/Phaser/Login/LoginScene.ts index 606b4077..1b7ef76f 100644 --- a/front/src/Phaser/Login/LoginScene.ts +++ b/front/src/Phaser/Login/LoginScene.ts @@ -4,7 +4,7 @@ import {TextInput} from "../Components/TextInput"; import {ClickButton} from "../Components/ClickButton"; import Image = Phaser.GameObjects.Image; import Rectangle = Phaser.GameObjects.Rectangle; -import {PLAYER_RESOURCES} from "../Entity/PlayableCharacter"; +import {PLAYER_RESOURCES} from "../Entity/Character"; import {cypressAsserter} from "../../Cypress/CypressAsserter"; import {SelectCharacterSceneInitDataInterface, SelectCharacterSceneName} from "./SelectCharacterScene"; diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts index f91a810c..eb5f25e9 100644 --- a/front/src/Phaser/Login/SelectCharacterScene.ts +++ b/front/src/Phaser/Login/SelectCharacterScene.ts @@ -3,7 +3,7 @@ import {TextField} from "../Components/TextField"; import {ClickButton} from "../Components/ClickButton"; import Image = Phaser.GameObjects.Image; import Rectangle = Phaser.GameObjects.Rectangle; -import {PLAYER_RESOURCES} from "../Entity/PlayableCharacter"; +import {PLAYER_RESOURCES} from "../Entity/Character"; //todo: put this constants in a dedicated file export const SelectCharacterSceneName = "SelectCharacterScene"; diff --git a/front/src/Phaser/Player/Player.ts b/front/src/Phaser/Player/Player.ts index 2e88bcec..6794a472 100644 --- a/front/src/Phaser/Player/Player.ts +++ b/front/src/Phaser/Player/Player.ts @@ -2,39 +2,21 @@ import {PlayerAnimationNames} from "./Animation"; import {GameScene, Textures} from "../Game/GameScene"; import {MessageUserPositionInterface, PointInterface} from "../../Connection"; import {ActiveEventList, UserInputEvent, UserInputManager} from "../UserInput/UserInputManager"; -import {PlayableCharacter} from "../Entity/PlayableCharacter"; +import {Character} from "../Entity/Character"; export const hasMovedEventName = "hasMoved"; -export interface CurrentGamerInterface extends PlayableCharacter{ +export interface CurrentGamerInterface extends Character{ moveUser(delta: number) : void; say(text : string) : void; } -export interface GamerInterface extends PlayableCharacter{ - userId : string; - updatePosition(position: PointInterface): void; - say(text : string) : void; -} - -interface AnimationData { - key: string; - frameRate: number; - repeat: number; - frameModel: string; //todo use an enum - frameStart: number; - frameEnd: number; -} - - -export class Player extends PlayableCharacter implements CurrentGamerInterface, GamerInterface { - userId: string; +export class Player extends Character implements CurrentGamerInterface { userInputManager: UserInputManager; previousDirection: string; wasMoving: boolean; constructor( - userId: string, Scene: GameScene, x: number, y: number, @@ -43,62 +25,13 @@ export class Player extends PlayableCharacter implements CurrentGamerInterface, direction: string, moving: boolean ) { - super(Scene, x, y, PlayerTexture, name, 1); + super(Scene, x, y, PlayerTexture, name, direction, moving, 1); //create input to move this.userInputManager = new UserInputManager(Scene); - //set data - this.userId = userId; - //the current player model should be push away by other players to prevent conflict this.setImmovable(false); - this.initAnimation(); - - this.playAnimation(direction, moving); - } - - private initAnimation(): void { - this.getPlayerAnimations(this.PlayerTexture).forEach(d => { - this.scene.anims.create({ - key: d.key, - frames: this.scene.anims.generateFrameNumbers(d.frameModel, {start: d.frameStart, end: d.frameEnd}), - frameRate: d.frameRate, - repeat: d.repeat - }); - }) - } - - private getPlayerAnimations(name: string): AnimationData[] { - return [{ - key: `${name}-${PlayerAnimationNames.WalkDown}`, - frameModel: name, - frameStart: 0, - frameEnd: 2, - frameRate: 10, - repeat: -1 - }, { - key: `${name}-${PlayerAnimationNames.WalkLeft}`, - frameModel: name, - frameStart: 3, - frameEnd: 5, - frameRate: 10, - repeat: -1 - }, { - key: `${name}-${PlayerAnimationNames.WalkRight}`, - frameModel: name, - frameStart: 6, - frameEnd: 8, - frameRate: 10, - repeat: -1 - }, { - key: `${name}-${PlayerAnimationNames.WalkUp}`, - frameModel: name, - frameStart: 9, - frameEnd: 11, - frameRate: 10, - repeat: -1 - }]; } moveUser(delta: number): void { @@ -146,24 +79,4 @@ export class Player extends PlayableCharacter implements CurrentGamerInterface, } this.wasMoving = moving; } - - //todo: put this method into the NonPlayer class instead - updatePosition(position: PointInterface): void { - this.playAnimation(position.direction, position.moving); - this.setX(position.x); - this.setY(position.y); - this.setDepth(position.y); - } - - private playAnimation(direction : string, moving: boolean): void { - if (moving && (!this.anims.currentAnim || this.anims.currentAnim.key !== direction)) { - this.play(this.PlayerTexture+'-'+direction, true); - } else if (!moving) { - /*if (this.anims.currentAnim) { - this.anims.stop(); - }*/ - this.play(this.PlayerTexture+'-'+direction, true); - this.stop(); - } - } } diff --git a/front/src/Phaser/Reconnecting/ReconnectingScene.ts b/front/src/Phaser/Reconnecting/ReconnectingScene.ts index 45651ed0..7188b223 100644 --- a/front/src/Phaser/Reconnecting/ReconnectingScene.ts +++ b/front/src/Phaser/Reconnecting/ReconnectingScene.ts @@ -4,7 +4,7 @@ import {TextInput} from "../Components/TextInput"; import {ClickButton} from "../Components/ClickButton"; import Image = Phaser.GameObjects.Image; import Rectangle = Phaser.GameObjects.Rectangle; -import {PLAYER_RESOURCES} from "../Entity/PlayableCharacter"; +import {PLAYER_RESOURCES} from "../Entity/Character"; import {cypressAsserter} from "../../Cypress/CypressAsserter"; import Sprite = Phaser.GameObjects.Sprite;