From 5d463d097a45766735d7c1dd99209d7e56fc35e4 Mon Sep 17 00:00:00 2001 From: gparant Date: Tue, 7 Apr 2020 19:23:21 +0200 Subject: [PATCH] Refactor Class - Add MapManager permit to create map, camera and player. - Add CameraManager permit to move and update camera. - Add player Call extended of Phaser.GameObjects.Sprite. Permit to manager player data and moving in the map. - Add Animation class permit to manage the player animations. --- front/src/GameScene.ts | 185 --------------------------- front/src/Phaser/CameraManager.ts | 95 ++++++++++++++ front/src/Phaser/GameScene.ts | 35 +++++ front/src/Phaser/MapManager.ts | 85 ++++++++++++ front/src/Phaser/Player.ts | 90 +++++++++++++ front/src/Phaser/Player/Animation.ts | 60 +++++++++ front/src/index.ts | 2 +- 7 files changed, 366 insertions(+), 186 deletions(-) delete mode 100644 front/src/GameScene.ts create mode 100644 front/src/Phaser/CameraManager.ts create mode 100644 front/src/Phaser/GameScene.ts create mode 100644 front/src/Phaser/MapManager.ts create mode 100644 front/src/Phaser/Player.ts create mode 100644 front/src/Phaser/Player/Animation.ts diff --git a/front/src/GameScene.ts b/front/src/GameScene.ts deleted file mode 100644 index 2cb36131..00000000 --- a/front/src/GameScene.ts +++ /dev/null @@ -1,185 +0,0 @@ -import {RESOLUTION} from "./Enum/EnvironmentVariable"; - -export class GameScene extends Phaser.Scene { - private player: Phaser.GameObjects.Sprite; - - private keyZ: Phaser.Input.Keyboard.Key; - private keyQ: Phaser.Input.Keyboard.Key; - private keyS: Phaser.Input.Keyboard.Key; - private keyD: Phaser.Input.Keyboard.Key; - private keyRight: Phaser.Input.Keyboard.Key; - private keyLeft: Phaser.Input.Keyboard.Key; - private keyUp: Phaser.Input.Keyboard.Key; - private keyDown: Phaser.Input.Keyboard.Key; - private keyShift: Phaser.Input.Keyboard.Key; - - private Mappy : Phaser.Tilemaps.Tilemap; - - private startX = ((window.innerWidth / 2) / RESOLUTION); - private startY = ((window.innerHeight / 2) / RESOLUTION); - - constructor() { - super({ - key: "GameScene" - }); - } - - preload(): void { - this.load.image('tiles', 'maps/tiles.png'); - this.load.tilemapTiledJSON('map', 'maps/map2.json'); - this.load.spritesheet('player', - 'resources/characters/pipoya/Male 01-1.png', - { frameWidth: 32, frameHeight: 32 } - ); - } - - init(): void { - this.keyShift = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT); - - this.keyZ = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Z); - this.keyQ = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q); - this.keyS = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); - this.keyD = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); - - this.keyUp = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.UP); - this.keyLeft = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT); - this.keyDown = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN); - this.keyRight = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT); - } - - private moveCamera(x:number, y:number, speedMultiplier: number): void { - this.cameras.main.scrollX += speedMultiplier * 2 * x; - this.cameras.main.scrollY += speedMultiplier * 2 * y; - } - - create(): void { - this.Mappy = this.add.tilemap("map"); - let terrain = this.Mappy.addTilesetImage("tiles", "tiles"); - - let bottomLayer = this.Mappy.createStaticLayer("Calque 1", [terrain], 0, 0); - let topLayer = this.Mappy.createStaticLayer("Calque 2", [terrain], 0, 0); - - // Let's manage animations of the player - this.anims.create({ - key: 'down', - frames: this.anims.generateFrameNumbers('player', { start: 0, end: 2 }), - frameRate: 10, - repeat: -1 - }); - - this.anims.create({ - key: 'left', - frames: this.anims.generateFrameNumbers('player', { start: 3, end: 5 }), - frameRate: 10, - repeat: -1 - }); - - this.anims.create({ - key: 'right', - frames: this.anims.generateFrameNumbers('player', { start: 6, end: 8 }), - frameRate: 10, - repeat: -1 - }); - - this.anims.create({ - key: 'up', - frames: this.anims.generateFrameNumbers('player', { start: 9, end: 11 }), - frameRate: 10, - repeat: -1 - }); - - //let player = this.add.sprite(450, 450, 'player'); - //player.anims.play('down'); - //player.setBounce(0.2); - //player.setCollideWorldBounds(true); - this.player = this.add.sprite(this.startX, this.startY, 'player'); - } - - private angle: number = 0; - - update(dt: number): void { - let xCameraPosition = this.cameras.main.scrollX; - let yCameraPosition = this.cameras.main.scrollY; - - let speedMultiplier = this.keyShift.isDown ? 5 : 1; - - if (this.keyZ.isDown || this.keyUp.isDown) { - this.managePlayerAnimation('up'); - if (this.player.y > 0) { - this.player.setY(this.player.y - 2); - } else { - this.player.setY(0); - } - - if (yCameraPosition > 0) { - if (this.player.y < (this.Mappy.widthInPixels - this.startY)) { - this.moveCamera(0, -1, speedMultiplier); - } - } else { - this.cameras.main.scrollY = 0; - } - } else if (this.keyQ.isDown || this.keyLeft.isDown) { - - this.managePlayerAnimation('left'); - if (this.player.x > 0) { - this.player.setX(this.player.x - 2); - } else { - this.player.setX(0); - } - - if (xCameraPosition > 0) { - if (this.player.x < (this.Mappy.heightInPixels - this.startX)) { - this.moveCamera(-1, 0, speedMultiplier); - } - } else { - this.cameras.main.scrollX = 0; - } - } else if (this.keyS.isDown || this.keyDown.isDown) { - - this.managePlayerAnimation('down'); - if (this.Mappy.heightInPixels > this.player.y) { - this.player.setY(this.player.y + 2); - } else { - this.player.setY(this.Mappy.heightInPixels); - } - - if (this.Mappy.heightInPixels > (yCameraPosition + (window.innerHeight / RESOLUTION))) { - if (this.player.y > this.startY) { - this.moveCamera(0, 1, speedMultiplier); - } - } else { - this.cameras.main.scrollY = (this.Mappy.heightInPixels - (window.innerHeight / RESOLUTION)); - } - } else if (this.keyD.isDown || this.keyRight.isDown) { - - this.managePlayerAnimation('right'); - if (this.Mappy.widthInPixels > this.player.x) { - this.player.setX(this.player.x + 2) - } else { - this.player.setX(this.Mappy.widthInPixels) - } - - if (this.Mappy.widthInPixels > (xCameraPosition + (window.innerWidth / RESOLUTION))) { - if (this.player.x > this.startX) { - this.moveCamera(1, 0, speedMultiplier); - } - } else { - this.cameras.main.scrollX = (this.Mappy.widthInPixels - (window.innerWidth / RESOLUTION)); - } - } else { - this.managePlayerAnimation('none'); - } - /*this.cameras.main.scrollX = Math.floor(300 + 300 * Math.cos(this.angle)); - this.cameras.main.scrollY = Math.floor(300 + 300 * Math.sin(this.angle)); - - this.angle = dt * 0.0001;*/ - } - - managePlayerAnimation(direction: string) { - if (!this.player.anims.currentAnim || this.player.anims.currentAnim.key !== direction) { - this.player.anims.play(direction); - } else if (direction === 'none' && this.player.anims.currentAnim) { - this.player.anims.currentAnim.destroy(); - } - } -} diff --git a/front/src/Phaser/CameraManager.ts b/front/src/Phaser/CameraManager.ts new file mode 100644 index 00000000..528e06ca --- /dev/null +++ b/front/src/Phaser/CameraManager.ts @@ -0,0 +1,95 @@ +import {RESOLUTION} from "../Enum/EnvironmentVariable"; +import {Player} from "./Player"; +import {MapManagerInterface} from "./MapManager"; + +export interface CameraManagerInterface { + CurrentPlayer : Player; + MapManager : MapManagerInterface; + moveCamera() : void; +} + +export class CameraManager implements CameraManagerInterface{ + Scene : Phaser.Scene; + Camera : Phaser.Cameras.Scene2D.Camera; + CurrentPlayer : Player; + MapManager : MapManagerInterface; + + constructor( + Scene: Phaser.Scene, + Camera : Phaser.Cameras.Scene2D.Camera, + MapManager: MapManagerInterface, + CurrentPlayer: Player + ) { + this.Scene = Scene; + this.MapManager = MapManager; + this.Camera = Camera; + this.CurrentPlayer = CurrentPlayer; + } + /** + * + * @param x + * @param y + * @param speedMultiplier + */ + private moveCameraPosition(x:number, y:number, speedMultiplier: number): void { + this.Camera.scrollX += speedMultiplier * 2 * x; + this.Camera.scrollY += speedMultiplier * 2 * y; + } + + /** + * + */ + moveCamera(): void { + //center of camera + let startX = ((window.innerWidth / 2) / RESOLUTION); + let startY = ((window.innerHeight / 2) / RESOLUTION); + + //if user client on shift, camera and player speed + let speedMultiplier = this.MapManager.keyShift.isDown ? 5 : 1; + + if (this.MapManager.keyZ.isDown || this.MapManager.keyUp.isDown) { + if (!this.CanToMoveUp()) { + this.Camera.scrollY = 0; + }else if (this.CurrentPlayer.y < (this.MapManager.Map.widthInPixels - startY)) { + this.moveCameraPosition(0, -1, speedMultiplier); + } + } + if (this.MapManager.keyQ.isDown || this.MapManager.keyLeft.isDown) { + if (!this.CanToMoveLeft()) { + this.Camera.scrollX = 0; + }else if (this.CurrentPlayer.x < (this.MapManager.Map.heightInPixels - startX)) { + this.moveCameraPosition(-1, 0, speedMultiplier); + } + } + if (this.MapManager.keyS.isDown || this.MapManager.keyDown.isDown) { + if (!this.CanToMoveDown()) { + this.Camera.scrollY = (this.MapManager.Map.heightInPixels - (window.innerHeight / RESOLUTION)); + } else if (this.CurrentPlayer.y > startY) { + this.moveCameraPosition(0, 1, speedMultiplier); + } + } + if (this.MapManager.keyD.isDown || this.MapManager.keyRight.isDown) { + if (!this.CanToMoveRight()) { + this.Camera.scrollX = (this.MapManager.Map.widthInPixels - (window.innerWidth / RESOLUTION)); + } else if (this.CurrentPlayer.x > startX) { + this.moveCameraPosition(1, 0, speedMultiplier); + } + } + } + + private CanToMoveUp(){ + return this.Camera.scrollY > 0; + } + + private CanToMoveLeft(){ + return this.Camera.scrollX > 0; + } + + private CanToMoveDown(){ + return this.MapManager.Map.heightInPixels > (this.Camera.scrollY + (window.innerHeight / RESOLUTION)) + } + + private CanToMoveRight(){ + return this.MapManager.Map.widthInPixels > (this.Camera.scrollX + (window.innerWidth / RESOLUTION)) + } +} \ No newline at end of file diff --git a/front/src/Phaser/GameScene.ts b/front/src/Phaser/GameScene.ts new file mode 100644 index 00000000..4f2eb9cc --- /dev/null +++ b/front/src/Phaser/GameScene.ts @@ -0,0 +1,35 @@ +import {MapManagerInterface, MapManager} from "./MapManager"; + +export class GameScene extends Phaser.Scene { + private MapManager : MapManagerInterface; + + constructor() { + super({ + key: "GameScene" + }); + } + + //hook preload scene + preload(): void { + this.load.image('tiles', 'maps/tiles.png'); + this.load.tilemapTiledJSON('map', 'maps/map2.json'); + this.load.spritesheet('player', + 'resources/characters/pipoya/Male 01-1.png', + { frameWidth: 32, frameHeight: 32 } + ); + } + + //hook initialisation + init(){}; + + //hook create scene + create(): void { + //create map manager + this.MapManager = new MapManager(this); + } + + //hook update + update(dt: number): void { + this.MapManager.update(); + } +} diff --git a/front/src/Phaser/MapManager.ts b/front/src/Phaser/MapManager.ts new file mode 100644 index 00000000..ecd86210 --- /dev/null +++ b/front/src/Phaser/MapManager.ts @@ -0,0 +1,85 @@ +import {CameraManager, CameraManagerInterface} from "./CameraManager"; +import {RESOLUTION} from "../Enum/EnvironmentVariable"; +import {Player} from "./Player"; + +export interface MapManagerInterface { + keyZ: Phaser.Input.Keyboard.Key; + keyQ: Phaser.Input.Keyboard.Key; + keyS: Phaser.Input.Keyboard.Key; + keyD: Phaser.Input.Keyboard.Key; + keyRight: Phaser.Input.Keyboard.Key; + keyLeft: Phaser.Input.Keyboard.Key; + keyUp: Phaser.Input.Keyboard.Key; + keyDown: Phaser.Input.Keyboard.Key; + keyShift: Phaser.Input.Keyboard.Key; + + Map: Phaser.Tilemaps.Tilemap; + Terrain: Phaser.Tilemaps.Tileset; + Camera: CameraManagerInterface; + update(): void; +} +export class MapManager implements MapManagerInterface{ + keyZ: Phaser.Input.Keyboard.Key; + keyQ: Phaser.Input.Keyboard.Key; + keyS: Phaser.Input.Keyboard.Key; + keyD: Phaser.Input.Keyboard.Key; + keyRight: Phaser.Input.Keyboard.Key; + keyLeft: Phaser.Input.Keyboard.Key; + keyUp: Phaser.Input.Keyboard.Key; + keyDown: Phaser.Input.Keyboard.Key; + keyShift: Phaser.Input.Keyboard.Key; + + Terrain : Phaser.Tilemaps.Tileset; + Camera: CameraManagerInterface; + CurrentPlayer: Player; + Scene: Phaser.Scene; + Map: Phaser.Tilemaps.Tilemap; + startX = (window.innerWidth / 2) / RESOLUTION; + startY = (window.innerHeight / 2) / RESOLUTION; + + constructor(scene: Phaser.Scene){ + this.Scene = scene; + + //initalise map + this.Map = this.Scene.add.tilemap("map"); + this.Terrain = this.Map.addTilesetImage("tiles", "tiles"); + this.Map.createStaticLayer("tiles", "tiles"); + this.Map.createStaticLayer("Calque 1", [this.Terrain], 0, 0); + this.Map.createStaticLayer("Calque 2", [this.Terrain], 0, 0); + + //initialise keyboard + this.initKeyBoard(); + + //initialise player + this.CurrentPlayer = new Player( + this.Scene, + this.startX, + this.startY, + this + ); + this.CurrentPlayer.initAnimation(); + + //initialise camera + this.Camera = new CameraManager(this.Scene, this.Scene.cameras.main, this, this.CurrentPlayer); + } + + + initKeyBoard() { + this.keyShift = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT); + + this.keyZ = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Z); + this.keyQ = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q); + this.keyS = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); + this.keyD = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); + + this.keyUp = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.UP); + this.keyLeft = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT); + this.keyDown = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN); + this.keyRight = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT); + } + + update() : void { + this.CurrentPlayer.move(); + this.Camera.moveCamera() + } +} \ No newline at end of file diff --git a/front/src/Phaser/Player.ts b/front/src/Phaser/Player.ts new file mode 100644 index 00000000..f76778a4 --- /dev/null +++ b/front/src/Phaser/Player.ts @@ -0,0 +1,90 @@ +import {MapManagerInterface} from "./MapManager"; +import {getPlayerAnimations, playAnimation, PlayerAnimationNames} from "./Player/Animation"; + +export class Player extends Phaser.GameObjects.Sprite{ + MapManager : MapManagerInterface; + PlayerValue : string; + + constructor( + Scene : Phaser.Scene, + x : number, + y : number, + MapManager: MapManagerInterface, + PlayerValue : string = "player" + ) { + super(Scene, x, y, PlayerValue); + this.PlayerValue = PlayerValue; + Scene.add.existing(this); + this.MapManager = MapManager; + } + + + initAnimation(){ + getPlayerAnimations(this.PlayerValue).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 + }); + }) + } + + move(){ + //if user client on shift, camera and player speed + let speedMultiplier = this.MapManager.keyShift.isDown ? 5 : 1; + let haveMove = false; + + if((this.MapManager.keyZ.isDown || this.MapManager.keyUp.isDown)){ + if(!this.CanToMoveUp()){ + return; + } + playAnimation(this, PlayerAnimationNames.WalkUp); + this.setY(this.y - (2 * speedMultiplier)); + haveMove = true; + } + if((this.MapManager.keyQ.isDown || this.MapManager.keyLeft.isDown)){ + if(!this.CanToMoveLeft()){ + return; + } + playAnimation(this, PlayerAnimationNames.WalkLeft); + this.setX(this.x - (2 * speedMultiplier)); + haveMove = true; + } + if((this.MapManager.keyS.isDown || this.MapManager.keyDown.isDown)){ + if(!this.CanToMoveDown()){ + return; + } + playAnimation(this, PlayerAnimationNames.WalkDown); + this.setY(this.y + (2 * speedMultiplier)); + haveMove = true; + } + if((this.MapManager.keyD.isDown || this.MapManager.keyRight.isDown)){ + if(!this.CanToMoveRight()){ + return; + } + playAnimation(this, PlayerAnimationNames.WalkRight); + this.setX(this.x + (2 * speedMultiplier)); + haveMove = true; + } + if(!haveMove){ + playAnimation(this, PlayerAnimationNames.None); + } + } + + private CanToMoveUp(){ + return this.y > 0; + } + + private CanToMoveLeft(){ + return this.x > 0; + } + + private CanToMoveDown(){ + return this.MapManager.Map.heightInPixels > this.y; + } + + private CanToMoveRight(){ + return this.MapManager.Map.widthInPixels > this.x; + } +} \ No newline at end of file diff --git a/front/src/Phaser/Player/Animation.ts b/front/src/Phaser/Player/Animation.ts new file mode 100644 index 00000000..3652a8d1 --- /dev/null +++ b/front/src/Phaser/Player/Animation.ts @@ -0,0 +1,60 @@ +interface AnimationData { + key: string; + frameRate: number; + repeat: number; + frameModel: string; //todo use an enum + frameStart: number; + frameEnd: number; +} + +export enum PlayerAnimationNames { + WalkDown = 'down', + WalkLeft = 'left', + WalkUp = 'up', + WalkRight = 'right', + None = 'none', +}; + +export const getPlayerAnimations = (PlayerValue : string): AnimationData[] => { + return [{ + key: PlayerAnimationNames.WalkDown, + frameModel: PlayerValue, + frameStart: 0, + frameEnd: 2, + frameRate: 10, + repeat: -1 + }, { + key: PlayerAnimationNames.WalkLeft, + frameModel: PlayerValue, + frameStart: 3, + frameEnd: 5, + frameRate: 10, + repeat: -1 + }, { + key: PlayerAnimationNames.WalkRight, + frameModel: PlayerValue, + frameStart: 6, + frameEnd: 8, + frameRate: 10, + repeat: -1 + }, { + key: PlayerAnimationNames.WalkUp, + frameModel: PlayerValue, + frameStart: 9, + frameEnd: 11, + frameRate: 10, + repeat: -1 + }]; +}; + +export const playAnimation = (Player : Phaser.GameObjects.Sprite, direction : string) => { + if (!Player.anims.currentAnim || Player.anims.currentAnim.key !== direction) { + if (direction !== PlayerAnimationNames.None) { + Player.anims.play(direction); + } else if (Player.anims.isPlaying) { + Player.anims.stop(); + } + } else if (direction === PlayerAnimationNames.None && Player.anims.currentAnim) { + Player.anims.currentAnim.destroy(); + } +}; diff --git a/front/src/index.ts b/front/src/index.ts index cf100627..f0f5107d 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -1,6 +1,6 @@ import 'phaser'; import GameConfig = Phaser.Types.Core.GameConfig; -import {GameScene} from "./GameScene"; +import {GameScene} from "./Phaser/GameScene"; import {Connexion} from "./Connexion"; import {RESOLUTION} from "./Enum/EnvironmentVariable";