diff --git a/public/base.glb b/public/base.glb index a3df2df..c332c49 100644 Binary files a/public/base.glb and b/public/base.glb differ diff --git a/public/ship1.glb b/public/ship1.glb index af17b15..a95912d 100644 Binary files a/public/ship1.glb and b/public/ship1.glb differ diff --git a/public/ship2.glb b/public/ship2.glb index b61d626..d13b7f1 100644 Binary files a/public/ship2.glb and b/public/ship2.glb differ diff --git a/src/level1.ts b/src/level1.ts index 8901360..6abfb66 100644 --- a/src/level1.ts +++ b/src/level1.ts @@ -27,7 +27,6 @@ export class Level1 implements Level { private _initialized: boolean = false; private _startBase: AbstractMesh; private _endBase: AbstractMesh; - private _scoreboard: Scoreboard; private _levelConfig: LevelConfig; private _audioEngine: AudioEngineV2; private _deserializer: LevelDeserializer; @@ -38,7 +37,7 @@ export class Level1 implements Level { this._audioEngine = audioEngine; this._deserializer = new LevelDeserializer(levelConfig); this._ship = new Ship(audioEngine); - this._scoreboard = new Scoreboard(); + const xr = DefaultScene.XR; debugLog('Level1 constructor - Setting up XR observables'); @@ -105,18 +104,18 @@ export class Level1 implements Level { setLoadingMessage("Loading level from configuration..."); // Use deserializer to create all entities from config - const entities = await this._deserializer.deserialize(this._scoreboard.onScoreObservable); + const entities = await this._deserializer.deserialize(this._ship.scoreboard.onScoreObservable); this._startBase = entities.startBase; // sun and planets are already created by deserializer // Initialize scoreboard with total asteroid count - this._scoreboard.setRemainingCount(entities.asteroids.length); + this._ship.scoreboard.setRemainingCount(entities.asteroids.length); debugLog(`Initialized scoreboard with ${entities.asteroids.length} asteroids`); // Position ship from config const shipConfig = this._deserializer.getShipConfig(); - this._ship.position = new Vector3(shipConfig.position[0], shipConfig.position[1], shipConfig.position[2]); + //this._ship.position = new Vector3(shipConfig.position[0], shipConfig.position[1], shipConfig.position[2]); // Add distance constraints to asteroids (if physics enabled) setLoadingMessage("Configuring physics constraints..."); diff --git a/src/scoreboard.ts b/src/scoreboard.ts index 506def4..b34f82f 100644 --- a/src/scoreboard.ts +++ b/src/scoreboard.ts @@ -1,6 +1,7 @@ import {AdvancedDynamicTexture, Control, StackPanel, TextBlock} from "@babylonjs/gui"; import {DefaultScene} from "./defaultScene"; import { + AbstractMesh, Mesh, MeshBuilder, Observable, StandardMaterial, Vector3, @@ -21,7 +22,7 @@ export class Scoreboard { private _done = false; public readonly onScoreObservable: Observable = new Observable(); constructor() { - this.initialize(); + } public get done() { return this._done; @@ -32,26 +33,40 @@ export class Scoreboard { public setRemainingCount(count: number) { this._remaining = count; } - private initialize() { + public initialize(baseMesh: Mesh) { const scene = DefaultScene.MainScene; const parent = scene.getNodeById('ship'); debugLog('Scoreboard parent:', parent); debugLog('Initializing scoreboard'); - const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene); + let scoreboard = null; + + if (baseMesh) { + scoreboard = baseMesh; + + scoreboard.material.dispose(); + //scoreboard.material = new StandardMaterial("scoreboard", scene); + + } else { + scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene); + scoreboard.parent =parent; + + scoreboard.position.y = 1.05; + scoreboard.position.z = 2.1; + scoreboard.visibility = .5; + scoreboard.scaling = new Vector3(.4, .4, .4); + } + // 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.background = "green"; advancedTexture.hasAlpha = false; const scoreText = this.createText(); @@ -69,8 +84,8 @@ export class Scoreboard { const panel = new StackPanel(); panel.isVertical = true; - panel.height = 1; - panel.isVertical = true; + //panel.height = .5; + //panel.isVertical = true; panel.addControl(scoreText); panel.addControl(remainingText); panel.addControl(fpsText); @@ -92,6 +107,7 @@ export class Scoreboard { this._score += score.score; this._remaining += score.remaining; }); + this._active = true; } private createText(): TextBlock { diff --git a/src/ship.ts b/src/ship.ts index 89be482..70358e8 100644 --- a/src/ship.ts +++ b/src/ship.ts @@ -22,9 +22,10 @@ import {DefaultScene} from "./defaultScene"; import { GameConfig } from "./gameConfig"; import { Sight } from "./sight"; import debugLog from './debug'; -const MAX_LINEAR_VELOCITY = 80; +import {Scoreboard} from "./scoreboard"; +const MAX_LINEAR_VELOCITY = 200; const MAX_ANGULAR_VELOCITY = 1.8; -const LINEAR_FORCE_MULTIPLIER = 800; +const LINEAR_FORCE_MULTIPLIER = 1200; const ANGULAR_FORCE_MULTIPLIER = 20; const controllerComponents = [ @@ -52,6 +53,7 @@ type ControllerEvent = { export class Ship { private _ship: TransformNode; + private _scoreboard: Scoreboard; private _controllerObservable: Observable = new Observable(); private _ammoMaterial: StandardMaterial; private _primaryThrustVectorSound: StaticSound; @@ -87,7 +89,9 @@ export class Ship { volume: 0.5 }); } - + public get scoreboard(): Scoreboard { + return this._scoreboard; + } private shoot() { // Only allow shooting if physics is enabled const config = GameConfig.getInstance(); @@ -98,8 +102,9 @@ export class Ship { this._shot?.play(); const ammo = new InstancedMesh("ammo", this._ammoBaseMesh as Mesh); ammo.parent = this._ship; - ammo.position.y = 2; - ammo.rotation.x = Math.PI / 2; + ammo.position.y = .5; + ammo.position.z = 7.1; + //ammo.rotation.x = Math.PI / 2; ammo.setParent(null); const ammoAggregate = new PhysicsAggregate(ammo, PhysicsShapeType.SPHERE, { mass: 1000, @@ -110,7 +115,7 @@ export class Ship { ammoAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC); - ammoAggregate.body.setLinearVelocity(this._ship.forward.scale(100000)) + ammoAggregate.body.setLinearVelocity(this._ship.forward.scale(200000)) //.add(this._ship.physicsBody.getLinearVelocity())); window.setTimeout(() => { @@ -170,7 +175,7 @@ export class Ship { // Create sight reticle this._sight = new Sight(DefaultScene.MainScene, this._ship, { - position: new Vector3(0, 2, 125), + position: new Vector3(0, .5, 125), circleRadius: 2, crosshairLength: 1.5, lineThickness: 0.1, @@ -183,11 +188,16 @@ export class Ship { private async initialize() { + this._scoreboard = new Scoreboard(); + const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "ship2.glb", DefaultScene.MainScene); + const shipMesh = importMesh.meshes[0]; shipMesh.id = "shipMesh"; shipMesh.name = "shipMesh"; + debugLog(shipMesh.position); shipMesh.parent = this._ship; + debugLog(shipMesh.position); // Create physics aggregate based on the loaded mesh (if physics enabled) const config = GameConfig.getInstance(); @@ -242,6 +252,9 @@ export class Ship { } light.parent = this._ship;*/ //DefaultScene.MainScene.getMaterialById('glass_mat.002').alpha = .4; + const screenMesh = DefaultScene.MainScene.getMaterialById('Screen')?.getBindedMeshes()[0]; + this._scoreboard.initialize(screenMesh as Mesh); + //this._scoreboard.initialize(null); } diff --git a/src/sight.ts b/src/sight.ts index c51d924..a556766 100644 --- a/src/sight.ts +++ b/src/sight.ts @@ -78,8 +78,9 @@ export class Sight { tessellation: 64 }, this.scene); this.circle.parent = this.reticleGroup; + this.circle.rotation.x = -Math.PI / 2; this.circle.material = material; - // this.circle.renderingGroupId = this.config.renderingGroupId; + this.circle.renderingGroupId = this.config.renderingGroupId; // Create crosshair lines (4 lines extending from center gap) this.createCrosshairLines(material);