diff --git a/back/src/Controller/AuthenticateController.ts b/back/src/Controller/AuthenticateController.ts index f9eed470..6175984f 100644 --- a/back/src/Controller/AuthenticateController.ts +++ b/back/src/Controller/AuthenticateController.ts @@ -3,6 +3,7 @@ import Jwt from "jsonwebtoken"; import {BAD_REQUEST, OK} from "http-status-codes"; import {SECRET_KEY, ROOM} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..." import { uuid } from 'uuidv4'; +import {userManager} from "../Model/Users/UserManager"; export class AuthenticateController{ App : Application; @@ -10,6 +11,7 @@ export class AuthenticateController{ constructor(App : Application) { this.App = App; this.login(); + this.getAllUsers(); } //permit to login on application. Return token to connect on Websocket IO. @@ -22,13 +24,16 @@ export class AuthenticateController{ }); } //TODO check user email for The Coding Machine game - let userId = uuid(); - let token = Jwt.sign({email: param.email, roomId: ROOM, userId: userId}, SECRET_KEY, {expiresIn: '24h'}); - return res.status(OK).send({ - token: token, - roomId: ROOM, - userId: userId - }); + let user = userManager.createUser(param.email); + let token = Jwt.sign({email: user.email, userId: user.id}, SECRET_KEY, {expiresIn: '24h'}); + return res.status(OK).send(user); }); } -} \ No newline at end of file + + getAllUsers(){ + this.App.get("/users", (req: Request, res: Response) => { + let users = userManager.getAllUsers(); + return res.status(OK).send(users); + }); + } +} diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 1fc114a4..836cc280 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -7,6 +7,7 @@ import Jwt, {JsonWebTokenError} from "jsonwebtoken"; import {SECRET_KEY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..." import {ExtRooms, RefreshUserPositionFunction} from "../Model/Websocket/ExtRoom"; import {ExtRoomsInterface} from "_Model/Websocket/ExtRoomsInterface"; +import {userManager} from "../Model/Users/UserManager"; export class IoSocketController{ Io: socketIO.Server; @@ -112,23 +113,12 @@ export class IoSocketController{ **/ seTimeOutInProgress : any = null; shareUsersPosition(){ - if(this.seTimeOutInProgress){ - clearTimeout(this.seTimeOutInProgress); - } - //send for each room, all data of position user - let arrayMap = (this.Io.sockets.adapter.rooms as ExtRooms).userPositionMapByRoom; - if(!arrayMap){ - this.seTimeOutInProgress = setTimeout(() => { - this.shareUsersPosition(); - }, 10); - return; - } - arrayMap.forEach((value : any) => { - let roomId = value[0]; - this.Io.in(roomId).emit('user-position', JSON.stringify(arrayMap)); - }); - this.seTimeOutInProgress = setTimeout(() => { - this.shareUsersPosition(); - }, 10); + //every 1/10 of seconds, emit the current list of events + setInterval(() => { + let userEvents = userManager.getEventList(); + if (userEvents.length) { + this.Io.emit('user-position', JSON.stringify(userEvents)); + } + }, 100) } } diff --git a/back/src/Model/Users/UserManager.ts b/back/src/Model/Users/UserManager.ts new file mode 100644 index 00000000..0972208e --- /dev/null +++ b/back/src/Model/Users/UserManager.ts @@ -0,0 +1,86 @@ +import {uuid} from "uuidv4"; +import {BehaviorSubject} from "rxjs"; + +export interface UserPosition { + x: number; + y: number; +} + +export class User { + name: string; + email: string; + position: UserPosition; + id: string; + + constructor(id: string, name: string, email: string, position: UserPosition) { + this.id = id; + this.name = name; + this.email = email; + this.position = position + } +} + +export interface UserPositionChangeEvent { + user: User; + deleted: boolean + added: boolean +} + +class UserManager { + + private usersList: Map = new Map(); + + private eventsList: UserPositionChangeEvent[] = []; + + //todo add more parameters + createUser(email: string): User { + let userId = uuid(); + let user = new User(userId, "toto", email, {x: 0, y: 0}); + + this.usersList.set(userId, user); + this.eventsList.push({added: true, deleted: false, user}) + return user; + } + + deleteUser(id: string): User { + let user = this.usersList.get(id); + if (!user) { + throw "Could not delete user with id "+id; + } + this.usersList.delete(id); + + this.eventsList.push({added: false, deleted: true, user}); + return user; + } + + updateUserPosition(id: string, userPosition: UserPosition): User { + let user = this.usersList.get(id); + if (!user) { + throw "Could not find user with id "+id; + } + user.position = userPosition; + this.usersList.set(id, user); + + this.eventsList.push({added: false, deleted: false, user}); + return user; + } + + getAllUsers(): User[] { + let array = []; + for (const value of this.usersList.values()) { + array.push(value); + } + return array; + } + + //flush the list of events + getEventList(): UserPositionChangeEvent[] { + let events = this.eventsList; + this.eventsList = []; + return events; + } +} + +export const userManager = new UserManager(); + + diff --git a/back/tsconfig.json b/back/tsconfig.json index 7686fb67..e4c7b050 100644 --- a/back/tsconfig.json +++ b/back/tsconfig.json @@ -66,6 +66,7 @@ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ /* Advanced Options */ + "downlevelIteration": true, "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ } } diff --git a/front/dist/resources/objects/play_button.png b/front/dist/resources/objects/play_button.png new file mode 100644 index 00000000..36aa309b Binary files /dev/null and b/front/dist/resources/objects/play_button.png differ diff --git a/front/dist/resources/objects/rockSprite.png b/front/dist/resources/objects/rockSprite.png deleted file mode 100644 index 40820abd..00000000 Binary files a/front/dist/resources/objects/rockSprite.png and /dev/null differ diff --git a/front/package.json b/front/package.json index 25d613e6..8d40e22e 100644 --- a/front/package.json +++ b/front/package.json @@ -17,6 +17,7 @@ "@types/axios": "^0.14.0", "@types/socket.io-client": "^1.4.32", "phaser": "^3.22.0", + "rxjs": "^6.5.5", "socket.io-client": "^2.3.0" }, "scripts": { diff --git a/front/src/Connexion.ts b/front/src/Connexion.ts deleted file mode 100644 index 0d9f998a..00000000 --- a/front/src/Connexion.ts +++ /dev/null @@ -1,212 +0,0 @@ -import {GameManagerInterface} from "./Phaser/Game/GameManager"; - -const SocketIo = require('socket.io-client'); -import Axios from "axios"; -import {API_URL} from "./Enum/EnvironmentVariable"; - -class Message { - userId: string; - roomId: string; - - constructor(userId : string, roomId : string) { - this.userId = userId; - this.roomId = roomId; - } - - toJson() { - return { - userId: this.userId, - roomId: this.roomId, - } - } -} - -export interface PointInterface { - x: number; - y: number; - direction : string; - toJson() : object; -} - -class Point implements PointInterface{ - x: number; - y: number; - direction : string; - - constructor(x : number, y : number, direction : string = "none") { - if(x === null || y === null){ - throw Error("position x and y cannot be null"); - } - this.x = x; - this.y = y; - this.direction = direction; - } - - toJson(){ - return { - x : this.x, - y: this.y, - direction: this.direction - } - } -} - -export interface MessageUserPositionInterface { - userId: string; - roomId: string; - position: PointInterface; -} -class MessageUserPosition extends Message implements MessageUserPositionInterface{ - position: PointInterface; - - constructor(userId : string, roomId : string, point : Point) { - super(userId, roomId); - this.position = point; - } - - toString() { - return JSON.stringify( - Object.assign( - super.toJson(), - { - position: this.position.toJson() - }) - ); - } -} - -export interface ListMessageUserPositionInterface { - roomId : string; - listUsersPosition: Array; -} -class ListMessageUserPosition{ - roomId : string; - listUsersPosition: Array; - - constructor(roomId : string, data : any) { - this.roomId = roomId; - this.listUsersPosition = new Array(); - data.forEach((userPosition: any) => { - this.listUsersPosition.push(new MessageUserPosition( - userPosition.userId, - userPosition.roomId, - new Point( - userPosition.position.x, - userPosition.position.y, - userPosition.position.direction - ) - )); - }); - } -} -export interface ConnexionInterface { - socket : any; - token : string; - email : string; - userId: string; - startedRoom : string; - createConnexion() : Promise; - joinARoom(roomId : string) : void; - sharePosition(roomId : string, x : number, y : number, direction : string) : void; - positionOfAllUser() : void; -} -export class Connexion implements ConnexionInterface{ - socket : any; - token : string; - email : string; - userId: string; - startedRoom : string; - - GameManager: GameManagerInterface; - - constructor(email : string, GameManager: GameManagerInterface) { - this.email = email; - this.GameManager = GameManager; - } - - createConnexion() : Promise{ - return Axios.post(`${API_URL}/login`, {email: this.email}) - .then((res) => { - this.token = res.data.token; - this.startedRoom = res.data.roomId; - this.userId = res.data.userId; - - this.socket = SocketIo(`${API_URL}`, { - query: { - token: this.token - } - }); - - //join the room - this.joinARoom(this.startedRoom); - - //share your first position - this.sharePosition(this.startedRoom, 0, 0); - - this.positionOfAllUser(); - - this.errorMessage(); - - return this; - }) - .catch((err) => { - console.error(err); - throw err; - }); - } - - /** - * Permit to join a room - * @param roomId - */ - joinARoom(roomId : string) : void { - let messageUserPosition = new MessageUserPosition(this.userId, this.startedRoom, new Point(0, 0)); - this.socket.emit('join-room', messageUserPosition.toString()); - } - - /** - * - * @param roomId - * @param x - * @param y - * @param direction - */ - sharePosition(roomId : string, x : number, y : number, direction : string = "none") : void{ - if(!this.socket){ - return; - } - let messageUserPosition = new MessageUserPosition(this.userId, roomId, new Point(x, y, direction)); - this.socket.emit('user-position', messageUserPosition.toString()); - } - - /** - * The data sent is an array with information for each user : - * [ - * { - * userId: , - * roomId: , - * position: { - * x : , - * y : , - * direction: - * } - * }, - * ... - * ] - **/ - positionOfAllUser() : void { - this.socket.on("user-position", (message: string) => { - let dataList = JSON.parse(message); - dataList.forEach((UserPositions: any) => { - let listMessageUserPosition = new ListMessageUserPosition(UserPositions[0], UserPositions[1]); - this.GameManager.shareUserPosition(listMessageUserPosition); - }); - }); - } - - errorMessage() : void { - this.socket.on('message-error', (message : string) => { - console.error("message-error", message); - }) - } -} \ No newline at end of file diff --git a/front/src/Connexion/ConnectedUser.ts b/front/src/Connexion/ConnectedUser.ts new file mode 100644 index 00000000..03a5c9ec --- /dev/null +++ b/front/src/Connexion/ConnectedUser.ts @@ -0,0 +1,17 @@ +export class ConnectedUser { + id: string; + name: string; + email: string; + x: number; + y: number; + roomId: string + + constructor( id: string,name: string, email: string, x: number, y: number) { + this.id = id; + this.name = name; + this.email = email; + this.x = x; + this.y = y; + this.roomId = "THECODINGMACHINE"; + } +} \ No newline at end of file diff --git a/front/src/Connexion/ConnexionManager.ts b/front/src/Connexion/ConnexionManager.ts new file mode 100644 index 00000000..388805e7 --- /dev/null +++ b/front/src/Connexion/ConnexionManager.ts @@ -0,0 +1,37 @@ +import {ConnectedUser} from "./ConnectedUser"; + +const SocketIo = require('socket.io-client'); +import Axios from "axios"; +import {API_URL} from "../Enum/EnvironmentVariable"; + +class ConnexionManager { + socket : any; + token : string; + email : string; + userId: string; + startedRoom : string; + + + async createConnexion(email : string) : Promise<{connectedUser: ConnectedUser, socket: any}>{ + let res = await Axios.post(`${API_URL}/login`, {email}); + this.token = res.data.token; + this.startedRoom = res.data.roomId; + this.userId = res.data.userId; + let connectedUser = new ConnectedUser(res.data.userId, res.data.name, res.data.email, 0, 0); + + let socket = SocketIo(`${API_URL}`, { + query: { + token: this.token + } + }); + return {connectedUser, socket}; + } + + getAllUsers() { + return Axios.post(`${API_URL}/users`).then(res => { + return res.data.map((user:any) => new ConnectedUser(user.id, user.name, user.email, user.x, user.y)) + }); + } +} + +export const connexionManager = new ConnexionManager(); \ No newline at end of file diff --git a/front/src/Connexion/GameManager.ts b/front/src/Connexion/GameManager.ts new file mode 100644 index 00000000..db2bed3b --- /dev/null +++ b/front/src/Connexion/GameManager.ts @@ -0,0 +1,73 @@ +import {ConnectedUser} from "./ConnectedUser"; +import {BehaviorSubject} from "rxjs"; +import {connexionManager} from "./ConnexionManager"; + +export enum StatusGameManagerEnum { + IN_PROGRESS = 1, + CURRENT_USER_CREATED = 2 +} + +interface Position{ + x: number; + y: number; +} + +class ConnectedUserPositionData{ + userId: string; + position: Position; + + constructor(userId: string, position: Position) { + this.userId = userId; + this.position = position; + } +} + +export interface UserPositionChangeEvent { + userId: string; + x: number; + y: number; + deleted: boolean + added: boolean +} + +export class GameManager { + status: StatusGameManagerEnum; + private connectedUser: ConnectedUser; + private socket: any; + private connectedUserPosition = new BehaviorSubject({x: 0, y: 0}); + public otherUserPositionsChange: BehaviorSubject = new BehaviorSubject([]); + + constructor() { + this.status = StatusGameManagerEnum.IN_PROGRESS; + } + + + async login(email:string) { + let response = await connexionManager.createConnexion(email); + this.connectedUser = response.connectedUser; + this.socket = response.socket; + + this.socket.on('message-error', (message : string) => { + console.error("message-error", message); + }); + + + this.socket.on("user-position", (message: string) => { + let eventList = JSON.parse(message); + this.otherUserPositionsChange.next(eventList); + }); + + this.connectedUserPosition.subscribe(position => { + let data = new ConnectedUserPositionData(this.connectedUser.id, position); + this.socket.emit('user-position', JSON.stringify(data)); + }) + + + } + + updateConnectedUserPosition(x: number, y: number) { + this.connectedUserPosition.next({x, y}); + } +} + +export const gameManager = new GameManager(); \ No newline at end of file diff --git a/front/src/Phaser/Entity/PlayableCaracter.ts b/front/src/Phaser/Entity/PlayableCaracter.ts index 3a18ea73..c15bb345 100644 --- a/front/src/Phaser/Entity/PlayableCaracter.ts +++ b/front/src/Phaser/Entity/PlayableCaracter.ts @@ -18,6 +18,17 @@ export class PlayableCaracter extends Phaser.Physics.Arcade.Sprite { this.setOffset(8, 16); } + 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}), + frameRate: d.frameRate, + repeat: d.repeat + }); + }) + } + move(x: number, y: number){ this.setVelocity(x, y); diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts deleted file mode 100644 index d03a3152..00000000 --- a/front/src/Phaser/Game/GameManager.ts +++ /dev/null @@ -1,77 +0,0 @@ -import {GameSceneInterface, GameScene} from "./GameScene"; -import {ROOM} from "../../Enum/EnvironmentVariable" -import {Connexion, ConnexionInterface, ListMessageUserPositionInterface} from "../../Connexion"; - -export enum StatusGameManagerEnum { - IN_PROGRESS = 1, - CURRENT_USER_CREATED = 2 -} - -export let ConnexionInstance : ConnexionInterface; - -export interface GameManagerInterface { - GameScenes: Array; - status : number; - createCurrentPlayer() : void; - shareUserPosition(ListMessageUserPosition : ListMessageUserPositionInterface): void; -} -export class GameManager implements GameManagerInterface { - GameScenes: Array = []; - status: number; - - constructor() { - this.status = StatusGameManagerEnum.IN_PROGRESS; - ConnexionInstance = new Connexion("test@gmail.com", this); - } - - createGame(){ - return ConnexionInstance.createConnexion().then(() => { - this.configureGame(); - /** TODO add loader in the page **/ - }).catch((err) => { - console.error(err); - throw err; - }); - } - - /** - * permit to config rooms - */ - configureGame() { - ROOM.forEach((roomId) => { - let newGame = new GameScene(roomId, this); - this.GameScenes.push((newGame as GameSceneInterface)); - }); - } - - /** - * Permit to create player in started room - * @param RoomId - * @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; - } - - /** - * Share position in game - * @param ListMessageUserPosition - */ - shareUserPosition(ListMessageUserPosition: ListMessageUserPositionInterface): void { - if (this.status === StatusGameManagerEnum.IN_PROGRESS) { - return; - } - try { - let Game: GameSceneInterface = this.GameScenes.find((Game: GameSceneInterface) => Game.RoomId === ListMessageUserPosition.roomId); - if (!Game) { - return; - } - Game.shareUserPosition(ListMessageUserPosition.listUsersPosition) - } catch (e) { - console.error(e); - } - } -} \ No newline at end of file diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index a08c8fd2..336bd0b4 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1,25 +1,20 @@ -import {GameManagerInterface, StatusGameManagerEnum} from "./GameManager"; -import {MessageUserPositionInterface} from "../../Connexion"; -import {CurrentGamerInterface, GamerInterface, Player} from "../Player/Player"; +import {CurrentGamerInterface, Player} from "../Player/Player"; import {DEBUG_MODE, RESOLUTION, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable"; import Tile = Phaser.Tilemaps.Tile; import {ITiledMap, ITiledTileSet} from "../Map/ITiledMap"; import {cypressAsserter} from "../../Cypress/CypressAsserter"; +import {NonPlayer} from "../NonPlayer/NonPlayer"; +import {ConnectedUser} from "../../Connexion/ConnectedUser"; +import {gameManager, UserPositionChangeEvent} from "../../Connexion/GameManager"; +import {connexionManager} from "../../Connexion/ConnexionManager"; +export const GameSceneName = "GameScene"; export enum Textures { - Rock = 'rock', Player = 'playerModel', Map = 'map' } -export interface GameSceneInterface extends Phaser.Scene { - RoomId : string; - Map: Phaser.Tilemaps.Tilemap; - createCurrentPlayer(UserId : string) : void; - shareUserPosition(UsersPosition : Array): void; -} -export class GameScene extends Phaser.Scene implements GameSceneInterface{ - GameManager : GameManagerInterface; +export class GameScene extends Phaser.Scene { RoomId : string; Terrains : Array; CurrentPlayer: CurrentGamerInterface; @@ -32,12 +27,11 @@ export class GameScene extends Phaser.Scene implements GameSceneInterface{ startY = (window.innerHeight / 2) / RESOLUTION; - constructor(RoomId : string, GameManager : GameManagerInterface) { + constructor() { super({ - key: "GameScene" + key: GameSceneName }); - this.RoomId = RoomId; - this.GameManager = GameManager; + this.RoomId = connexionManager.startedRoom; this.Terrains = []; } @@ -55,7 +49,6 @@ export class GameScene extends Phaser.Scene implements GameSceneInterface{ }) }); this.load.tilemapTiledJSON(Textures.Map, mapUrl); - 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 } @@ -96,7 +89,6 @@ export class GameScene extends Phaser.Scene implements GameSceneInterface{ //add entities this.Objects = new Array(); - this.addSpite(this.physics.add.sprite(200, 400, Textures.Rock, 26)); //init event click this.EventToClickOnTile(); @@ -105,7 +97,9 @@ export class GameScene extends Phaser.Scene implements GameSceneInterface{ this.MapPlayers = this.physics.add.group({ immovable: true }); //notify game manager can to create currentUser in map - this.GameManager.createCurrentPlayer(); + this.createCurrentPlayer(); + + gameManager.otherUserPositionsChange.subscribe((list:any) => this.updateOrCreateMapPlayer(list)) //initialise camera @@ -155,10 +149,11 @@ export class GameScene extends Phaser.Scene implements GameSceneInterface{ }) } - createCurrentPlayer(UserId : string){ + createCurrentPlayer(){ //initialise player this.CurrentPlayer = new Player( - UserId, + connexionManager.userId, + connexionManager.email, this, this.startX, this.startY, @@ -186,61 +181,44 @@ export class GameScene extends Phaser.Scene implements GameSceneInterface{ this.CurrentPlayer.moveUser(); } - /** - * Share position in scene - * @param UsersPosition - */ - shareUserPosition(UsersPosition : Array): void { - this.updateOrCreateMapPlayer(UsersPosition); - } - /** * Create new player and clean the player on the map * @param UsersPosition */ - updateOrCreateMapPlayer(UsersPosition : Array){ - if(!this.CurrentPlayer){ - return; - } + updateOrCreateMapPlayer(userEvents : UserPositionChangeEvent[]){ + //add or create new user - UsersPosition.forEach((userPosition : MessageUserPositionInterface) => { - if(userPosition.userId === this.CurrentPlayer.userId){ - return; - } - let player = this.findPlayerInMap(userPosition.userId); + userEvents.forEach(userEvent => { + let player = this.findPlayerInMap(userEvent.userId); if(!player){ - this.addPlayer(userPosition); + this.addPlayer(userEvent); }else{ - player.updatePosition(userPosition); + if (userEvent.deleted) { + player.destroy(); + } else { + player.updatePosition(userEvent); + } } - }); - - //clean map - this.MapPlayers.getChildren().forEach((player: GamerInterface) => { - if(UsersPosition.find((message : MessageUserPositionInterface) => message.userId === player.userId)){ - return; - } - player.destroy(); - this.MapPlayers.remove(player); - }); + + }) } - private findPlayerInMap(UserId : string) : GamerInterface | null{ + private findPlayerInMap(UserId : string) : any | null{ let player = this.MapPlayers.getChildren().find((player: Player) => UserId === player.userId); if(!player){ return null; } - return (player as GamerInterface); + return player; } /** * Create new player * @param MessageUserPosition */ - addPlayer(MessageUserPosition : MessageUserPositionInterface){ + addPlayer(MessageUserPosition : any){ //initialise player - let player = new Player( + let player = new NonPlayer( MessageUserPosition.userId, this, MessageUserPosition.position.x, @@ -251,8 +229,9 @@ export class GameScene extends Phaser.Scene implements GameSceneInterface{ player.updatePosition(MessageUserPosition); //init colision - this.physics.add.collider(this.CurrentPlayer, player, (CurrentPlayer: CurrentGamerInterface, MapPlayer: GamerInterface) => { - CurrentPlayer.say("Hello, how are you ? "); + this.physics.add.overlap(this.CurrentPlayer, player, (CurrentPlayer: CurrentGamerInterface, MapPlayer: any) => { + CurrentPlayer.say("Salut ça va?"); + MapPlayer.say("Oui et toi?"); }); } } diff --git a/front/src/Phaser/Login/LogincScene.ts b/front/src/Phaser/Login/LogincScene.ts new file mode 100644 index 00000000..8a078877 --- /dev/null +++ b/front/src/Phaser/Login/LogincScene.ts @@ -0,0 +1,52 @@ +import KeyboardKeydownCallback = Phaser.Types.Input.Keyboard.KeyboardKeydownCallback; +import {GameSceneName} from "../Game/GameScene"; +import {connexionManager} from "../../Connexion/ConnexionManager"; + +export const LoginSceneName = "LoginScene"; +enum LoginTextures { + playButton = "play_button", +} + +export class LogincScene extends Phaser.Scene { + private playButton: Phaser.GameObjects.Image; + private textEntry: Phaser.GameObjects.Text; + constructor() { + super({ + key: LoginSceneName + }); + } + + preload() { + this.load.image(LoginTextures.playButton, "resources/objects/play_button.png"); + } + + create() { + this.add.text(10, 10, 'Enter your email:', { font: '32px Courier', fill: '#ffffff' }); + + this.textEntry = this.add.text(10, 50, '', { font: '32px Courier', fill: '#ffff00' }); + let keySpace = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); + let keyBackspace = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.BACKSPACE); + this.input.keyboard.on('keydown', (event: any) => { + if (event.keyCode === 8 && this.textEntry.text.length > 0) { + this.textEntry.text = this.textEntry.text.substr(0, this.textEntry.text.length - 1); + } else if (event.keyCode === 32 || (event.keyCode >= 48 && event.keyCode < 90)) { + this.textEntry.text += event.key; + } + }); + + this.playButton = this.add.image(this.game.renderer.width / 2, this.game.renderer.height / 2, LoginTextures.playButton).setDepth(1); + this.playButton.setInteractive(); + this.playButton.on("pointerup", this.login.bind(this)); + } + + update(time: number, delta: number): void { + + } + + async login() { + let email = this.textEntry.text; + if (!email) return; + await connexionManager.createConnexion("a.poly@thecodingmachine.com"); + this.scene.start(GameSceneName); + } +} \ No newline at end of file diff --git a/front/src/Phaser/NonPlayer/NonPlayer.ts b/front/src/Phaser/NonPlayer/NonPlayer.ts index 63012e46..cdf72d0d 100644 --- a/front/src/Phaser/NonPlayer/NonPlayer.ts +++ b/front/src/Phaser/NonPlayer/NonPlayer.ts @@ -2,27 +2,41 @@ 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"; +import {getPlayerAnimations, playAnimation} from "../Player/Animation"; export class NonPlayer extends PlayableCaracter { isFleeing: boolean = false; - fleeingDirection:any = null //todo create a vector class + fleeingDirection:any = null + private userId: string; + + //todo create a vector class - constructor(scene: Phaser.Scene, x: number, y: number) { + constructor(userId:string, scene: Phaser.Scene, x: number, y: number) { super(scene, x, y, Textures.Player, 1); + this.userId = userId this.setSize(32, 32); //edit the hitbox to better match the caracter model } - updatePosition(MessageUserPosition : MessageUserPositionInterface){ + updatePosition(MessageUserPosition:any){ playAnimation(this, MessageUserPosition.position.direction); this.setX(MessageUserPosition.position.x); this.setY(MessageUserPosition.position.y); } - fleeFrom(player:Player) { + 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}), + frameRate: d.frameRate, + repeat: d.repeat + }); + }) + } + + /*fleeFrom(player:Player) { if (this.isFleeing) return; this.say("Don't touch me!"); this.isFleeing = true; @@ -36,5 +50,5 @@ export class NonPlayer extends PlayableCaracter { 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/Player.ts b/front/src/Phaser/Player/Player.ts index 4cd1a6aa..ed679d13 100644 --- a/front/src/Phaser/Player/Player.ts +++ b/front/src/Phaser/Player/Player.ts @@ -1,9 +1,8 @@ import {getPlayerAnimations, playAnimation, PlayerAnimationNames} from "./Animation"; -import {GameSceneInterface, Textures} from "../Game/GameScene"; -import {ConnexionInstance} from "../Game/GameManager"; -import {MessageUserPositionInterface} from "../../Connexion"; import {ActiveEventList, UserInputEvent, UserInputManager} from "../UserInput/UserInputManager"; import {PlayableCaracter} from "../Entity/PlayableCaracter"; +import {gameManager} from "../../Connexion/GameManager"; +import {Textures} from "../Game/GameScene"; export interface CurrentGamerInterface extends PlayableCaracter{ userId : string; @@ -13,22 +12,16 @@ export interface CurrentGamerInterface extends PlayableCaracter{ say(text : string) : void; } -export interface GamerInterface extends PlayableCaracter{ - userId : string; - PlayerValue : string; - initAnimation() : void; - updatePosition(MessageUserPosition : MessageUserPositionInterface) : void; - say(text : string) : void; -} - -export class Player extends PlayableCaracter implements CurrentGamerInterface, GamerInterface { +export class Player extends PlayableCaracter implements CurrentGamerInterface { userId: string; PlayerValue: string; userInputManager: UserInputManager; + private email: string; constructor( userId: string, - Scene: GameSceneInterface, + email: string, + Scene: Phaser.Scene, x: number, y: number, PlayerValue: string = Textures.Player @@ -40,21 +33,12 @@ export class Player extends PlayableCaracter implements CurrentGamerInterface, G //set data this.userId = userId; + this.email = email; this.PlayerValue = PlayerValue; //the current player model should be push away by other players to prevent conflict this.setImmovable(false); - } - - 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}), - frameRate: d.frameRate, - repeat: d.repeat - }); - }) + this.say("My email is "+this.email) } moveUser(): void { @@ -89,18 +73,7 @@ export class Player extends PlayableCaracter implements CurrentGamerInterface, G direction = PlayerAnimationNames.None; this.stop(); } - this.sharePosition(direction); - } - - private sharePosition(direction: string) { - if (ConnexionInstance) { - ConnexionInstance.sharePosition((this.scene as GameSceneInterface).RoomId, this.x, this.y, direction); - } - } - - updatePosition(MessageUserPosition: MessageUserPositionInterface) { - playAnimation(this, MessageUserPosition.position.direction); - this.setX(MessageUserPosition.position.x); - this.setY(MessageUserPosition.position.y); + + gameManager.updateConnectedUserPosition(this.x, this.y); } } \ No newline at end of file diff --git a/front/src/Phaser/UserInput/UserInputManager.ts b/front/src/Phaser/UserInput/UserInputManager.ts index 6c5b32c2..2677e04a 100644 --- a/front/src/Phaser/UserInput/UserInputManager.ts +++ b/front/src/Phaser/UserInput/UserInputManager.ts @@ -1,5 +1,4 @@ import Map = Phaser.Structs.Map; -import {GameSceneInterface} from "../Game/GameScene"; interface UserInputManagerDatum { keyCode: number; @@ -50,7 +49,7 @@ export class UserInputManager { {keyCode: Phaser.Input.Keyboard.KeyCodes.F, event: UserInputEvent.Shout, keyInstance: null}, ]; - constructor(Scene : GameSceneInterface) { + constructor(Scene : Phaser.Scene) { this.KeysCode.forEach(d => { d.keyInstance = Scene.input.keyboard.addKey(d.keyCode); }); diff --git a/front/src/index.ts b/front/src/index.ts index e5306389..d4f048c6 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -1,17 +1,16 @@ import 'phaser'; import GameConfig = Phaser.Types.Core.GameConfig; -import {GameManager} from "./Phaser/Game/GameManager"; import {DEBUG_MODE, RESOLUTION} from "./Enum/EnvironmentVariable"; import {cypressAsserter} from "./Cypress/CypressAsserter"; - -let gameManager = new GameManager(); +import {LogincScene} from "./Phaser/Login/LogincScene"; +import {GameScene} from "./Phaser/Game/GameScene"; const config: GameConfig = { title: "Office game", width: window.innerWidth / RESOLUTION, height: window.innerHeight / RESOLUTION, parent: "game", - scene: gameManager.GameScenes, + scene: [LogincScene, GameScene], zoom: RESOLUTION, physics: { default: "arcade", @@ -23,10 +22,8 @@ const config: GameConfig = { cypressAsserter.gameStarted(); -gameManager.createGame().then(() => { - let game = new Phaser.Game(config); +let game = new Phaser.Game(config); - window.addEventListener('resize', function (event) { - game.scale.resize(window.innerWidth / RESOLUTION, window.innerHeight / RESOLUTION); - }); -}); +window.addEventListener('resize', function (event) { + game.scale.resize(window.innerWidth / RESOLUTION, window.innerHeight / RESOLUTION); +}); \ No newline at end of file diff --git a/front/tsconfig.json b/front/tsconfig.json index e30c2f81..8fa23917 100644 --- a/front/tsconfig.json +++ b/front/tsconfig.json @@ -7,6 +7,7 @@ "module": "es6", "target": "es5", "jsx": "react", + "downlevelIteration": true, "allowJs": true } } diff --git a/front/yarn.lock b/front/yarn.lock index c9b34f3f..debdc713 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -3278,7 +3278,7 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.5.3: +rxjs@^6.5.3, rxjs@^6.5.5: version "6.5.5" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==