Some checks failed
Build / build (push) Failing after 18s
- Update Ship class to use CONVEX_HULL physics from ship1.glb - Find geometry mesh from loaded GLB and create physics from it - Move physics creation to initialize() after mesh loads - Add fallback to BOX shape if mesh not found - Fix ship position setter for async initialization - Add null check for physics body - Set transform position directly if body doesn't exist yet - Prevents crash when position set before mesh loads - Optimize planet vertex count for performance - Reduce sphere segments from 32 to 12 - ~144 vertices vs ~1024 vertices per planet - Planets are background objects, lower poly acceptable - Update ship1.glb model 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
123 lines
4.2 KiB
TypeScript
123 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() {
|
|
this.initialize();
|
|
}
|
|
public get done() {
|
|
return this._done;
|
|
}
|
|
public set done(value: boolean) {
|
|
this._done = value;
|
|
}
|
|
public setRemainingCount(count: number) {
|
|
this._remaining = count;
|
|
}
|
|
private initialize() {
|
|
const scene = DefaultScene.MainScene;
|
|
|
|
const parent = scene.getNodeById('ship');
|
|
console.log('Scoreboard parent:', parent);
|
|
console.log('Initializing scoreboard');
|
|
const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene);
|
|
scoreboard.renderingGroupId = 3;
|
|
const material = new StandardMaterial("scoreboard", scene);
|
|
|
|
scoreboard.parent =parent;
|
|
|
|
scoreboard.position.y = 1.05;
|
|
scoreboard.position.z = 2.1;
|
|
scoreboard.visibility = .5;
|
|
|
|
scoreboard.scaling = new Vector3(.4, .4, .4);
|
|
|
|
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);
|
|
}
|
|
} |