Hide logo on loading screens
[libreadventure.git] / front / src / Phaser / Login / SelectCharacterScene.ts
1 import {gameManager} from "../Game/GameManager";
2 import {TextField} from "../Components/TextField";
3 import {ClickButton} from "../Components/ClickButton";
4 import Image = Phaser.GameObjects.Image;
5 import Rectangle = Phaser.GameObjects.Rectangle;
6 import {PLAYER_RESOURCES} from "../Entity/Character";
7 import {GameSceneInitInterface} from "../Game/GameScene";
8
9 //todo: put this constants in a dedicated file
10 export const SelectCharacterSceneName = "SelectCharacterScene";
11 enum LoginTextures {
12 playButton = "play_button",
13 icon = "icon",
14 mainFont = "main_font"
15 }
16
17 export interface SelectCharacterSceneInitDataInterface {
18 name: string
19 }
20
21 export class SelectCharacterScene extends Phaser.Scene {
22 private readonly nbCharactersPerRow = 4;
23 private textField: TextField;
24 private pressReturnField: TextField;
25 private logo: Image;
26 private loginName: string;
27
28 private selectedRectangle: Rectangle;
29 private selectedRectangleXPos = 0; // Number of the character selected in the rows
30 private selectedRectangleYPos = 0; // Number of the character selected in the columns
31 private selectedPlayer: Phaser.Physics.Arcade.Sprite;
32 private players: Array<Phaser.Physics.Arcade.Sprite> = new Array<Phaser.Physics.Arcade.Sprite>();
33
34 constructor() {
35 super({
36 key: SelectCharacterSceneName
37 });
38 }
39
40 init({ name }: SelectCharacterSceneInitDataInterface) {
41 this.loginName = name;
42 }
43
44 preload() {
45 this.load.image(LoginTextures.playButton, "resources/objects/play_button.png");
46 //this.load.image(LoginTextures.icon, "resources/logos/tcm_full.png");
47 // Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap
48 this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
49 //add player png
50 PLAYER_RESOURCES.forEach((playerResource: any) => {
51 this.load.spritesheet(
52 playerResource.name,
53 playerResource.img,
54 {frameWidth: 32, frameHeight: 32}
55 );
56 });
57 }
58
59 create() {
60 this.textField = new TextField(this, this.game.renderer.width / 2, 50, 'Select your character');
61 this.textField.setOrigin(0.5).setCenterAlign()
62
63 this.pressReturnField = new TextField(this, this.game.renderer.width / 2, 230, 'Press enter to start');
64 this.pressReturnField.setOrigin(0.5).setCenterAlign()
65
66 let rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16;
67
68 this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xFFFFFF);
69
70 //this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon);
71 //this.add.existing(this.logo);
72
73 this.input.keyboard.on('keyup-ENTER', () => {
74 return this.login(this.loginName);
75 });
76
77 this.input.keyboard.on('keydown-RIGHT', () => {
78 if (this.selectedRectangleXPos < this.nbCharactersPerRow - 1) {
79 this.selectedRectangleXPos++;
80 }
81 this.updateSelectedPlayer();
82 });
83 this.input.keyboard.on('keydown-LEFT', () => {
84 if (this.selectedRectangleXPos > 0) {
85 this.selectedRectangleXPos--;
86 }
87 this.updateSelectedPlayer();
88 });
89 this.input.keyboard.on('keydown-DOWN', () => {
90 if (this.selectedRectangleYPos < Math.ceil(PLAYER_RESOURCES.length / this.nbCharactersPerRow) - 1) {
91 this.selectedRectangleYPos++;
92 }
93 this.updateSelectedPlayer();
94 });
95 this.input.keyboard.on('keydown-UP', () => {
96 if (this.selectedRectangleYPos > 0) {
97 this.selectedRectangleYPos--;
98 }
99 this.updateSelectedPlayer();
100 });
101
102 /*create user*/
103 this.createCurrentPlayer();
104
105 if (window.localStorage) {
106 let playerNumberStr: string = window.localStorage.getItem('selectedPlayer') ?? '0';
107 let playerNumber: number = Number(playerNumberStr);
108 this.selectedRectangleXPos = playerNumber % this.nbCharactersPerRow;
109 this.selectedRectangleYPos = Math.floor(playerNumber / this.nbCharactersPerRow);
110 this.updateSelectedPlayer();
111 }
112 }
113
114 update(time: number, delta: number): void {
115 this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2));
116 }
117
118 private async login(name: string) {
119 return gameManager.connect(name, this.selectedPlayer.texture.key).then(() => {
120 // Do we have a start URL in the address bar? If so, let's redirect to this address
121 let instanceAndMapUrl = this.findMapUrl();
122 if (instanceAndMapUrl !== null) {
123 let [mapUrl, instance] = instanceAndMapUrl;
124 let key = gameManager.loadMap(mapUrl, this.scene, instance);
125 this.scene.start(key, {
126 startLayerName: window.location.hash ? window.location.hash.substr(1) : undefined
127 } as GameSceneInitInterface);
128 return mapUrl;
129 } else {
130 // If we do not have a map address in the URL, let's ask the server for a start map.
131 return gameManager.loadStartMap().then((scene : any) => {
132 if (!scene) {
133 return;
134 }
135 let key = gameManager.loadMap(window.location.protocol + "//" + scene.mapUrlStart, this.scene, scene.startInstance);
136 this.scene.start(key);
137 return scene;
138 }).catch((err) => {
139 console.error(err);
140 throw err;
141 });
142 }
143 }).catch((err) => {
144 console.error(err);
145 throw err;
146 });
147 }
148
149 /**
150 * Returns the map URL and the instance from the current URL
151 */
152 private findMapUrl(): [string, string]|null {
153 let path = window.location.pathname;
154 if (!path.startsWith('/_/')) {
155 return null;
156 }
157 let instanceAndMap = path.substr(3);
158 let firstSlash = instanceAndMap.indexOf('/');
159 if (firstSlash === -1) {
160 return null;
161 }
162 let instance = instanceAndMap.substr(0, firstSlash);
163 return [window.location.protocol+'//'+instanceAndMap.substr(firstSlash+1), instance];
164 }
165
166 createCurrentPlayer(): void {
167 for (let i = 0; i <PLAYER_RESOURCES.length; i++) {
168 let playerResource = PLAYER_RESOURCES[i];
169
170 let col = i % this.nbCharactersPerRow;
171 let row = Math.floor(i / this.nbCharactersPerRow);
172
173 let [x, y] = this.getCharacterPosition(col, row);
174 let player = this.physics.add.sprite(x, y, playerResource.name, 0);
175 player.setBounce(0.2);
176 player.setCollideWorldBounds(true);
177 this.anims.create({
178 key: playerResource.name,
179 frames: this.anims.generateFrameNumbers(playerResource.name, {start: 0, end: 2,}),
180 frameRate: 10,
181 repeat: -1
182 });
183 player.setInteractive().on("pointerdown", () => {
184 this.selectedRectangleXPos = col;
185 this.selectedRectangleYPos = row;
186 this.updateSelectedPlayer();
187 });
188 this.players.push(player);
189 }
190 this.selectedPlayer = this.players[0];
191 this.selectedPlayer.play(PLAYER_RESOURCES[0].name);
192 }
193
194 /**
195 * Returns pixel position by on column and row number
196 */
197 private getCharacterPosition(x: number, y: number): [number, number] {
198 return [
199 this.game.renderer.width / 2 + 16 + (x - this.nbCharactersPerRow / 2) * 32,
200 y * 32 + 90
201 ];
202 }
203
204 private updateSelectedPlayer(): void {
205 this.selectedPlayer.anims.pause();
206 let [x, y] = this.getCharacterPosition(this.selectedRectangleXPos, this.selectedRectangleYPos);
207 this.selectedRectangle.setX(x);
208 this.selectedRectangle.setY(y);
209 let playerNumber = this.selectedRectangleXPos + this.selectedRectangleYPos * this.nbCharactersPerRow;
210 let player = this.players[playerNumber];
211 player.play(PLAYER_RESOURCES[playerNumber].name);
212 this.selectedPlayer = player;
213 if (window.localStorage) {
214 window.localStorage.setItem('selectedPlayer', String(playerNumber));
215 }
216 }
217 }