space-game/src/scoreboard.ts

121 lines
4.2 KiB
TypeScript

import {AdvancedDynamicTexture, Control, StackPanel, TextBlock} from "@babylonjs/gui";
import {DefaultScene} from "./defaultScene";
import {
Angle,
MeshBuilder,
Observable, StandardMaterial,
Vector3,
} from "@babylonjs/core";
export type ScoreEvent = {
score: number,
message: string,
remaining: number,
timeRemaining? : number
}
export class Scoreboard {
private _score: number = 0;
private _remaining: number = 0;
private _timeRemaining: number = 61;
private _lastMessage: string = null;
private _active = false;
private _done = false;
public readonly onScoreObservable: Observable<ScoreEvent> = new Observable<ScoreEvent>();
constructor() {
DefaultScene.MainScene.onNewMeshAddedObservable.add((mesh) => {
if (mesh.id == 'RightUpperDisplay') {
this.initialize();
}
});
}
public get done() {
return this._done;
}
public set done(value: boolean) {
this._done = value;
}
private initialize() {
const scene = DefaultScene.MainScene;
const parent = scene.getMeshById('RightUpperDisplay');
const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene);
const material = new StandardMaterial("scoreboard", scene);
scoreboard.parent =parent;
scoreboard.position.x = -.76;
scoreboard.position.y = 4.19;
scoreboard.position.z = .53;
scoreboard.rotation.x = Angle.FromDegrees(104).radians();
scoreboard.rotation.z = Math.PI;
scoreboard.scaling = new Vector3(.3, .3, .3);
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(scoreboard, 512, 512);
advancedTexture.background = "black";
advancedTexture.hasAlpha = false;
const scoreText = this.createText();
const fpsText = this.createText();
fpsText.text = "FPS: 60";
const hullText = this.createText();
hullText.text = 'Hull: 100%';
const remainingText = this.createText();
remainingText.text = 'Remaining: 0';
const timeRemainingText = this.createText();
timeRemainingText.text = 'Time: 2:00';
const panel = new StackPanel();
panel.isVertical = true;
panel.height = 1;
panel.isVertical = true;
panel.addControl(scoreText);
panel.addControl(remainingText);
panel.addControl(fpsText);
panel.addControl(hullText);
panel.addControl(timeRemainingText);
advancedTexture.addControl(panel);
let i = 0;
let lastSecond: number = Date.now();
const afterRender = scene.onAfterRenderObservable.add(() => {
scoreText.text = `Score: ${this.calculateScore()}`;
remainingText.text = `Remaining: ${this._remaining}`;
const now = Date.now();
if (this._active && (Math.floor(lastSecond / 1000) < Math.floor(now/1000))) {
this._timeRemaining--;
if (this._timeRemaining <= 0) {
scene.onAfterRenderObservable.remove(afterRender);
}
lastSecond = now;
timeRemainingText.text = `Time: ${Math.floor(this._timeRemaining/60).toString().padStart(2,"0")}:${(this._timeRemaining%60).toString().padStart(2,"0")}`;
}
if (i++%60 == 0) {
fpsText.text = `FPS: ${Math.floor(scene.getEngine().getFps())}`;
}
});
this.onScoreObservable.add((score: ScoreEvent) => {
this._score += score.score * this._timeRemaining;
this._remaining += score.remaining;
this._lastMessage = score.message;
if (score.timeRemaining) {
this._timeRemaining = score.timeRemaining;
}
});
this._active = true;
}
private createText(): TextBlock {
const text1 = new TextBlock();
text1.color = "white";
text1.fontSize = "60px";
text1.height = "80px";
text1.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
text1.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
return text1;
}
private calculateScore() {
return Math.floor(this._score);
}
}