"@types/http-status-codes": "^1.2.0",
"@types/jsonwebtoken": "^8.3.8",
"@types/socket.io": "^2.1.4",
+ "@types/uuidv4": "^5.0.0",
"body-parser": "^1.19.0",
"express": "^4.17.1",
"http-status-codes": "^1.4.0",
"jsonwebtoken": "^8.5.1",
"socket.io": "^2.3.0",
"ts-node-dev": "^1.0.0-pre.44",
- "typescript": "^3.8.3"
+ "typescript": "^3.8.3",
+ "uuidv4": "^6.0.7"
},
"devDependencies": {
"@types/jasmine": "^3.5.10",
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';
export class AuthenticateController{
App : Application;
});
}
//TODO check user email for The Coding Machine game
- let token = Jwt.sign({email: param.email, roomId: ROOM}, SECRET_KEY, {expiresIn: '24h'});
- return res.status(OK).send({token: token, roomId: ROOM});
+ 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
+ });
});
}
}
\ No newline at end of file
}
arrayMap.forEach((value : any) => {
let roomId = value[0];
- let data = value[1];
- this.Io.in(roomId).emit('user-position', JSON.stringify(data));
+ this.Io.in(roomId).emit('user-position', JSON.stringify(arrayMap));
});
this.seTimeOutInProgress = setTimeout(() => {
this.shareUsersPosition();
resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==
+"@types/uuidv4@^5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@types/uuidv4/-/uuidv4-5.0.0.tgz#2c94e67b0c06d5adb28fb7ced1a1b5f0866ecd50"
+ integrity sha512-xUrhYSJnkTq9CP79cU3svoKTLPCIbMMnu9Twf/tMpHATYSHCAAeDNeb2a/29YORhk5p4atHhCTMsIBU/tvdh6A==
+ dependencies:
+ uuidv4 "*"
+
"@typescript-eslint/eslint-plugin@^2.26.0":
version "2.26.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.26.0.tgz#04c96560c8981421e5a9caad8394192363cc423f"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+uuid@7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
+ integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
+
+uuidv4@*, uuidv4@^6.0.7:
+ version "6.0.7"
+ resolved "https://registry.yarnpkg.com/uuidv4/-/uuidv4-6.0.7.tgz#15e920848e1afbbd97b4919bc50f4f2f2278f880"
+ integrity sha512-4mpYRFNqO22EckzxPSJ/+xjn9GgO6SAqEJ33yt23Y+HZZoZOt/6l4U4iIjc86ZfxSN2fSCGGmHNb3kiACFNd1g==
+ dependencies:
+ uuid "7.0.3"
+
v8-compile-cache@^2.0.3:
version "2.1.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"
import Axios from "axios";
import {API_URL} from "./Enum/EnvironmentVariable";
-export interface PointInterface {
- x: number;
- y: number;
- toJson() : object;
-}
-
-export class Message {
+class Message {
userId: string;
roomId: string;
}
}
-export class Point implements PointInterface{
+export interface PointInterface {
+ x: number;
+ y: number;
+ direction : string;
+ toJson() : object;
+}
+
+class Point implements PointInterface{
x: number;
y: number;
direction : string;
}
}
-export class MessageUserPosition extends Message{
+export interface MessageUserPositionInterface {
+ userId: string;
+ roomId: string;
+ position: PointInterface;
+}
+class MessageUserPosition extends Message implements MessageUserPositionInterface{
position: PointInterface;
constructor(userId : string, roomId : string, point : Point) {
}
}
+export interface ListMessageUserPositionInterface {
+ roomId : string;
+ listUsersPosition: Array<MessageUserPosition>;
+}
+class ListMessageUserPosition{
+ roomId : string;
+ listUsersPosition: Array<MessageUserPosition>;
+
+ constructor(roomId : string, data : any) {
+ this.roomId = roomId;
+ this.listUsersPosition = new Array<MessageUserPosition>();
+ 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 class Connexion {
socket : any;
token : string;
email : string;
+ userId: string;
startedRoom : string;
GameManager: GameManagerInterface;
constructor(email : string, GameManager: GameManagerInterface) {
this.email = email;
this.GameManager = GameManager;
- Axios.post(`${API_URL}/login`, {email: email})
+ }
+
+ createConnexion(){
+ 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: {
this.positionOfAllUser();
this.errorMessage();
+
+ return{
+ userId: this.userId,
+ roomId: this.startedRoom
+ }
})
.catch((err) => {
console.error(err);
* @param roomId
*/
joinARoom(roomId : string){
- let messageUserPosition = new MessageUserPosition(this.email, this.startedRoom, new Point(0, 0));
+ let messageUserPosition = new MessageUserPosition(this.userId, this.startedRoom, new Point(0, 0));
this.socket.emit('join-room', messageUserPosition.toString());
}
if(!this.socket){
return;
}
- let messageUserPosition = new MessageUserPosition(this.email, roomId, new Point(x, y, direction));
+ let messageUserPosition = new MessageUserPosition(this.userId, roomId, new Point(x, y, direction));
this.socket.emit('user-position', messageUserPosition.toString());
}
* ...
* ]
**/
- positionOfAllUser(){
- this.socket.on("user-position", (message : string) => {
- let data = JSON.parse(message);
- data.forEach((UserPositions : any) => {
- this.GameManager.sharedUserPosition(UserPositions);
+ positionOfAllUser() {
+ 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);
});
});
}
import {GameSceneInterface, GameScene} from "./GameScene";
import {ROOM} from "../../Enum/EnvironmentVariable"
-import {Connexion} from "../../Connexion";
+import {Connexion, ListMessageUserPositionInterface} from "../../Connexion";
+
+export enum StatusGameManagerEnum {
+ IN_PROGRESS = 1,
+ CURRENT_USER_CREATED = 2
+}
export let ConnexionInstance : Connexion;
export interface GameManagerInterface {
GameScenes: Array<GameSceneInterface>;
-
- sharedUserPosition(UserPositions: any): void;
+ status : number;
+ createCurrentPlayer() : void;
+ shareUserPosition(ListMessageUserPosition : ListMessageUserPositionInterface): void;
}
export class GameManager implements GameManagerInterface {
GameScenes: Array<GameSceneInterface> = [];
+ status: number;
constructor() {
- this.configureGame();
+ this.status = StatusGameManagerEnum.IN_PROGRESS;
ConnexionInstance = new Connexion("test@gmail.com", this);
}
+ createGame(){
+ return ConnexionInstance.createConnexion().then((data: any) => {
+ 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);
+ this.GameScenes.push((newGame as GameSceneInterface));
});
}
- sharedUserPosition(UserPositions: any) {
- let Game: GameSceneInterface = this.GameScenes.find((Game: GameSceneInterface) => Game.RoomId === UserPositions.roomId);
- Game.sharedUserPosition(UserPositions)
+ /**
+ * Permit to create player in started room
+ * @param RoomId
+ * @param UserId
+ */
+ createCurrentPlayer(): void {
+ 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
import {MapManagerInterface, MapManager} from "./MapManager";
-import {GameManagerInterface} from "./GameManager";
+import {GameManagerInterface, StatusGameManagerEnum} from "./GameManager";
+import {MessageUserPositionInterface} from "../../Connexion";
export interface GameSceneInterface extends Phaser.Scene {
RoomId : string;
- sharedUserPosition(data : []): void;
+ createCurrentPlayer(UserId : string) : void;
+ shareUserPosition(UsersPosition : Array<MessageUserPositionInterface>): void;
}
export class GameScene extends Phaser.Scene implements GameSceneInterface{
private MapManager : MapManagerInterface;
+ GameManager : GameManagerInterface;
RoomId : string;
constructor(RoomId : string, GameManager : GameManagerInterface) {
key: "GameScene"
});
this.RoomId = RoomId;
+ this.GameManager = GameManager;
}
//hook preload scene
create(): void {
//create map manager
this.MapManager = new MapManager(this);
+ //notify game manager can to create currentUser in map
+ this.GameManager.createCurrentPlayer();
+ }
+
+ /**
+ * Create current player
+ * @param UserId
+ */
+ createCurrentPlayer(UserId : string): void {
+ this.MapManager.createCurrentPlayer(UserId)
}
//hook update
update(dt: number): void {
+ if(this.GameManager.status === StatusGameManagerEnum.IN_PROGRESS){
+ return;
+ }
this.MapManager.update();
}
- sharedUserPosition(data: []): void {
- //TODO share position of all user
- //console.log("sharedUserPosition", data);
+ /**
+ * Share position in scene
+ * @param UsersPosition
+ */
+ shareUserPosition(UsersPosition : Array<MessageUserPositionInterface>): void {
+ this.MapManager.updateOrCreateMapPlayer(UsersPosition);
}
}
import {CameraManager, CameraManagerInterface} from "./CameraManager";
import {RESOLUTION} from "../../Enum/EnvironmentVariable";
import {Player} from "../Player/Player";
-import {GameScene, GameSceneInterface} from "./GameScene";
+import {GameSceneInterface} from "./GameScene";
+import {MessageUserPositionInterface} from "../../Connexion";
export interface MapManagerInterface {
keyZ: Phaser.Input.Keyboard.Key;
Terrain: Phaser.Tilemaps.Tileset;
Camera: CameraManagerInterface;
Scene: GameSceneInterface;
+
+ createCurrentPlayer(UserId : string): void;
update(): void;
+ updateOrCreateMapPlayer(UsersPosition : Array<MessageUserPositionInterface>): void;
}
export class MapManager implements MapManagerInterface{
keyZ: Phaser.Input.Keyboard.Key;
Terrain : Phaser.Tilemaps.Tileset;
Camera: CameraManagerInterface;
CurrentPlayer: Player;
+ MapPlayers : Player[];
Scene: GameSceneInterface;
Map: Phaser.Tilemaps.Tilemap;
startX = (window.innerWidth / 2) / RESOLUTION;
//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<Player>();
+ }
+
+ createCurrentPlayer(UserId : string){
//initialise player
this.CurrentPlayer = new Player(
+ UserId,
this.Scene,
this.startX,
this.startY,
this.CurrentPlayer.initAnimation();
}
-
initKeyBoard() {
this.keyShift = this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT);
update() : void {
this.CurrentPlayer.move();
}
+
+ /**
+ * Create new player and clean the player on the map
+ * @param UsersPosition
+ */
+ updateOrCreateMapPlayer(UsersPosition : Array<MessageUserPositionInterface>){
+ if(!this.CurrentPlayer){
+ return;
+ }
+
+ //add or create new user
+ UsersPosition.forEach((userPosition : MessageUserPositionInterface) => {
+ if(userPosition.userId === this.CurrentPlayer.userId){
+ return;
+ }
+ let player = this.MapPlayers.find((player: Player) => userPosition.userId === player.userId);
+ if(!player){
+ this.addPlayer(userPosition);
+ }else{
+ player.updatePosition(userPosition);
+ }
+ });
+
+ //clean map
+ let mapPlayers = new Array<Player>();
+ this.MapPlayers.forEach((player: Player) => {
+ if(UsersPosition.find((message : MessageUserPositionInterface) => message.userId === player.userId)){
+ mapPlayers.push(player);
+ return;
+ }
+ player.destroy();
+ });
+ this.MapPlayers = mapPlayers;
+ }
+
+ /**
+ * Create new player
+ * @param MessageUserPosition
+ */
+ addPlayer(MessageUserPosition : MessageUserPositionInterface){
+ //initialise player
+ let player = new Player(
+ MessageUserPosition.userId,
+ this.Scene,
+ MessageUserPosition.position.x,
+ MessageUserPosition.position.y,
+ this.Camera,
+ this
+ );
+ player.initAnimation();
+ this.MapPlayers.push(player);
+ player.updatePosition(MessageUserPosition)
+ }
}
\ No newline at end of file
import {GameSceneInterface} from "../Game/GameScene";
import {ConnexionInstance} from "../Game/GameManager";
import {CameraManagerInterface} from "../Game/CameraManager";
+import {MessageUserPositionInterface} from "../../Connexion";
export class Player extends Phaser.GameObjects.Sprite{
+ userId : string;
MapManager : MapManagerInterface;
PlayerValue : string;
CameraManager: CameraManagerInterface;
constructor(
+ userId: string,
Scene : GameSceneInterface,
x : number,
y : number,
PlayerValue : string = "player"
) {
super(Scene, x, y, PlayerValue);
+ this.userId = userId;
this.PlayerValue = PlayerValue;
Scene.add.existing(this);
this.MapManager = MapManager;
this.CameraManager = CameraManager;
}
-
initAnimation(){
getPlayerAnimations(this.PlayerValue).forEach(d => {
this.scene.anims.create({
}
if(!haveMove){
playAnimation(this, PlayerAnimationNames.None);
- }else{
- this.sharePosition(direction);
+ direction = PlayerAnimationNames.None;
}
-
+ this.sharePosition(direction);
this.CameraManager.moveCamera(this);
}
private CanMoveRight(){
return this.MapManager.Map.widthInPixels > this.x;
}
+
+ updatePosition(MessageUserPosition : MessageUserPositionInterface){
+ playAnimation(this, MessageUserPosition.position.direction);
+ this.setX(MessageUserPosition.position.x);
+ this.setY(MessageUserPosition.position.y);
+ }
}
\ No newline at end of file
zoom: RESOLUTION,
};
-let game = new Phaser.Game(config);
+gameManager.createGame().then(() => {
+ 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);
+ });
});