Merge branch 'develop' of github.com:thecodingmachine/workadventure into outline

# Conflicts:
#	front/src/Phaser/Game/GameScene.ts
#	front/src/Phaser/Player/Player.ts
#	front/src/index.ts
#	front/yarn.lock
This commit is contained in:
David Négrier 2020-08-17 22:51:37 +02:00
commit 6b970adc6c
304 changed files with 2395 additions and 797 deletions

View file

@ -1,6 +1,8 @@
import {PlayerAnimationNames} from "../Player/Animation";
import {SpeechBubble} from "./SpeechBubble";
import BitmapText = Phaser.GameObjects.BitmapText;
import Container = Phaser.GameObjects.Container;
import Sprite = Phaser.GameObjects.Sprite;
export interface PlayerResourceDescriptionInterface {
name: string,
@ -38,57 +40,62 @@ interface AnimationData {
frameEnd: number;
}
export abstract class Character extends Phaser.Physics.Arcade.Sprite {
export abstract class Character extends Container {
private bubble: SpeechBubble|null = null;
private readonly playerName: BitmapText;
public PlayerValue: string;
public PlayerTexture: string;
public sprites: Map<string, Sprite>;
private lastDirection: string = PlayerAnimationNames.WalkDown;
constructor(scene: Phaser.Scene,
x: number,
y: number,
texture: string,
textures: string[],
name: string,
direction: string,
moving: boolean,
frame?: string | number
) {
super(scene, x, y, texture, frame);
super(scene, x, y/*, texture, frame*/);
this.sprites = new Map<string, Sprite>();
for (const texture of textures) {
const sprite = new Sprite(scene, 0, 0, texture, frame);
this.add(sprite);
this.getPlayerAnimations(texture).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
});
})
// Needed, otherwise, animations are not handled correctly.
this.scene.sys.updateList.add(sprite);
this.sprites.set(texture, sprite);
}
this.PlayerValue = name;
this.PlayerTexture = texture;
this.playerName = new BitmapText(scene, x, y - 25, 'main_font', name, 8);
this.playerName.setOrigin(0.5).setCenterAlign().setDepth(99999);
scene.add.existing(this.playerName);
this.scene.sys.updateList.add(this);
this.scene.sys.displayList.add(this);
//this.setScale(2);
scene.add.existing(this);
this.scene.physics.world.enableBody(this);
this.setImmovable(true);
this.setCollideWorldBounds(true);
this.setSize(16, 16); //edit the hitbox to better match the character model
this.setOffset(8, 16);
this.getBody().setImmovable(true);
this.getBody().setCollideWorldBounds(true);
this.setSize(16, 16);
this.getBody().setSize(16, 16); //edit the hitbox to better match the character model
this.getBody().setOffset(0, 8);
this.setDepth(-1);
this.scene.events.on('postupdate', this.postupdate.bind(this));
this.initAnimation();
this.playAnimation(direction, moving);
}
private initAnimation(): void {
this.getPlayerAnimations(this.PlayerTexture).forEach(d => {
this.scene.anims.create({
key: d.key,
frames: this.scene.anims.generateFrameNumbers(d.frameModel, {start: d.frameStart, end: d.frameEnd}),
frameRate: d.frameRate,
repeat: d.repeat
});
})
}
private getPlayerAnimations(name: string): AnimationData[] {
return [{
key: `${name}-${PlayerAnimationNames.WalkDown}`,
@ -122,34 +129,53 @@ export abstract class Character extends Phaser.Physics.Arcade.Sprite {
}
protected playAnimation(direction : string, moving: boolean): void {
if (!this.anims) {
console.error('ANIMS IS NOT DEFINED!!!');
return;
}
if (moving && (!this.anims.currentAnim || this.anims.currentAnim.key !== direction)) {
this.play(this.PlayerTexture+'-'+direction, true);
} else if (!moving) {
/*if (this.anims.currentAnim) {
this.anims.stop();
}*/
this.play(this.PlayerTexture+'-'+direction, true);
this.stop();
for (const [texture, sprite] of this.sprites.entries()) {
if (!sprite.anims) {
console.error('ANIMS IS NOT DEFINED!!!');
return;
}
if (moving && (!sprite.anims.currentAnim || sprite.anims.currentAnim.key !== direction)) {
sprite.play(texture+'-'+direction, true);
} else if (!moving) {
/*if (this.anims.currentAnim) {
this.anims.stop();
}*/
sprite.play(texture+'-'+direction, true);
sprite.anims.stop();
}
}
}
move(x: number, y: number) {
protected getBody(): Phaser.Physics.Arcade.Body {
const body = this.body;
if (!(body instanceof Phaser.Physics.Arcade.Body)) {
throw new Error('Container does not have arcade body');
}
return body;
}
this.setVelocity(x, y);
move(x: number, y: number) {
const body = this.getBody();
body.setVelocity(x, y);
// up or down animations are prioritized over left and right
if (this.body.velocity.y < 0) { //moving up
this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkUp}`, true);
} else if (this.body.velocity.y > 0) { //moving down
this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkDown}`, true);
} else if (this.body.velocity.x > 0) { //moving right
this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkRight}`, true);
} else if (this.body.velocity.x < 0) { //moving left
this.anims.playReverse(`${this.PlayerTexture}-${PlayerAnimationNames.WalkLeft}`, true);
if (body.velocity.y < 0) { //moving up
this.lastDirection = PlayerAnimationNames.WalkUp;
this.playAnimation(PlayerAnimationNames.WalkUp, true);
//this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkUp}`, true);
} else if (body.velocity.y > 0) { //moving down
this.lastDirection = PlayerAnimationNames.WalkDown;
this.playAnimation(PlayerAnimationNames.WalkDown, true);
//this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkDown}`, true);
} else if (body.velocity.x > 0) { //moving right
this.lastDirection = PlayerAnimationNames.WalkRight;
this.playAnimation(PlayerAnimationNames.WalkRight, true);
//this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkRight}`, true);
} else if (body.velocity.x < 0) { //moving left
this.lastDirection = PlayerAnimationNames.WalkLeft;
this.playAnimation(PlayerAnimationNames.WalkLeft, true);
//this.anims.playReverse(`${this.PlayerTexture}-${PlayerAnimationNames.WalkLeft}`, true);
}
if (this.bubble) {
@ -166,8 +192,8 @@ export abstract class Character extends Phaser.Physics.Arcade.Sprite {
}
stop(){
this.setVelocity(0, 0);
this.anims.stop();
this.getBody().setVelocity(0, 0);
this.playAnimation(this.lastDirection, false);
}
say(text: string) {
@ -186,6 +212,9 @@ export abstract class Character extends Phaser.Physics.Arcade.Sprite {
if (this.scene) {
this.scene.events.removeListener('postupdate', this.postupdate.bind(this));
}
for (const sprite of this.sprites.values()) {
this.scene.sys.updateList.remove(sprite);
}
super.destroy(fromScene);
this.playerName.destroy();
}

View file

@ -7,8 +7,6 @@ import {Character} from "../Entity/Character";
*/
export class RemotePlayer extends Character {
userId: string;
previousDirection: string;
wasMoving: boolean;
constructor(
userId: string,
@ -16,11 +14,11 @@ export class RemotePlayer extends Character {
x: number,
y: number,
name: string,
PlayerTexture: string,
PlayerTextures: string[],
direction: string,
moving: boolean
) {
super(Scene, x, y, PlayerTexture, name, direction, moving, 1);
super(Scene, x, y, PlayerTextures, name, direction, moving, 1);
//set data
this.userId = userId;

View file

@ -0,0 +1,312 @@
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
export interface BodyResourceDescriptionInterface {
name: string,
img: string
}
export const COLOR_RESOURCES: Array<BodyResourceDescriptionInterface> = [
{name:"color_1", img: "resources/customisation/character_color/character_color0.png"},
{name:"color_2", img: "resources/customisation/character_color/character_color1.png"},
{name:"color_3", img: "resources/customisation/character_color/character_color2.png"},
{name:"color_4", img: "resources/customisation/character_color/character_color3.png"},
{name:"color_5", img: "resources/customisation/character_color/character_color4.png"},
{name:"color_6", img: "resources/customisation/character_color/character_color5.png"},
{name:"color_7", img: "resources/customisation/character_color/character_color6.png"},
{name:"color_8", img: "resources/customisation/character_color/character_color7.png"},
{name:"color_9", img: "resources/customisation/character_color/character_color8.png"},
{name:"color_10",img: "resources/customisation/character_color/character_color9.png"},
{name:"color_11",img: "resources/customisation/character_color/character_color10.png"},
{name:"color_12",img: "resources/customisation/character_color/character_color11.png"},
{name:"color_13",img: "resources/customisation/character_color/character_color12.png"},
{name:"color_14",img: "resources/customisation/character_color/character_color13.png"},
{name:"color_15",img: "resources/customisation/character_color/character_color14.png"},
{name:"color_16",img: "resources/customisation/character_color/character_color15.png"},
{name:"color_17",img: "resources/customisation/character_color/character_color16.png"},
{name:"color_18",img: "resources/customisation/character_color/character_color17.png"},
{name:"color_19",img: "resources/customisation/character_color/character_color18.png"},
{name:"color_20",img: "resources/customisation/character_color/character_color19.png"},
{name:"color_21",img: "resources/customisation/character_color/character_color20.png"},
{name:"color_22",img: "resources/customisation/character_color/character_color21.png"},
{name:"color_23",img: "resources/customisation/character_color/character_color22.png"},
{name:"color_24",img: "resources/customisation/character_color/character_color23.png"},
{name:"color_25",img: "resources/customisation/character_color/character_color24.png"},
{name:"color_26",img: "resources/customisation/character_color/character_color25.png"},
{name:"color_27",img: "resources/customisation/character_color/character_color26.png"},
{name:"color_28",img: "resources/customisation/character_color/character_color27.png"},
{name:"color_29",img: "resources/customisation/character_color/character_color28.png"},
{name:"color_30",img: "resources/customisation/character_color/character_color29.png"},
{name:"color_31",img: "resources/customisation/character_color/character_color30.png"},
{name:"color_32",img: "resources/customisation/character_color/character_color31.png"},
{name:"color_33",img: "resources/customisation/character_color/character_color32.png"}
];
export const EYES_RESOURCES: Array<BodyResourceDescriptionInterface> = [
{name: "eyes_1", img: "resources/customisation/character_eyes/character_eyes1.png"},
{name: "eyes_2", img: "resources/customisation/character_eyes/character_eyes2.png"},
{name: "eyes_3", img: "resources/customisation/character_eyes/character_eyes3.png"},
{name: "eyes_4", img: "resources/customisation/character_eyes/character_eyes4.png"},
{name: "eyes_5", img: "resources/customisation/character_eyes/character_eyes5.png"},
{name: "eyes_6", img: "resources/customisation/character_eyes/character_eyes6.png"},
{name: "eyes_7", img: "resources/customisation/character_eyes/character_eyes7.png"},
{name: "eyes_8", img: "resources/customisation/character_eyes/character_eyes8.png"},
{name: "eyes_9", img: "resources/customisation/character_eyes/character_eyes9.png"},
{name: "eyes_10", img: "resources/customisation/character_eyes/character_eyes10.png"},
{name: "eyes_11", img: "resources/customisation/character_eyes/character_eyes11.png"},
{name: "eyes_12", img: "resources/customisation/character_eyes/character_eyes12.png"},
{name: "eyes_13", img: "resources/customisation/character_eyes/character_eyes13.png"},
{name: "eyes_14", img: "resources/customisation/character_eyes/character_eyes14.png"},
{name: "eyes_15", img: "resources/customisation/character_eyes/character_eyes15.png"},
{name: "eyes_16", img: "resources/customisation/character_eyes/character_eyes16.png"},
{name: "eyes_17", img: "resources/customisation/character_eyes/character_eyes17.png"},
{name: "eyes_18", img: "resources/customisation/character_eyes/character_eyes18.png"},
{name: "eyes_19", img: "resources/customisation/character_eyes/character_eyes19.png"},
{name: "eyes_20", img: "resources/customisation/character_eyes/character_eyes20.png"},
{name: "eyes_21", img: "resources/customisation/character_eyes/character_eyes21.png"},
{name: "eyes_22", img: "resources/customisation/character_eyes/character_eyes22.png"},
{name: "eyes_23", img: "resources/customisation/character_eyes/character_eyes23.png"},
{name: "eyes_24", img: "resources/customisation/character_eyes/character_eyes24.png"},
{name: "eyes_25", img: "resources/customisation/character_eyes/character_eyes25.png"},
{name: "eyes_26", img: "resources/customisation/character_eyes/character_eyes26.png"},
{name: "eyes_27", img: "resources/customisation/character_eyes/character_eyes27.png"},
{name: "eyes_28", img: "resources/customisation/character_eyes/character_eyes28.png"},
{name: "eyes_29", img: "resources/customisation/character_eyes/character_eyes29.png"},
{name: "eyes_30", img: "resources/customisation/character_eyes/character_eyes30.png"}
]
export const HAIR_RESOURCES: Array<BodyResourceDescriptionInterface> = [
{name:"hair_1", img: "resources/customisation/character_hairs/character_hairs0.png"},
{name:"hair_2", img: "resources/customisation/character_hairs/character_hairs1.png"},
{name:"hair_3", img: "resources/customisation/character_hairs/character_hairs2.png"},
{name:"hair_4", img: "resources/customisation/character_hairs/character_hairs3.png"},
{name:"hair_5", img: "resources/customisation/character_hairs/character_hairs4.png"},
{name:"hair_6", img: "resources/customisation/character_hairs/character_hairs5.png"},
{name:"hair_7", img: "resources/customisation/character_hairs/character_hairs6.png"},
{name:"hair_8", img: "resources/customisation/character_hairs/character_hairs7.png"},
{name:"hair_9", img: "resources/customisation/character_hairs/character_hairs8.png"},
{name:"hair_10",img: "resources/customisation/character_hairs/character_hairs9.png"},
{name:"hair_11",img: "resources/customisation/character_hairs/character_hairs10.png"},
{name:"hair_12",img: "resources/customisation/character_hairs/character_hairs11.png"},
{name:"hair_13",img: "resources/customisation/character_hairs/character_hairs12.png"},
{name:"hair_14",img: "resources/customisation/character_hairs/character_hairs13.png"},
{name:"hair_15",img: "resources/customisation/character_hairs/character_hairs14.png"},
{name:"hair_16",img: "resources/customisation/character_hairs/character_hairs15.png"},
{name:"hair_17",img: "resources/customisation/character_hairs/character_hairs16.png"},
{name:"hair_18",img: "resources/customisation/character_hairs/character_hairs17.png"},
{name:"hair_19",img: "resources/customisation/character_hairs/character_hairs18.png"},
{name:"hair_20",img: "resources/customisation/character_hairs/character_hairs19.png"},
{name:"hair_21",img: "resources/customisation/character_hairs/character_hairs20.png"},
{name:"hair_22",img: "resources/customisation/character_hairs/character_hairs21.png"},
{name:"hair_23",img: "resources/customisation/character_hairs/character_hairs22.png"},
{name:"hair_24",img: "resources/customisation/character_hairs/character_hairs23.png"},
{name:"hair_25",img: "resources/customisation/character_hairs/character_hairs24.png"},
{name:"hair_26",img: "resources/customisation/character_hairs/character_hairs25.png"},
{name:"hair_27",img: "resources/customisation/character_hairs/character_hairs26.png"},
{name:"hair_28",img: "resources/customisation/character_hairs/character_hairs27.png"},
{name:"hair_29",img: "resources/customisation/character_hairs/character_hairs28.png"},
{name:"hair_30",img: "resources/customisation/character_hairs/character_hairs29.png"},
{name:"hair_31",img: "resources/customisation/character_hairs/character_hairs30.png"},
{name:"hair_32",img: "resources/customisation/character_hairs/character_hairs31.png"},
{name:"hair_33",img: "resources/customisation/character_hairs/character_hairs32.png"},
{name:"hair_34",img: "resources/customisation/character_hairs/character_hairs33.png"},
{name:"hair_35",img: "resources/customisation/character_hairs/character_hairs34.png"},
{name:"hair_36",img: "resources/customisation/character_hairs/character_hairs35.png"},
{name:"hair_37",img: "resources/customisation/character_hairs/character_hairs36.png"},
{name:"hair_38",img: "resources/customisation/character_hairs/character_hairs37.png"},
{name:"hair_39",img: "resources/customisation/character_hairs/character_hairs38.png"},
{name:"hair_40",img: "resources/customisation/character_hairs/character_hairs39.png"},
{name:"hair_41",img: "resources/customisation/character_hairs/character_hairs40.png"},
{name:"hair_42",img: "resources/customisation/character_hairs/character_hairs41.png"},
{name:"hair_43",img: "resources/customisation/character_hairs/character_hairs42.png"},
{name:"hair_44",img: "resources/customisation/character_hairs/character_hairs43.png"},
{name:"hair_45",img: "resources/customisation/character_hairs/character_hairs44.png"},
{name:"hair_46",img: "resources/customisation/character_hairs/character_hairs45.png"},
{name:"hair_47",img: "resources/customisation/character_hairs/character_hairs46.png"},
{name:"hair_48",img: "resources/customisation/character_hairs/character_hairs47.png"},
{name:"hair_49",img: "resources/customisation/character_hairs/character_hairs48.png"},
{name:"hair_50",img: "resources/customisation/character_hairs/character_hairs49.png"},
{name:"hair_51",img: "resources/customisation/character_hairs/character_hairs50.png"},
{name:"hair_52",img: "resources/customisation/character_hairs/character_hairs51.png"},
{name:"hair_53",img: "resources/customisation/character_hairs/character_hairs52.png"},
{name:"hair_54",img: "resources/customisation/character_hairs/character_hairs53.png"},
{name:"hair_55",img: "resources/customisation/character_hairs/character_hairs54.png"},
{name:"hair_56",img: "resources/customisation/character_hairs/character_hairs55.png"},
{name:"hair_57",img: "resources/customisation/character_hairs/character_hairs56.png"},
{name:"hair_58",img: "resources/customisation/character_hairs/character_hairs57.png"},
{name:"hair_59",img: "resources/customisation/character_hairs/character_hairs58.png"},
{name:"hair_60",img: "resources/customisation/character_hairs/character_hairs59.png"},
{name:"hair_61",img: "resources/customisation/character_hairs/character_hairs60.png"},
{name:"hair_62",img: "resources/customisation/character_hairs/character_hairs61.png"},
{name:"hair_63",img: "resources/customisation/character_hairs/character_hairs62.png"},
{name:"hair_64",img: "resources/customisation/character_hairs/character_hairs63.png"},
{name:"hair_65",img: "resources/customisation/character_hairs/character_hairs64.png"},
{name:"hair_66",img: "resources/customisation/character_hairs/character_hairs65.png"},
{name:"hair_67",img: "resources/customisation/character_hairs/character_hairs66.png"},
{name:"hair_68",img: "resources/customisation/character_hairs/character_hairs67.png"},
{name:"hair_69",img: "resources/customisation/character_hairs/character_hairs68.png"},
{name:"hair_70",img: "resources/customisation/character_hairs/character_hairs69.png"},
{name:"hair_71",img: "resources/customisation/character_hairs/character_hairs70.png"},
{name:"hair_72",img: "resources/customisation/character_hairs/character_hairs71.png"},
{name:"hair_73",img: "resources/customisation/character_hairs/character_hairs72.png"},
{name:"hair_74",img: "resources/customisation/character_hairs/character_hairs73.png"}
];
export const CLOTHES_RESOURCES: Array<BodyResourceDescriptionInterface> = [
{name:"clothes_1", img: "resources/customisation/character_clothes/character_clothes0.png"},
{name:"clothes_2", img: "resources/customisation/character_clothes/character_clothes1.png"},
{name:"clothes_3", img: "resources/customisation/character_clothes/character_clothes2.png"},
{name:"clothes_4", img: "resources/customisation/character_clothes/character_clothes3.png"},
{name:"clothes_5", img: "resources/customisation/character_clothes/character_clothes4.png"},
{name:"clothes_6", img: "resources/customisation/character_clothes/character_clothes5.png"},
{name:"clothes_7", img: "resources/customisation/character_clothes/character_clothes6.png"},
{name:"clothes_8", img: "resources/customisation/character_clothes/character_clothes7.png"},
{name:"clothes_9", img: "resources/customisation/character_clothes/character_clothes8.png"},
{name:"clothes_10",img: "resources/customisation/character_clothes/character_clothes9.png"},
{name:"clothes_11",img: "resources/customisation/character_clothes/character_clothes10.png"},
{name:"clothes_12",img: "resources/customisation/character_clothes/character_clothes11.png"},
{name:"clothes_13",img: "resources/customisation/character_clothes/character_clothes12.png"},
{name:"clothes_14",img: "resources/customisation/character_clothes/character_clothes13.png"},
{name:"clothes_15",img: "resources/customisation/character_clothes/character_clothes14.png"},
{name:"clothes_16",img: "resources/customisation/character_clothes/character_clothes15.png"},
{name:"clothes_17",img: "resources/customisation/character_clothes/character_clothes16.png"},
{name:"clothes_18",img: "resources/customisation/character_clothes/character_clothes17.png"},
{name:"clothes_19",img: "resources/customisation/character_clothes/character_clothes18.png"},
{name:"clothes_20",img: "resources/customisation/character_clothes/character_clothes19.png"},
{name:"clothes_21",img: "resources/customisation/character_clothes/character_clothes20.png"},
{name:"clothes_22",img: "resources/customisation/character_clothes/character_clothes21.png"},
{name:"clothes_23",img: "resources/customisation/character_clothes/character_clothes22.png"},
{name:"clothes_24",img: "resources/customisation/character_clothes/character_clothes23.png"},
{name:"clothes_25",img: "resources/customisation/character_clothes/character_clothes24.png"},
{name:"clothes_26",img: "resources/customisation/character_clothes/character_clothes25.png"},
{name:"clothes_27",img: "resources/customisation/character_clothes/character_clothes26.png"},
{name:"clothes_28",img: "resources/customisation/character_clothes/character_clothes27.png"},
{name:"clothes_29",img: "resources/customisation/character_clothes/character_clothes28.png"},
{name:"clothes_30",img: "resources/customisation/character_clothes/character_clothes29.png"},
{name:"clothes_31",img: "resources/customisation/character_clothes/character_clothes30.png"},
{name:"clothes_32",img: "resources/customisation/character_clothes/character_clothes31.png"},
{name:"clothes_33",img: "resources/customisation/character_clothes/character_clothes32.png"},
{name:"clothes_34",img: "resources/customisation/character_clothes/character_clothes33.png"},
{name:"clothes_35",img: "resources/customisation/character_clothes/character_clothes34.png"},
{name:"clothes_36",img: "resources/customisation/character_clothes/character_clothes35.png"},
{name:"clothes_37",img: "resources/customisation/character_clothes/character_clothes36.png"},
{name:"clothes_38",img: "resources/customisation/character_clothes/character_clothes37.png"},
{name:"clothes_39",img: "resources/customisation/character_clothes/character_clothes38.png"},
{name:"clothes_40",img: "resources/customisation/character_clothes/character_clothes39.png"},
{name:"clothes_41",img: "resources/customisation/character_clothes/character_clothes40.png"},
{name:"clothes_42",img: "resources/customisation/character_clothes/character_clothes41.png"},
{name:"clothes_43",img: "resources/customisation/character_clothes/character_clothes42.png"},
{name:"clothes_44",img: "resources/customisation/character_clothes/character_clothes43.png"},
{name:"clothes_45",img: "resources/customisation/character_clothes/character_clothes44.png"},
{name:"clothes_46",img: "resources/customisation/character_clothes/character_clothes45.png"},
{name:"clothes_47",img: "resources/customisation/character_clothes/character_clothes46.png"},
{name:"clothes_48",img: "resources/customisation/character_clothes/character_clothes47.png"},
{name:"clothes_49",img: "resources/customisation/character_clothes/character_clothes48.png"},
{name:"clothes_50",img: "resources/customisation/character_clothes/character_clothes49.png"},
{name:"clothes_51",img: "resources/customisation/character_clothes/character_clothes50.png"},
{name:"clothes_52",img: "resources/customisation/character_clothes/character_clothes51.png"},
{name:"clothes_53",img: "resources/customisation/character_clothes/character_clothes52.png"},
{name:"clothes_54",img: "resources/customisation/character_clothes/character_clothes53.png"},
{name:"clothes_55",img: "resources/customisation/character_clothes/character_clothes54.png"},
{name:"clothes_56",img: "resources/customisation/character_clothes/character_clothes55.png"},
{name:"clothes_57",img: "resources/customisation/character_clothes/character_clothes56.png"},
{name:"clothes_58",img: "resources/customisation/character_clothes/character_clothes57.png"},
{name:"clothes_59",img: "resources/customisation/character_clothes/character_clothes58.png"},
{name:"clothes_60",img: "resources/customisation/character_clothes/character_clothes59.png"},
{name:"clothes_61",img: "resources/customisation/character_clothes/character_clothes60.png"},
{name:"clothes_62",img: "resources/customisation/character_clothes/character_clothes61.png"},
{name:"clothes_63",img: "resources/customisation/character_clothes/character_clothes62.png"},
{name:"clothes_64",img: "resources/customisation/character_clothes/character_clothes63.png"},
{name:"clothes_65",img: "resources/customisation/character_clothes/character_clothes64.png"},
{name:"clothes_66",img: "resources/customisation/character_clothes/character_clothes65.png"},
{name:"clothes_67",img: "resources/customisation/character_clothes/character_clothes66.png"},
{name:"clothes_68",img: "resources/customisation/character_clothes/character_clothes67.png"},
{name:"clothes_69",img: "resources/customisation/character_clothes/character_clothes68.png"},
{name:"clothes_70",img: "resources/customisation/character_clothes/character_clothes69.png"},
];
export const HATS_RESOURCES: Array<BodyResourceDescriptionInterface> = [
{name: "hats_1", img: "resources/customisation/character_hats/character_hats1.png"},
{name: "hats_2", img: "resources/customisation/character_hats/character_hats2.png"},
{name: "hats_3", img: "resources/customisation/character_hats/character_hats3.png"},
{name: "hats_4", img: "resources/customisation/character_hats/character_hats4.png"},
{name: "hats_5", img: "resources/customisation/character_hats/character_hats5.png"},
{name: "hats_6", img: "resources/customisation/character_hats/character_hats6.png"},
{name: "hats_7", img: "resources/customisation/character_hats/character_hats7.png"},
{name: "hats_8", img: "resources/customisation/character_hats/character_hats8.png"},
{name: "hats_9", img: "resources/customisation/character_hats/character_hats9.png"},
{name: "hats_10", img: "resources/customisation/character_hats/character_hats10.png"},
{name: "hats_11", img: "resources/customisation/character_hats/character_hats11.png"},
{name: "hats_12", img: "resources/customisation/character_hats/character_hats12.png"},
{name: "hats_13", img: "resources/customisation/character_hats/character_hats13.png"},
{name: "hats_14", img: "resources/customisation/character_hats/character_hats14.png"},
{name: "hats_15", img: "resources/customisation/character_hats/character_hats15.png"},
{name: "hats_16", img: "resources/customisation/character_hats/character_hats16.png"},
{name: "hats_17", img: "resources/customisation/character_hats/character_hats17.png"},
{name: "hats_18", img: "resources/customisation/character_hats/character_hats18.png"},
{name: "hats_19", img: "resources/customisation/character_hats/character_hats19.png"},
{name: "hats_20", img: "resources/customisation/character_hats/character_hats20.png"},
{name: "hats_21", img: "resources/customisation/character_hats/character_hats21.png"},
{name: "hats_22", img: "resources/customisation/character_hats/character_hats22.png"},
{name: "hats_23", img: "resources/customisation/character_hats/character_hats23.png"},
{name: "hats_24", img: "resources/customisation/character_hats/character_hats24.png"},
{name: "hats_25", img: "resources/customisation/character_hats/character_hats25.png"},
{name: "hats_26", img: "resources/customisation/character_hats/character_hats26.png"}
];
export const ACCESSORIES_RESOURCES: Array<BodyResourceDescriptionInterface> = [
{name: "accessory_1", img: "resources/customisation/character_accessories/character_accessories1.png"},
{name: "accessory_2", img: "resources/customisation/character_accessories/character_accessories2.png"},
{name: "accessory_3", img: "resources/customisation/character_accessories/character_accessories3.png"},
{name: "accessory_4", img: "resources/customisation/character_accessories/character_accessories4.png"},
{name: "accessory_5", img: "resources/customisation/character_accessories/character_accessories5.png"},
{name: "accessory_6", img: "resources/customisation/character_accessories/character_accessories6.png"},
{name: "accessory_7", img: "resources/customisation/character_accessories/character_accessories7.png"},
{name: "accessory_8", img: "resources/customisation/character_accessories/character_accessories8.png"},
{name: "accessory_9", img: "resources/customisation/character_accessories/character_accessories9.png"},
{name: "accessory_10", img: "resources/customisation/character_accessories/character_accessories10.png"},
{name: "accessory_11", img: "resources/customisation/character_accessories/character_accessories11.png"},
{name: "accessory_12", img: "resources/customisation/character_accessories/character_accessories12.png"},
{name: "accessory_13", img: "resources/customisation/character_accessories/character_accessories13.png"},
{name: "accessory_14", img: "resources/customisation/character_accessories/character_accessories14.png"},
{name: "accessory_15", img: "resources/customisation/character_accessories/character_accessories15.png"},
{name: "accessory_16", img: "resources/customisation/character_accessories/character_accessories16.png"},
{name: "accessory_17", img: "resources/customisation/character_accessories/character_accessories17.png"},
{name: "accessory_18", img: "resources/customisation/character_accessories/character_accessories18.png"},
{name: "accessory_19", img: "resources/customisation/character_accessories/character_accessories19.png"},
{name: "accessory_20", img: "resources/customisation/character_accessories/character_accessories20.png"},
{name: "accessory_21", img: "resources/customisation/character_accessories/character_accessories21.png"},
{name: "accessory_22", img: "resources/customisation/character_accessories/character_accessories22.png"},
{name: "accessory_23", img: "resources/customisation/character_accessories/character_accessories23.png"},
{name: "accessory_24", img: "resources/customisation/character_accessories/character_accessories24.png"},
{name: "accessory_25", img: "resources/customisation/character_accessories/character_accessories25.png"},
{name: "accessory_26", img: "resources/customisation/character_accessories/character_accessories26.png"},
{name: "accessory_27", img: "resources/customisation/character_accessories/character_accessories27.png"},
{name: "accessory_28", img: "resources/customisation/character_accessories/character_accessories28.png"},
{name: "accessory_29", img: "resources/customisation/character_accessories/character_accessories29.png"},
{name: "accessory_30", img: "resources/customisation/character_accessories/character_accessories30.png"},
{name: "accessory_31", img: "resources/customisation/character_accessories/character_accessories31.png"},
{name: "accessory_32", img: "resources/customisation/character_accessories/character_accessories32.png"}
];
export const LAYERS: Array<Array<BodyResourceDescriptionInterface>> = [
COLOR_RESOURCES,
EYES_RESOURCES,
HAIR_RESOURCES,
CLOTHES_RESOURCES,
HATS_RESOURCES,
ACCESSORIES_RESOURCES
];
export const loadAllLayers = (load: LoaderPlugin) => {
for (let j = 0; j < LAYERS.length; j++) {
for (let i = 0; i < LAYERS[j].length; i++) {
load.spritesheet(
LAYERS[j][i].name,
LAYERS[j][i].img,
{frameWidth: 32, frameHeight: 32}
)
}
}
}

View file

@ -3,6 +3,6 @@ import {PointInterface} from "../../Connection";
export interface AddPlayerInterface {
userId: string;
name: string;
character: string;
characterLayers: string[];
position: PointInterface;
}

View file

@ -13,12 +13,19 @@ export interface HasMovedEvent {
}
export class GameManager {
private playerName: string;
private characterUserSelected: string;
private playerName!: string;
private characterLayers!: string[];
public storePlayerDetails(name: string, characterUserSelected : string): void {
public setPlayerName(name: string): void {
this.playerName = name;
this.characterUserSelected = characterUserSelected;
}
public setCharacterUserSelected(characterUserSelected : string): void {
this.characterLayers = [characterUserSelected];
}
public setCharacterLayers(layers: string[]) {
this.characterLayers = layers;
}
loadStartMap() : Promise<StartMapInterface> {
@ -35,8 +42,8 @@ export class GameManager {
return this.playerName;
}
getCharacterSelected(): string {
return this.characterUserSelected;
getCharacterSelected(): string[] {
return this.characterLayers;
}
loadMap(mapUrl: string, scene: Phaser.Scenes.ScenePlugin, instance: string): string {

View file

@ -1,12 +1,16 @@
import {GameManager, gameManager, HasMovedEvent} from "./GameManager";
import {
Connection,
GroupCreatedUpdatedMessageInterface, MessageUserJoined,
GroupCreatedUpdatedMessageInterface,
MessageUserJoined,
MessageUserMovedInterface,
MessageUserPositionInterface, PointInterface, PositionInterface, RoomJoinedMessageInterface
MessageUserPositionInterface,
PointInterface,
PositionInterface,
RoomJoinedMessageInterface
} from "../../Connection";
import {CurrentGamerInterface, hasMovedEventName, Player} from "../Player/Player";
import { DEBUG_MODE, ZOOM_LEVEL, POSITION_DELAY } from "../../Enum/EnvironmentVariable";
import {DEBUG_MODE, POSITION_DELAY, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable";
import {
ITiledMap,
ITiledMapLayer,
@ -14,18 +18,20 @@ import {
ITiledTileSet
} from "../Map/ITiledMap";
import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character";
import Texture = Phaser.Textures.Texture;
import Sprite = Phaser.GameObjects.Sprite;
import CanvasTexture = Phaser.Textures.CanvasTexture;
import {AddPlayerInterface} from "./AddPlayerInterface";
import {PlayerAnimationNames} from "../Player/Animation";
import {PlayerMovement} from "./PlayerMovement";
import {PlayersPositionInterpolator} from "./PlayersPositionInterpolator";
import {RemotePlayer} from "../Entity/RemotePlayer";
import GameObject = Phaser.GameObjects.GameObject;
import { Queue } from 'queue-typescript';
import {SimplePeer} from "../../WebRtc/SimplePeer";
import {Queue} from 'queue-typescript';
import {SimplePeer, UserSimplePeer} from "../../WebRtc/SimplePeer";
import {ReconnectingSceneName} from "../Reconnecting/ReconnectingScene";
import {loadAllLayers} from "../Entity/body_character";
import {layoutManager, LayoutMode} from "../../WebRtc/LayoutManager";
import Texture = Phaser.Textures.Texture;
import Sprite = Phaser.GameObjects.Sprite;
import CanvasTexture = Phaser.Textures.CanvasTexture;
import GameObject = Phaser.GameObjects.GameObject;
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
import {FourOFourSceneName} from "../Reconnecting/FourOFourScene";
import {ItemFactoryInterface} from "../Items/ItemFactoryInterface";
@ -75,36 +81,36 @@ interface DeleteGroupEventInterface {
export class GameScene extends Phaser.Scene {
GameManager : GameManager;
Terrains : Array<Phaser.Tilemaps.Tileset>;
CurrentPlayer: CurrentGamerInterface;
MapPlayers : Phaser.Physics.Arcade.Group;
CurrentPlayer!: CurrentGamerInterface;
MapPlayers!: Phaser.Physics.Arcade.Group;
MapPlayersByKey : Map<string, RemotePlayer> = new Map<string, RemotePlayer>();
Map: Phaser.Tilemaps.Tilemap;
Layers : Array<Phaser.Tilemaps.StaticTilemapLayer>;
Objects : Array<Phaser.Physics.Arcade.Sprite>;
mapFile: ITiledMap;
Map!: Phaser.Tilemaps.Tilemap;
Layers!: Array<Phaser.Tilemaps.StaticTilemapLayer>;
Objects!: Array<Phaser.Physics.Arcade.Sprite>;
mapFile!: ITiledMap;
groups: Map<string, Sprite>;
startX: number;
startY: number;
circleTexture: CanvasTexture;
startX!: number;
startY!: number;
circleTexture!: CanvasTexture;
pendingEvents: Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface> = new Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface>();
private initPosition: PositionInterface|null = null;
private playersPositionInterpolator = new PlayersPositionInterpolator();
private connection: Connection;
private simplePeer : SimplePeer;
private connectionPromise: Promise<Connection>
private connection!: Connection;
private simplePeer!: SimplePeer;
private connectionPromise!: Promise<Connection>
private connectionAnswerPromise: Promise<RoomJoinedMessageInterface>;
private connectionAnswerPromiseResolve: (value?: RoomJoinedMessageInterface | PromiseLike<RoomJoinedMessageInterface>) => void;
private connectionAnswerPromiseResolve!: (value?: RoomJoinedMessageInterface | PromiseLike<RoomJoinedMessageInterface>) => void;
// A promise that will resolve when the "create" method is called (signaling loading is ended)
private createPromise: Promise<void>;
private createPromiseResolve: (value?: void | PromiseLike<void>) => void;
private createPromiseResolve!: (value?: void | PromiseLike<void>) => void;
MapKey: string;
MapUrlFile: string;
RoomId: string;
instance: string;
currentTick: number;
lastSentTick: number; // The last tick at which a position was sent.
currentTick!: number;
lastSentTick!: number; // The last tick at which a position was sent.
lastMoveEventSent: HasMovedEvent = {
direction: '',
moving: false,
@ -114,10 +120,13 @@ export class GameScene extends Phaser.Scene {
private PositionNextScene: Array<Array<{ key: string, hash: string }>> = new Array<Array<{ key: string, hash: string }>>();
private startLayerName: string|undefined;
private presentationModeSprite!: Sprite;
private chatModeSprite!: Sprite;
private repositionCallback!: (this: Window, ev: UIEvent) => void;
private actionableItems: Map<number, ActionableItem> = new Map<number, ActionableItem>();
// The item that can be selected by pressing the space key.
private outlinedItem: ActionableItem|null = null;
private userInputManager: UserInputManager;
private userInputManager!: UserInputManager;
static createFromUrl(mapUrlFile: string, instance: string, key: string|null = null): GameScene {
const mapKey = GameScene.getMapKeyByUrl(mapUrlFile);
@ -177,6 +186,14 @@ export class GameScene extends Phaser.Scene {
);
});
this.load.spritesheet(
'layout_modes',
'resources/objects/layout_modes.png',
{frameWidth: 32, frameHeight: 32}
);
loadAllLayers(this.load);
this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
this.connectionPromise = Connection.createConnection(gameManager.getPlayerName(), gameManager.getCharacterSelected()).then((connection : Connection) => {
@ -185,7 +202,7 @@ export class GameScene extends Phaser.Scene {
connection.onUserJoins((message: MessageUserJoined) => {
const userMessage: AddPlayerInterface = {
userId: message.userId,
character: message.character,
characterLayers: message.characterLayers,
name: message.name,
position: message.position
}
@ -230,6 +247,7 @@ export class GameScene extends Phaser.Scene {
this.scene.stop(this.scene.key);
this.scene.remove(this.scene.key);
window.removeEventListener('resize', this.repositionCallback);
})
connection.onActionableEvent((message => {
@ -243,6 +261,19 @@ export class GameScene extends Phaser.Scene {
// When connection is performed, let's connect SimplePeer
this.simplePeer = new SimplePeer(this.connection);
const self = this;
this.simplePeer.registerPeerConnectionListener({
onConnect(user: UserSimplePeer) {
self.presentationModeSprite.setVisible(true);
self.chatModeSprite.setVisible(true);
},
onDisconnect(userId: string) {
if (self.simplePeer.getNbConnections() === 0) {
self.presentationModeSprite.setVisible(false);
self.chatModeSprite.setVisible(false);
}
}
})
this.scene.wake();
this.scene.sleep(ReconnectingSceneName);
@ -484,6 +515,41 @@ export class GameScene extends Phaser.Scene {
this.input.keyboard.on('keyup-SPACE', () => {
this.outlinedItem?.activate();
});
this.presentationModeSprite = this.add.sprite(2, this.game.renderer.height - 2, 'layout_modes', 0);
this.presentationModeSprite.setScrollFactor(0, 0);
this.presentationModeSprite.setOrigin(0, 1);
this.presentationModeSprite.setInteractive();
this.presentationModeSprite.setVisible(false);
this.presentationModeSprite.on('pointerup', this.switchLayoutMode.bind(this));
this.chatModeSprite = this.add.sprite(36, this.game.renderer.height - 2, 'layout_modes', 3);
this.chatModeSprite.setScrollFactor(0, 0);
this.chatModeSprite.setOrigin(0, 1);
this.chatModeSprite.setInteractive();
this.chatModeSprite.setVisible(false);
this.chatModeSprite.on('pointerup', this.switchLayoutMode.bind(this));
// FIXME: change this to use the UserInputManager class for input
this.input.keyboard.on('keyup-' + 'M', () => {
this.switchLayoutMode();
});
this.repositionCallback = this.reposition.bind(this);
window.addEventListener('resize', this.repositionCallback);
this.reposition();
}
private switchLayoutMode(): void {
const mode = layoutManager.getLayoutMode();
if (mode === LayoutMode.Presentation) {
layoutManager.switchLayoutMode(LayoutMode.VideoChat);
this.presentationModeSprite.setFrame(1);
this.chatModeSprite.setFrame(2);
} else {
layoutManager.switchLayoutMode(LayoutMode.Presentation);
this.presentationModeSprite.setFrame(0);
this.chatModeSprite.setFrame(3);
}
}
private getExitSceneUrl(layer: ITiledMapLayer): string|undefined {
@ -791,6 +857,7 @@ export class GameScene extends Phaser.Scene {
this.simplePeer.unregister();
this.scene.stop();
this.scene.remove(this.scene.key);
window.removeEventListener('resize', this.repositionCallback);
this.scene.start(nextSceneKey.key, {
startLayerName: nextSceneKey.hash
});
@ -870,7 +937,7 @@ export class GameScene extends Phaser.Scene {
addPlayerData.position.x,
addPlayerData.position.y,
addPlayerData.name,
addPlayerData.character,
addPlayerData.characterLayers,
addPlayerData.position.direction,
addPlayerData.position.moving
);
@ -987,4 +1054,9 @@ export class GameScene extends Phaser.Scene {
emitActionableEvent(itemId: number, eventName: string, state: unknown, parameters: unknown) {
this.connection.emitActionableEvent(itemId, eventName, state, parameters);
}
private reposition(): void {
this.presentationModeSprite.setY(this.game.renderer.height - 2);
this.chatModeSprite.setY(this.game.renderer.height - 2);
}
}

View file

@ -0,0 +1,275 @@
import {EnableCameraSceneName} from "./EnableCameraScene";
import {TextField} from "../Components/TextField";
import Image = Phaser.GameObjects.Image;
import Rectangle = Phaser.GameObjects.Rectangle;
import {LAYERS, loadAllLayers} from "../Entity/body_character";
import Sprite = Phaser.GameObjects.Sprite;
import Container = Phaser.GameObjects.Container;
import {gameManager} from "../Game/GameManager";
export const CustomizeSceneName = "CustomizeScene";
enum CustomizeTextures{
icon = "icon",
arrowRight = "arrow_right",
mainFont = "main_font",
arrowUp = "arrow_up",
}
export class CustomizeScene extends Phaser.Scene {
private textField!: TextField;
private enterField!: TextField;
private arrowRight!: Image;
private arrowLeft!: Image;
private arrowDown!: Image;
private arrowUp!: Image;
private Rectangle!: Rectangle;
private logo!: Image;
private selectedLayers: Array<number> = [0];
private containersRow: Array<Array<Container>> = new Array<Array<Container>>();
private activeRow = 0;
private repositionCallback!: (this: Window, ev: UIEvent) => void;
constructor() {
super({
key: CustomizeSceneName
});
}
preload() {
this.load.image(CustomizeTextures.arrowRight, "resources/objects/arrow_right.png");
this.load.image(CustomizeTextures.icon, "resources/logos/tcm_full.png");
this.load.image(CustomizeTextures.arrowUp, "resources/objects/arrow_up.png");
this.load.bitmapFont(CustomizeTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
//load all the png files
loadAllLayers(this.load);
}
create() {
this.textField = new TextField(this, this.game.renderer.width / 2, 30, 'Customize your own Avatar!');
this.textField.setOrigin(0.5).setCenterAlign();
this.textField.setVisible(true);
this.enterField = new TextField(this, this.game.renderer.width / 2, 500, 'you can start the game by pressing SPACE..');
this.enterField.setOrigin(0.5).setCenterAlign();
this.enterField.setVisible(true);
this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, CustomizeTextures.icon);
this.add.existing(this.logo);
this.arrowRight = new Image(this, this.game.renderer.width*0.9, this.game.renderer.height/2, CustomizeTextures.arrowRight);
this.add.existing(this.arrowRight);
this.arrowLeft = new Image(this, this.game.renderer.width/9, this.game.renderer.height/2, CustomizeTextures.arrowRight);
this.arrowLeft.flipX = true;
this.add.existing(this.arrowLeft);
this.Rectangle = this.add.rectangle(this.cameras.main.worldView.x + this.cameras.main.width / 2, this.cameras.main.worldView.y + this.cameras.main.height / 2, 32, 33)
this.Rectangle.setStrokeStyle(2, 0xFFFFFF);
this.add.existing(this.Rectangle);
this.arrowDown = new Image(this, this.game.renderer.width - 30, 100, CustomizeTextures.arrowUp);
this.arrowDown.flipY = true;
this.add.existing(this.arrowDown);
this.arrowUp = new Image(this, this.game.renderer.width - 30, 60, CustomizeTextures.arrowUp);
this.add.existing(this.arrowUp);
this.createCustomizeLayer(0, 0, 0);
this.createCustomizeLayer(0, 0, 1);
this.createCustomizeLayer(0, 0, 2);
this.createCustomizeLayer(0, 0, 3);
this.createCustomizeLayer(0, 0, 4);
this.createCustomizeLayer(0, 0, 5);
this.moveLayers();
this.input.keyboard.on('keyup-ENTER', () => {
const layers: string[] = [];
let i = 0;
for (const layerItem of this.selectedLayers) {
if (layerItem !== undefined) {
layers.push(LAYERS[i][layerItem].name);
}
i++;
}
gameManager.setCharacterLayers(layers);
return this.scene.start(EnableCameraSceneName);
});
this.input.keyboard.on('keydown-RIGHT', () => {
if (this.selectedLayers[this.activeRow] === undefined) {
this.selectedLayers[this.activeRow] = 0;
}
if (this.selectedLayers[this.activeRow] < LAYERS[this.activeRow].length - 1) {
this.selectedLayers[this.activeRow]++;
this.moveLayers();
this.updateSelectedLayer();
}
});
this.input.keyboard.on('keydown-LEFT', () => {
if (this.selectedLayers[this.activeRow] > 0) {
if (this.selectedLayers[this.activeRow] === 0) {
delete this.selectedLayers[this.activeRow];
} else {
this.selectedLayers[this.activeRow]--;
}
this.moveLayers();
this.updateSelectedLayer();
}
});
this.input.keyboard.on('keydown-DOWN', () => {
if (this.activeRow < LAYERS.length - 1) {
this.activeRow++;
this.moveLayers();
}
});
this.input.keyboard.on('keydown-UP', () => {
if (this.activeRow > 0) {
this.activeRow--;
this.moveLayers();
}
});
this.repositionCallback = this.reposition.bind(this);
window.addEventListener('resize', this.repositionCallback);
}
update(time: number, delta: number): void {
super.update(time, delta);
this.enterField.setVisible(!!(Math.floor(time / 500) % 2));
}
/**
* @param x, the layer's vertical position
* @param y, the layer's horizontal position
* @param layerNumber, index of the LAYERS array
* create the layer and display it on the scene
*/
private createCustomizeLayer(x: number, y: number, layerNumber: number): void {
this.containersRow[layerNumber] = new Array<Container>();
let alpha = 0;
let layerPosX = 0;
for (let i = 0; i < LAYERS[layerNumber].length; i++) {
const container = this.generateCharacter(300 + x + layerPosX, y, layerNumber, i);
this.containersRow[layerNumber][i] = container;
this.add.existing(container);
layerPosX += 30;
alpha += 0.1;
}
}
/**
* Generates a character from the current selected items BUT replaces
* one layer item with an item we pass in parameter.
*
* Current selected items are fetched from this.selectedLayers
*
* @param x,
* @param y,
* @param layerNumber, The selected layer number (0 for body...)
* @param selectedItem, The number of the item select (0 for black body...)
*/
private generateCharacter(x: number, y: number, layerNumber: number, selectedItem: number) {
return new Container(this, x, y,this.getContainerChildren(layerNumber,selectedItem));
}
private getContainerChildren(layerNumber: number, selectedItem: number): Array<Sprite> {
const children: Array<Sprite> = new Array<Sprite>();
for (let j = 0; j <= layerNumber; j++) {
if (j === layerNumber) {
children.push(this.generateLayers(0, 0, LAYERS[j][selectedItem].name));
} else {
const layer = this.selectedLayers[j];
if (layer === undefined) {
continue;
}
children.push(this.generateLayers(0, 0, LAYERS[j][layer].name));
}
}
return children;
}
/**
* Move the layer left, right, up and down and update the selected layer
*/
private moveLayers(): void {
const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
const screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 2;
const screenWidth = this.game.renderer.width;
const screenHeight = this.game.renderer.height;
for (let i = 0; i < this.containersRow.length; i++) {
for (let j = 0; j < this.containersRow[i].length; j++) {
let selectedX = this.selectedLayers[i];
if (selectedX === undefined) {
selectedX = 0;
}
this.containersRow[i][j].x = screenCenterX + (j - selectedX) * 40;
this.containersRow[i][j].y = screenCenterY + (i - this.activeRow) * 40;
const alpha1 = Math.abs(selectedX - j)*47*2/screenWidth;
const alpha2 = Math.abs(this.activeRow - i)*49*2/screenHeight;
this.containersRow[i][j].setAlpha((1 -alpha1)*(1 - alpha2));
}
}
}
/**
* @param x, the sprite's vertical position
* @param y, the sprites's horizontal position
* @param name, the sprite's name
* @return a new sprite
*/
private generateLayers(x: number, y: number, name: string): Sprite {
return new Sprite(this, x, y, name);
}
private updateSelectedLayer() {
for(let i = 0; i < this.containersRow.length; i++){
for(let j = 0; j < this.containersRow[i].length; j++){
const children = this.getContainerChildren(i, j);
this.containersRow[i][j].removeAll(true);
this.containersRow[i][j].add(children);
}
}
}
private reposition() {
this.moveLayers();
this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 2;
this.textField.x = this.game.renderer.width/2;
this.logo.x = this.game.renderer.width - 30;
this.logo.y = this.game.renderer.height - 20;
this.arrowUp.x = this.game.renderer.width - 30;
this.arrowUp.y = 60;
this.arrowDown.x = this.game.renderer.width - 30;
this.arrowDown.y = 100;
this.arrowLeft.x = this.game.renderer.width/9;
this.arrowLeft.y = this.game.renderer.height/2;
this.arrowRight.x = this.game.renderer.width*0.9;
this.arrowRight.y = this.game.renderer.height/2;
}
}

View file

@ -21,22 +21,22 @@ enum LoginTextures {
}
export class EnableCameraScene extends Phaser.Scene {
private textField: TextField;
private pressReturnField: TextField;
private cameraNameField: TextField;
private logo: Image;
private arrowLeft: Image;
private arrowRight: Image;
private arrowDown: Image;
private arrowUp: Image;
private textField!: TextField;
private pressReturnField!: TextField;
private cameraNameField!: TextField;
private logo!: Image;
private arrowLeft!: Image;
private arrowRight!: Image;
private arrowDown!: Image;
private arrowUp!: Image;
private microphonesList: MediaDeviceInfo[] = new Array<MediaDeviceInfo>();
private camerasList: MediaDeviceInfo[] = new Array<MediaDeviceInfo>();
private cameraSelected: number = 0;
private microphoneSelected: number = 0;
private soundMeter: SoundMeter;
private soundMeterSprite: SoundMeterSprite;
private microphoneNameField: TextField;
private repositionCallback: (this: Window, ev: UIEvent) => void;
private soundMeterSprite!: SoundMeterSprite;
private microphoneNameField!: TextField;
private repositionCallback!: (this: Window, ev: UIEvent) => void;
constructor() {
super({

View file

@ -6,7 +6,7 @@ import Image = Phaser.GameObjects.Image;
import Rectangle = Phaser.GameObjects.Rectangle;
import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character";
import {cypressAsserter} from "../../Cypress/CypressAsserter";
import {SelectCharacterSceneInitDataInterface, SelectCharacterSceneName} from "./SelectCharacterScene";
import {SelectCharacterSceneName} from "./SelectCharacterScene";
//todo: put this constants in a dedicated file
export const LoginSceneName = "LoginScene";
@ -89,6 +89,8 @@ export class LoginScene extends Phaser.Scene {
}
private login(name: string): void {
this.scene.start(SelectCharacterSceneName, { name } as SelectCharacterSceneInitDataInterface);
gameManager.setPlayerName(name);
this.scene.start(SelectCharacterSceneName);
}
}

View file

@ -1,36 +1,36 @@
import {gameManager} from "../Game/GameManager";
import {TextField} from "../Components/TextField";
import {ClickButton} from "../Components/ClickButton";
import Image = Phaser.GameObjects.Image;
import Rectangle = Phaser.GameObjects.Rectangle;
import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character";
import {GameSceneInitInterface} from "../Game/GameScene";
import {StartMapInterface} from "../../Connection";
import {EnableCameraSceneName} from "./EnableCameraScene";
import {CustomizeSceneName} from "./CustomizeScene";
//todo: put this constants in a dedicated file
export const SelectCharacterSceneName = "SelectCharacterScene";
enum LoginTextures {
playButton = "play_button",
icon = "icon",
mainFont = "main_font"
}
export interface SelectCharacterSceneInitDataInterface {
name: string
mainFont = "main_font",
customizeButton = "customize_button",
customizeButtonSelected = "customize_button_selected"
}
export class SelectCharacterScene extends Phaser.Scene {
private readonly nbCharactersPerRow = 4;
private textField: TextField;
private pressReturnField: TextField;
private logo: Image;
private loginName: string;
private textField!: TextField;
private pressReturnField!: TextField;
private logo!: Image;
private customizeButton!: Image;
private customizeButtonSelected!: Image;
private selectedRectangle: Rectangle;
private selectedRectangle!: Rectangle;
private selectedRectangleXPos = 0; // Number of the character selected in the rows
private selectedRectangleYPos = 0; // Number of the character selected in the columns
private selectedPlayer: Phaser.Physics.Arcade.Sprite;
private selectedPlayer!: Phaser.Physics.Arcade.Sprite|null; // null if we are selecting the "customize" option
private players: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
constructor() {
@ -39,10 +39,6 @@ export class SelectCharacterScene extends Phaser.Scene {
});
}
init({ name }: SelectCharacterSceneInitDataInterface) {
this.loginName = name;
}
preload() {
this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
@ -56,13 +52,15 @@ export class SelectCharacterScene extends Phaser.Scene {
{frameWidth: 32, frameHeight: 32}
);
});
this.load.image(LoginTextures.customizeButton, 'resources/objects/customize.png');
this.load.image(LoginTextures.customizeButtonSelected, 'resources/objects/customize_selected.png');
}
create() {
this.textField = new TextField(this, this.game.renderer.width / 2, 50, 'Select your character');
this.textField.setOrigin(0.5).setCenterAlign()
this.pressReturnField = new TextField(this, this.game.renderer.width / 2, 230, 'Press enter to start');
this.pressReturnField = new TextField(this, this.game.renderer.width / 2, 256, 'Press enter to start');
this.pressReturnField.setOrigin(0.5).setCenterAlign()
const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
@ -73,7 +71,7 @@ export class SelectCharacterScene extends Phaser.Scene {
this.add.existing(this.logo);
this.input.keyboard.on('keyup-ENTER', () => {
return this.login(this.loginName);
return this.nextScene();
});
this.input.keyboard.on('keydown-RIGHT', () => {
@ -89,7 +87,7 @@ export class SelectCharacterScene extends Phaser.Scene {
this.updateSelectedPlayer();
});
this.input.keyboard.on('keydown-DOWN', () => {
if (this.selectedRectangleYPos < Math.ceil(PLAYER_RESOURCES.length / this.nbCharactersPerRow) - 1) {
if (this.selectedRectangleYPos < Math.ceil(PLAYER_RESOURCES.length / this.nbCharactersPerRow)) {
this.selectedRectangleYPos++;
}
this.updateSelectedPlayer();
@ -117,10 +115,15 @@ export class SelectCharacterScene extends Phaser.Scene {
this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2));
}
private login(name: string): void {
gameManager.storePlayerDetails(name, this.selectedPlayer.texture.key);
private nextScene(): void {
this.scene.start(EnableCameraSceneName);
if (this.selectedPlayer !== null) {
gameManager.setCharacterUserSelected(this.selectedPlayer.texture.key);
this.scene.start(EnableCameraSceneName);
} else {
this.scene.start(CustomizeSceneName);
}
// Do we have a start URL in the address bar? If so, let's redirect to this address
/*const instanceAndMapUrl = this.findMapUrl();
@ -188,6 +191,20 @@ export class SelectCharacterScene extends Phaser.Scene {
});
this.players.push(player);
}
this.customizeButton = new Image(this, this.game.renderer.width / 2, 90 + 32 * 4 + 6, LoginTextures.customizeButton);
this.customizeButton.setOrigin(0.5, 0.5);
this.add.existing(this.customizeButton);
this.customizeButtonSelected = new Image(this, this.game.renderer.width / 2, 90 + 32 * 4 + 6, LoginTextures.customizeButtonSelected);
this.customizeButtonSelected.setOrigin(0.5, 0.5);
this.customizeButtonSelected.setVisible(false);
this.add.existing(this.customizeButtonSelected);
this.customizeButton.setInteractive().on("pointerdown", () => {
this.selectedRectangleYPos = Math.ceil(PLAYER_RESOURCES.length / this.nbCharactersPerRow);
this.updateSelectedPlayer();
});
this.selectedPlayer = this.players[0];
this.selectedPlayer.play(PLAYER_RESOURCES[0].name);
}
@ -203,10 +220,22 @@ export class SelectCharacterScene extends Phaser.Scene {
}
private updateSelectedPlayer(): void {
this.selectedPlayer.anims.pause();
this.selectedPlayer?.anims.pause();
// If we selected the customize button
if (this.selectedRectangleYPos === Math.ceil(PLAYER_RESOURCES.length / this.nbCharactersPerRow)) {
this.selectedPlayer = null;
this.selectedRectangle.setVisible(false);
this.customizeButtonSelected.setVisible(true);
this.customizeButton.setVisible(false);
return;
}
this.customizeButtonSelected.setVisible(false);
this.customizeButton.setVisible(true);
const [x, y] = this.getCharacterPosition(this.selectedRectangleXPos, this.selectedRectangleYPos);
this.selectedRectangle.setVisible(true);
this.selectedRectangle.setX(x);
this.selectedRectangle.setY(y);
this.selectedRectangle.setSize(32, 32);
const playerNumber = this.selectedRectangleXPos + this.selectedRectangleYPos * this.nbCharactersPerRow;
const player = this.players[playerNumber];
player.play(PLAYER_RESOURCES[playerNumber].name);

View file

@ -13,23 +13,23 @@ export interface CurrentGamerInterface extends Character{
}
export class Player extends Character implements CurrentGamerInterface {
private previousDirection: string;
private wasMoving: boolean;
private previousDirection: string = PlayerAnimationNames.WalkDown;
private wasMoving: boolean = false;
constructor(
Scene: GameScene,
x: number,
y: number,
name: string,
PlayerTexture: string,
PlayerTextures: string[],
direction: string,
moving: boolean,
private userInputManager: UserInputManager
) {
super(Scene, x, y, PlayerTexture, name, direction, moving, 1);
super(Scene, x, y, PlayerTextures, name, direction, moving, 1);
//the current player model should be push away by other players to prevent conflict
this.setImmovable(false);
this.getBody().setImmovable(false);
}
moveUser(delta: number): void {

View file

@ -1,7 +1,6 @@
import {TextField} from "../Components/TextField";
import Image = Phaser.GameObjects.Image;
import Sprite = Phaser.GameObjects.Sprite;
import {SelectCharacterSceneInitDataInterface} from "../Login/SelectCharacterScene";
import Text = Phaser.GameObjects.Text;
export const FourOFourSceneName = "FourOFourScene";
@ -11,12 +10,12 @@ enum Textures {
}
export class FourOFourScene extends Phaser.Scene {
private mapNotFoundField: TextField;
private couldNotFindField: TextField;
private fileNameField: Text;
private logo: Image;
private cat: Sprite;
private file: string;
private mapNotFoundField!: TextField;
private couldNotFindField!: TextField;
private fileNameField!: Text;
private logo!: Image;
private cat!: Sprite;
private file!: string;
constructor() {
super({

View file

@ -9,9 +9,8 @@ enum ReconnectingTextures {
}
export class ReconnectingScene extends Phaser.Scene {
private reconnectingField: TextField;
private logo: Image;
private cat: Sprite;
private reconnectingField!: TextField;
private logo!: Image;
constructor() {
super({