diff --git a/front/dist/maps/map2.json b/front/dist/maps/map2.json index 9a10e634..d68f4df9 100644 --- a/front/dist/maps/map2.json +++ b/front/dist/maps/map2.json @@ -155,6 +155,12 @@ }, { "id":77, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }], "terrain":[2, 2, 2, 2] }, { diff --git a/front/dist/resources/objects/rockSprite.png b/front/dist/resources/objects/rockSprite.png new file mode 100644 index 00000000..40820abd Binary files /dev/null and b/front/dist/resources/objects/rockSprite.png differ diff --git a/front/src/Phaser/Entity/PlayableCaracter.ts b/front/src/Phaser/Entity/PlayableCaracter.ts new file mode 100644 index 00000000..69bcfd55 --- /dev/null +++ b/front/src/Phaser/Entity/PlayableCaracter.ts @@ -0,0 +1,45 @@ +import {getPlayerAnimations, playAnimation, PlayerAnimationNames} from "../Player/Animation"; +import {ActiveEventList, UserInputEvent} from "../UserInput/UserInputManager"; +import {SpeechBubble} from "./SpeechBubble"; + +export class PlayableCaracter extends Phaser.Physics.Arcade.Sprite { + private bubble: SpeechBubble; + + constructor(scene: Phaser.Scene, x: number, y: number, texture: string, frame?: string | number) { + super(scene, x, y, texture, frame); + + this.scene.sys.updateList.add(this); + this.scene.sys.displayList.add(this); + this.setScale(2); + this.scene.physics.world.enableBody(this); + this.setImmovable(true); + this.setCollideWorldBounds(true); + this.setSize(32, 32); //edit the hitbox to better match the caracter model + } + + move(x: number, y: number){ + + this.setVelocity(x, y); + + //todo improve animations to better account for diagonal movement + if (this.body.velocity.x > 0) { //moving right + this.play(PlayerAnimationNames.WalkRight, true); + } else if (this.body.velocity.x < 0) { //moving left + this.anims.playReverse(PlayerAnimationNames.WalkLeft, true); + } else if (this.body.velocity.y < 0) { //moving up + this.play(PlayerAnimationNames.WalkUp, true); + } else if (this.body.velocity.y > 0) { //moving down + this.play(PlayerAnimationNames.WalkDown, true); + } + } + + say(text: string) { + if (this.bubble) return; + this.bubble = new SpeechBubble(this.scene, this, text) + //todo make the buble destroy on player movement? + setTimeout(() => { + this.bubble.destroy(); + this.bubble = null; + }, 3000) + } +} \ No newline at end of file diff --git a/front/src/Phaser/Entity/SpeechBubble.ts b/front/src/Phaser/Entity/SpeechBubble.ts new file mode 100644 index 00000000..e3a055b2 --- /dev/null +++ b/front/src/Phaser/Entity/SpeechBubble.ts @@ -0,0 +1,62 @@ +import Scene = Phaser.Scene; +import {PlayableCaracter} from "./PlayableCaracter"; + +export class SpeechBubble { + private bubble: Phaser.GameObjects.Graphics; + private content: Phaser.GameObjects.Text; + + constructor(scene: Scene, player: PlayableCaracter, text: string) { + + let bubbleHeight = 50; + let bubblePadding = 10; + let bubbleWidth = bubblePadding * 2 + text.length * 10; + let arrowHeight = bubbleHeight / 4; + + this.bubble = scene.add.graphics({ x: player.x + 16, y: player.y - 80 }); + + // Bubble shadow + this.bubble.fillStyle(0x222222, 0.5); + this.bubble.fillRoundedRect(6, 6, bubbleWidth, bubbleHeight, 16); + + // this.bubble color + this.bubble.fillStyle(0xffffff, 1); + + // this.bubble outline line style + this.bubble.lineStyle(4, 0x565656, 1); + + // this.bubble shape and outline + this.bubble.strokeRoundedRect(0, 0, bubbleWidth, bubbleHeight, 16); + this.bubble.fillRoundedRect(0, 0, bubbleWidth, bubbleHeight, 16); + + // Calculate arrow coordinates + let point1X = Math.floor(bubbleWidth / 7); + let point1Y = bubbleHeight; + let point2X = Math.floor((bubbleWidth / 7) * 2); + let point2Y = bubbleHeight; + let point3X = Math.floor(bubbleWidth / 7); + let point3Y = Math.floor(bubbleHeight + arrowHeight); + + // bubble arrow shadow + this.bubble.lineStyle(4, 0x222222, 0.5); + this.bubble.lineBetween(point2X - 1, point2Y + 6, point3X + 2, point3Y); + + // bubble arrow fill + this.bubble.fillTriangle(point1X, point1Y, point2X, point2Y, point3X, point3Y); + this.bubble.lineStyle(2, 0x565656, 1); + this.bubble.lineBetween(point2X, point2Y, point3X, point3Y); + this.bubble.lineBetween(point1X, point1Y, point3X, point3Y); + + this.content = scene.add.text(0, 0, text, { fontFamily: 'Arial', fontSize: 20, color: '#000000', align: 'center', wordWrap: { width: bubbleWidth - (bubblePadding * 2) } }); + + let bounds = this.content.getBounds(); + + this.content.setPosition(this.bubble.x + (bubbleWidth / 2) - (bounds.width / 2), this.bubble.y + (bubbleHeight / 2) - (bounds.height / 2)); + + } + + destroy(): void { + this.bubble.setVisible(false) //todo find a better way + this.content.destroy() + } + +} \ No newline at end of file diff --git a/front/src/Phaser/Entity/Sprite.ts b/front/src/Phaser/Entity/Sprite.ts new file mode 100644 index 00000000..f2abad52 --- /dev/null +++ b/front/src/Phaser/Entity/Sprite.ts @@ -0,0 +1,8 @@ +export class Sprite extends Phaser.GameObjects.Sprite { + + constructor(scene: Phaser.Scene, x: number, y: number, texture: string, frame?: number | string) { + super(scene, x, y, texture, frame); + scene.sys.updateList.add(this); + scene.sys.displayList.add(this); + } +} \ No newline at end of file diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts index 71a3cbe3..d03a3152 100644 --- a/front/src/Phaser/Game/GameManager.ts +++ b/front/src/Phaser/Game/GameManager.ts @@ -50,6 +50,7 @@ export class GameManager implements GameManagerInterface { * @param UserId */ createCurrentPlayer(): void { + //Get started room send by the backend let game: GameSceneInterface = this.GameScenes.find((Game: GameSceneInterface) => Game.RoomId === ConnexionInstance.startedRoom); game.createCurrentPlayer(ConnexionInstance.userId); this.status = StatusGameManagerEnum.CURRENT_USER_CREATED; diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 61afdf68..a9a08fc6 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -2,6 +2,13 @@ import {MapManagerInterface, MapManager} from "./MapManager"; import {GameManagerInterface, StatusGameManagerEnum} from "./GameManager"; import {MessageUserPositionInterface} from "../../Connexion"; +export enum Textures { + Rock = 'rock', + Player = 'playerModel', + Map = 'map', + Tiles = 'tiles' +} + export interface GameSceneInterface extends Phaser.Scene { RoomId : string; createCurrentPlayer(UserId : string) : void; @@ -22,9 +29,10 @@ export class GameScene extends Phaser.Scene implements GameSceneInterface{ //hook preload scene preload(): void { - this.load.image('tiles', 'maps/tiles.png'); - this.load.tilemapTiledJSON('map', 'maps/map2.json'); - this.load.spritesheet('player', + this.load.image(Textures.Tiles, 'maps/tiles.png'); + this.load.tilemapTiledJSON(Textures.Map, 'maps/map2.json'); + this.load.image(Textures.Rock, 'resources/objects/rockSprite.png'); + this.load.spritesheet(Textures.Player, 'resources/characters/pipoya/Male 01-1.png', { frameWidth: 32, frameHeight: 32 } ); diff --git a/front/src/Phaser/Game/MapManager.ts b/front/src/Phaser/Game/MapManager.ts index a66e0d37..3a91954c 100644 --- a/front/src/Phaser/Game/MapManager.ts +++ b/front/src/Phaser/Game/MapManager.ts @@ -1,20 +1,11 @@ import {CameraManager, CameraManagerInterface} from "./CameraManager"; import {RESOLUTION} from "../../Enum/EnvironmentVariable"; import {CurrentGamerInterface, GamerInterface, Player} from "../Player/Player"; -import {GameSceneInterface} from "./GameScene"; +import {GameSceneInterface, Textures} from "./GameScene"; import {MessageUserPositionInterface} from "../../Connexion"; +import {NonPlayer} from "../NonPlayer/NonPlayer"; 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; @@ -25,25 +16,20 @@ export interface MapManagerInterface { updateOrCreateMapPlayer(UsersPosition : Array): 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: CurrentGamerInterface; - MapPlayers : GamerInterface[]; + MapPlayers : Phaser.Physics.Arcade.Group; Scene: GameSceneInterface; Map: Phaser.Tilemaps.Tilemap; + BottomLayer: Phaser.Tilemaps.StaticTilemapLayer; + TopLayer: Phaser.Tilemaps.StaticTilemapLayer; startX = (window.innerWidth / 2) / RESOLUTION; startY = (window.innerHeight / 2) / RESOLUTION; + //entities + private rock: Phaser.Physics.Arcade.Sprite; + constructor(scene: GameSceneInterface){ this.Scene = scene; @@ -51,15 +37,29 @@ export class MapManager implements MapManagerInterface{ 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); + this.BottomLayer = this.Map.createStaticLayer("Calque 1", [this.Terrain], 0, 0).setDepth(-2); + this.TopLayer = this.Map.createStaticLayer("Calque 2", [this.Terrain], 0, 0).setDepth(-1); + this.Scene.physics.world.setBounds(0,0, this.Map.widthInPixels, this.Map.heightInPixels); + + //add entitites + this.rock = this.Scene.physics.add.sprite(200, 400, Textures.Rock, 26).setImmovable(true); + + //debug code + //debug code to see the collision hitbox of the object in the top layer + this.TopLayer.renderDebug(this.Scene.add.graphics(),{ + tileColor: null, //non-colliding tiles + collidingTileColor: new Phaser.Display.Color(243, 134, 48, 200), // Colliding tiles, + faceColor: new Phaser.Display.Color(40, 39, 37, 255) // Colliding face edges + }); + + //init event click + this.EventToClickOnTile(); - //initialise keyboard - this.initKeyBoard(); //initialise camera this.Camera = new CameraManager(this.Scene, this.Scene.cameras.main, this); + //initialise list of other player - this.MapPlayers = new Array(); + this.MapPlayers = this.Scene.physics.add.group({ immovable: true }); } createCurrentPlayer(UserId : string){ @@ -73,24 +73,28 @@ export class MapManager implements MapManagerInterface{ this ); this.CurrentPlayer.initAnimation(); + + //create collision + this.Scene.physics.add.collider(this.CurrentPlayer, this.rock); + //add collision layer + this.Scene.physics.add.collider(this.CurrentPlayer, this.TopLayer); + this.TopLayer.setCollisionByProperty({collides:true}); } - 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); + EventToClickOnTile(){ + // debug code to get a tile properties by clicking on it + this.Scene.input.on("pointerdown", (pointer: Phaser.Input.Pointer)=>{ + //pixel position toz tile position + let tile = this.Map.getTileAt(this.Map.worldToTileX(pointer.worldX), this.Map.worldToTileY(pointer.worldY)); + if(tile){ + //console.log("MapManager => tile => pointerdown", tile); + this.CurrentPlayer.say("Your touch " + tile.layer.name); + } + }); } update() : void { - this.CurrentPlayer.move(); + this.CurrentPlayer.moveUser(); } /** @@ -107,7 +111,7 @@ export class MapManager implements MapManagerInterface{ if(userPosition.userId === this.CurrentPlayer.userId){ return; } - let player = this.MapPlayers.find((player: Player) => userPosition.userId === player.userId); + let player = this.findPlayerInMap(userPosition.userId); if(!player){ this.addPlayer(userPosition); }else{ @@ -116,15 +120,21 @@ export class MapManager implements MapManagerInterface{ }); //clean map - let mapPlayers = new Array(); - this.MapPlayers.forEach((player: Player) => { + this.MapPlayers.getChildren().forEach((player: GamerInterface) => { if(UsersPosition.find((message : MessageUserPositionInterface) => message.userId === player.userId)){ - mapPlayers.push(player); return; } player.destroy(); + this.MapPlayers.remove(player); }); - this.MapPlayers = mapPlayers; + } + + private findPlayerInMap(UserId : string) : GamerInterface | null{ + let player = this.MapPlayers.getChildren().find((player: Player) => UserId === player.userId); + if(!player){ + return null; + } + return (player as GamerInterface); } /** @@ -142,7 +152,12 @@ export class MapManager implements MapManagerInterface{ this ); player.initAnimation(); - this.MapPlayers.push(player); - player.updatePosition(MessageUserPosition) + this.MapPlayers.add(player); + player.updatePosition(MessageUserPosition); + + //init colision + this.Scene.physics.add.collider(this.CurrentPlayer, player, (CurrentPlayer: CurrentGamerInterface, MapPlayer: GamerInterface) => { + MapPlayer.say("Hello, how are you ? "); + }); } } \ No newline at end of file diff --git a/front/src/Phaser/NonPlayer/NonPlayer.ts b/front/src/Phaser/NonPlayer/NonPlayer.ts new file mode 100644 index 00000000..63012e46 --- /dev/null +++ b/front/src/Phaser/NonPlayer/NonPlayer.ts @@ -0,0 +1,40 @@ +import {PlayableCaracter} from "../Entity/PlayableCaracter"; +import {Textures} from "../Game/GameScene"; +import {UserInputEvent} from "../UserInput/UserInputManager"; +import {Player} from "../Player/Player"; +import {MessageUserPositionInterface} from "../../Connexion"; +import {playAnimation} from "../Player/Animation"; + +export class NonPlayer extends PlayableCaracter { + + isFleeing: boolean = false; + fleeingDirection:any = null //todo create a vector class + + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y, Textures.Player, 1); + this.setSize(32, 32); //edit the hitbox to better match the caracter model + } + + + updatePosition(MessageUserPosition : MessageUserPositionInterface){ + playAnimation(this, MessageUserPosition.position.direction); + this.setX(MessageUserPosition.position.x); + this.setY(MessageUserPosition.position.y); + } + + fleeFrom(player:Player) { + if (this.isFleeing) return; + this.say("Don't touch me!"); + this.isFleeing = true; + + setTimeout(() => { + this.say("Feww, I escaped."); + this.isFleeing = false + this.fleeingDirection = null + }, 3000); + + let vectorX = this.x - player.x; + let vectorY = this.y - player.y; + this.fleeingDirection = {x: vectorX, y: vectorY} + } +} \ No newline at end of file diff --git a/front/src/Phaser/Player/Animation.ts b/front/src/Phaser/Player/Animation.ts index eb8298f4..48f34682 100644 --- a/front/src/Phaser/Player/Animation.ts +++ b/front/src/Phaser/Player/Animation.ts @@ -1,3 +1,5 @@ +import {Textures} from "../Game/GameScene"; + interface AnimationData { key: string; frameRate: number; @@ -15,31 +17,31 @@ export enum PlayerAnimationNames { None = 'none', } -export const getPlayerAnimations = (PlayerValue : string): AnimationData[] => { +export const getPlayerAnimations = (): AnimationData[] => { return [{ key: PlayerAnimationNames.WalkDown, - frameModel: PlayerValue, + frameModel: Textures.Player, frameStart: 0, frameEnd: 2, frameRate: 10, repeat: -1 }, { key: PlayerAnimationNames.WalkLeft, - frameModel: PlayerValue, + frameModel: Textures.Player, frameStart: 3, frameEnd: 5, frameRate: 10, repeat: -1 }, { key: PlayerAnimationNames.WalkRight, - frameModel: PlayerValue, + frameModel: Textures.Player, frameStart: 6, frameEnd: 8, frameRate: 10, repeat: -1 }, { key: PlayerAnimationNames.WalkUp, - frameModel: PlayerValue, + frameModel: Textures.Player, frameStart: 9, frameEnd: 11, frameRate: 10, @@ -53,4 +55,4 @@ export const playAnimation = (Player : Phaser.GameObjects.Sprite, direction : st } else if (direction === PlayerAnimationNames.None && Player.anims.currentAnim) { Player.anims.currentAnim.destroy(); } -}; +} diff --git a/front/src/Phaser/Player/Player.ts b/front/src/Phaser/Player/Player.ts index f256bbf4..78aa5801 100644 --- a/front/src/Phaser/Player/Player.ts +++ b/front/src/Phaser/Player/Player.ts @@ -1,33 +1,38 @@ -import {MapManagerInterface} from "../Game/MapManager"; import {getPlayerAnimations, playAnimation, PlayerAnimationNames} from "./Animation"; -import {GameSceneInterface} from "../Game/GameScene"; +import {GameSceneInterface, Textures} from "../Game/GameScene"; import {ConnexionInstance} from "../Game/GameManager"; import {CameraManagerInterface} from "../Game/CameraManager"; import {MessageUserPositionInterface} from "../../Connexion"; +import {ActiveEventList, UserInputEvent, UserInputManager} from "../UserInput/UserInputManager"; +import {PlayableCaracter} from "../Entity/PlayableCaracter"; +import {MapManagerInterface} from "../Game/MapManager"; -export interface CurrentGamerInterface{ +export interface CurrentGamerInterface extends PlayableCaracter{ userId : string; MapManager : MapManagerInterface; PlayerValue : string; CameraManager: CameraManagerInterface; initAnimation() : void; - move() : void; + moveUser() : void; + say(text : string) : void; } -export interface GamerInterface{ +export interface GamerInterface extends PlayableCaracter{ userId : string; MapManager : MapManagerInterface; PlayerValue : string; CameraManager: CameraManagerInterface; initAnimation() : void; updatePosition(MessageUserPosition : MessageUserPositionInterface) : void; + say(text : string) : void; } -export class Player extends Phaser.GameObjects.Sprite implements CurrentGamerInterface, GamerInterface{ +export class Player extends PlayableCaracter implements CurrentGamerInterface, GamerInterface{ userId : string; MapManager : MapManagerInterface; PlayerValue : string; CameraManager: CameraManagerInterface; + userInputManager: UserInputManager; constructor( userId: string, @@ -36,72 +41,80 @@ export class Player extends Phaser.GameObjects.Sprite implements CurrentGamerInt y : number, CameraManager: CameraManagerInterface, MapManager: MapManagerInterface, - PlayerValue : string = "player" + PlayerValue : string = Textures.Player ) { - super(Scene, x, y, PlayerValue); + super(Scene, x, y, PlayerValue, 1); + + //create input to move + this.userInputManager = new UserInputManager(Scene); + + //set data this.userId = userId; this.PlayerValue = PlayerValue; - Scene.add.existing(this); this.MapManager = MapManager; this.CameraManager = CameraManager; + + //the current player model should be push away by other players to prevent conflict + this.setImmovable(false); + //edit the hitbox to better match the caracter model + this.setSize(32, 32); } - initAnimation() : void{ - getPlayerAnimations(this.PlayerValue).forEach(d => { + initAnimation() : void { + getPlayerAnimations().forEach(d => { this.scene.anims.create({ key: d.key, - frames: this.scene.anims.generateFrameNumbers(d.frameModel, { start: d.frameStart, end: d.frameEnd }), + frames: this.scene.anims.generateFrameNumbers(d.frameModel, {start: d.frameStart, end: d.frameEnd}), frameRate: d.frameRate, repeat: d.repeat }); }) } - move() : void{ + moveUser() : void { //if user client on shift, camera and player speed - let speedMultiplier = this.MapManager.keyShift.isDown ? 5 : 1; + //let speedMultiplier = this.MapManager.keyShift.isDown ? 5 : 1; let haveMove = false; let direction = null; - if((this.MapManager.keyZ.isDown || this.MapManager.keyUp.isDown)){ - if(!this.CanMoveUp()){ + let activeEvents = this.userInputManager.getEventListForGameTick(); + let speedMultiplier = activeEvents.get(UserInputEvent.SpeedUp) ? 500 : 100; + + if (activeEvents.get(UserInputEvent.MoveUp)) { + if (!this.CanMoveUp()) { return; } - playAnimation(this, PlayerAnimationNames.WalkUp); - this.setY(this.y - (2 * speedMultiplier)); + this.move(0, -speedMultiplier); haveMove = true; direction = PlayerAnimationNames.WalkUp; } - if((this.MapManager.keyQ.isDown || this.MapManager.keyLeft.isDown)){ - if(!this.CanMoveLeft()){ + if (activeEvents.get(UserInputEvent.MoveLeft)) { + if (!this.CanMoveLeft()) { return; } - playAnimation(this, PlayerAnimationNames.WalkLeft); - this.setX(this.x - (2 * speedMultiplier)); + this.move(-speedMultiplier, 0); haveMove = true; direction = PlayerAnimationNames.WalkLeft; } - if((this.MapManager.keyS.isDown || this.MapManager.keyDown.isDown)){ - if(!this.CanMoveDown()){ + if (activeEvents.get(UserInputEvent.MoveDown)) { + if (!this.CanMoveDown()) { return; } - playAnimation(this, PlayerAnimationNames.WalkDown); - this.setY(this.y + (2 * speedMultiplier)); + this.move(0, speedMultiplier); haveMove = true; direction = PlayerAnimationNames.WalkDown; } - if((this.MapManager.keyD.isDown || this.MapManager.keyRight.isDown)){ - if(!this.CanMoveRight()){ + if (activeEvents.get(UserInputEvent.MoveRight)) { + if (!this.CanMoveRight()) { return; } - playAnimation(this, PlayerAnimationNames.WalkRight); - this.setX(this.x + (2 * speedMultiplier)); + this.move(speedMultiplier, 0); haveMove = true; direction = PlayerAnimationNames.WalkRight; } - if(!haveMove){ - playAnimation(this, PlayerAnimationNames.None); + if (!haveMove) { direction = PlayerAnimationNames.None; + this.move(0, 0) } this.sharePosition(direction); this.CameraManager.moveCamera(this); @@ -125,10 +138,14 @@ export class Player extends Phaser.GameObjects.Sprite implements CurrentGamerInt return this.MapManager.Map.heightInPixels > this.y; } - private CanMoveRight(){ + private CanMoveRight() { return this.MapManager.Map.widthInPixels > this.x; } + stop() { + this.setVelocity(0, 0) + } + updatePosition(MessageUserPosition : MessageUserPositionInterface){ playAnimation(this, MessageUserPosition.position.direction); this.setX(MessageUserPosition.position.x); diff --git a/front/src/Phaser/UserInput/UserInputManager.ts b/front/src/Phaser/UserInput/UserInputManager.ts new file mode 100644 index 00000000..6c5b32c2 --- /dev/null +++ b/front/src/Phaser/UserInput/UserInputManager.ts @@ -0,0 +1,68 @@ +import Map = Phaser.Structs.Map; +import {GameSceneInterface} from "../Game/GameScene"; + +interface UserInputManagerDatum { + keyCode: number; + keyInstance: Phaser.Input.Keyboard.Key; + event: UserInputEvent +} + +export enum UserInputEvent { + MoveLeft = 1, + MoveUp, + MoveRight, + MoveDown, + SpeedUp, + Interact, + Shout, +} + +//we cannot the map structure so we have to create a replacment +export class ActiveEventList { + private KeysCode : any; + constructor() { + this.KeysCode = {}; + } + get(event: UserInputEvent): boolean { + return this.KeysCode[event] || false; + } + set(event: UserInputEvent, value: boolean): boolean { + return this.KeysCode[event] = true; + } +} + +//this class is responsible for catching user inputs and listing all active user actions at every game tick events. +export class UserInputManager { + private KeysCode: UserInputManagerDatum[] = [ + {keyCode: Phaser.Input.Keyboard.KeyCodes.Z, event: UserInputEvent.MoveUp, keyInstance: null}, + {keyCode: Phaser.Input.Keyboard.KeyCodes.Q, event: UserInputEvent.MoveLeft, keyInstance: null}, + {keyCode: Phaser.Input.Keyboard.KeyCodes.S, event: UserInputEvent.MoveDown, keyInstance: null}, + {keyCode: Phaser.Input.Keyboard.KeyCodes.D, event: UserInputEvent.MoveRight, keyInstance: null}, + + {keyCode: Phaser.Input.Keyboard.KeyCodes.UP, event: UserInputEvent.MoveUp, keyInstance: null}, + {keyCode: Phaser.Input.Keyboard.KeyCodes.LEFT, event: UserInputEvent.MoveLeft, keyInstance: null}, + {keyCode: Phaser.Input.Keyboard.KeyCodes.DOWN, event: UserInputEvent.MoveDown, keyInstance: null}, + {keyCode: Phaser.Input.Keyboard.KeyCodes.RIGHT, event: UserInputEvent.MoveRight, keyInstance: null}, + + {keyCode: Phaser.Input.Keyboard.KeyCodes.SHIFT, event: UserInputEvent.SpeedUp, keyInstance: null}, + + {keyCode: Phaser.Input.Keyboard.KeyCodes.E, event: UserInputEvent.Interact, keyInstance: null}, + {keyCode: Phaser.Input.Keyboard.KeyCodes.F, event: UserInputEvent.Shout, keyInstance: null}, + ]; + + constructor(Scene : GameSceneInterface) { + this.KeysCode.forEach(d => { + d.keyInstance = Scene.input.keyboard.addKey(d.keyCode); + }); + } + + getEventListForGameTick(): ActiveEventList { + let eventsMap = new ActiveEventList(); + this.KeysCode.forEach(d => { + if (d. keyInstance.isDown) { + eventsMap.set(d.event, true); + } + }); + return eventsMap; + } +} \ No newline at end of file diff --git a/front/src/index.ts b/front/src/index.ts index 2a18110d..5d90a19e 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -12,6 +12,12 @@ const config: GameConfig = { parent: "game", scene: gameManager.GameScenes, zoom: RESOLUTION, + physics: { + default: "arcade", + arcade: { + debug: true + } + } }; gameManager.createGame().then(() => {