space-game/src/levels/testLevel.ts
Michael Mainguy eccf101b73
All checks were successful
Build / build (push) Successful in 1m20s
Implement Svelte-based UI architecture with component system
Major refactoring of the UI layer to use Svelte components:
- Replace inline HTML with modular Svelte components
- Add authentication system with UserProfile component
- Implement navigation store for view management
- Create comprehensive settings and controls screens
- Add level editor with JSON validation
- Implement progression tracking system
- Update level configurations and base station model

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 15:01:17 -06:00

233 lines
8.1 KiB
TypeScript

import { DefaultScene } from "../core/defaultScene";
import {
Color3,
DirectionalLight,
MeshBuilder,
Observable,
StandardMaterial,
Vector3
} from "@babylonjs/core";
import type { AudioEngineV2 } from "@babylonjs/core";
import Level from "./level";
import debugLog from '../core/debug';
/**
* Minimal test level with just a box and a light for debugging
*/
export class TestLevel implements Level {
private _onReadyObservable: Observable<Level> = new Observable<Level>();
private _initialized: boolean = false;
private _audioEngine: AudioEngineV2;
private _boxCreationInterval: number | null = null;
private _totalBoxesCreated: number = 0;
private _boxesPerIteration: number = 1;
constructor(audioEngine: AudioEngineV2) {
this._audioEngine = audioEngine;
debugLog('[TestLevel] Constructor called');
// Don't call initialize here - let Main call it after registering the observable
}
getReadyObservable(): Observable<Level> {
return this._onReadyObservable;
}
public async play() {
debugLog('[TestLevel] play() called - entering XR');
debugLog('[TestLevel] XR available:', !!DefaultScene.XR);
debugLog('[TestLevel] XR baseExperience:', !!DefaultScene.XR?.baseExperience);
try {
// Enter XR mode
const xr = await DefaultScene.XR.baseExperience.enterXRAsync('immersive-vr', 'local-floor');
debugLog('[TestLevel] XR mode entered successfully');
debugLog('[TestLevel] XR session:', xr);
debugLog('[TestLevel] Camera position:', DefaultScene.XR.baseExperience.camera.position.toString());
this.startBoxCreation();
} catch (error) {
console.error('[TestLevel] ERROR entering XR:', error);
}
}
public dispose() {
debugLog('[TestLevel] dispose() called');
// Stop box creation timer
if (this._boxCreationInterval) {
clearInterval(this._boxCreationInterval);
this._boxCreationInterval = null;
debugLog('[TestLevel] Box creation timer stopped');
}
}
/**
* Create a box at the specified position with the specified color
*/
private createBox(position: Vector3, color: Color3, name?: string): void {
const box = MeshBuilder.CreateBox(
name || `box_${this._totalBoxesCreated}`,
{ size: 0.5 },
DefaultScene.MainScene
);
box.position = position;
const material = new StandardMaterial(`material_${this._totalBoxesCreated}`, DefaultScene.MainScene);
material.diffuseColor = color;
material.specularColor = new Color3(0.5, 0.5, 0.5);
box.material = material;
this._totalBoxesCreated++;
}
/**
* Start the box creation timer that doubles the number of boxes each iteration
*/
private startBoxCreation(): void {
debugLog('[TestLevel] Starting box creation timer...');
const createBatch = () => {
const boxesToCreate = Math.min(
this._boxesPerIteration,
1000 - this._totalBoxesCreated
);
debugLog(`[TestLevel] Creating ${boxesToCreate} boxes (total will be: ${this._totalBoxesCreated + boxesToCreate}/1000)`);
for (let i = 0; i < boxesToCreate; i++) {
// Random position in a 20x20x20 cube around origin
const position = new Vector3(
Math.random() * 20 - 10,
Math.random() * 20,
Math.random() * 20 - 10
);
// Random color
const color = new Color3(
Math.random(),
Math.random(),
Math.random()
);
this.createBox(position, color);
}
debugLog(`[TestLevel] Created ${boxesToCreate} boxes. Total: ${this._totalBoxesCreated}/1000`);
// Log performance metrics
const fps = DefaultScene.MainScene.getEngine().getFps();
// Directly compute triangle count from all meshes
const totalIndices = DefaultScene.MainScene.meshes.reduce((sum, mesh) => {
if (mesh.isEnabled() && mesh.isVisible) {
return sum + mesh.getTotalIndices();
}
return sum;
}, 0);
const triangleCount = Math.floor(totalIndices / 3);
debugLog(`[TestLevel] Performance Metrics:`, {
fps: fps.toFixed(2),
triangleCount: triangleCount,
totalIndices: totalIndices,
totalMeshes: DefaultScene.MainScene.meshes.length,
activeMeshes: DefaultScene.MainScene.meshes.filter(m => m.isEnabled() && m.isVisible).length,
totalBoxes: this._totalBoxesCreated
});
// Check if we've reached 1000 boxes
if (this._totalBoxesCreated >= 1000) {
debugLog('[TestLevel] Reached 1000 boxes, stopping timer');
if (this._boxCreationInterval) {
clearInterval(this._boxCreationInterval);
this._boxCreationInterval = null;
}
return;
}
// Double the number for next iteration
this._boxesPerIteration *= 2;
};
// Create first batch immediately
createBatch();
// Set up interval for subsequent batches
this._boxCreationInterval = setInterval(createBatch, 5000);
}
public async initialize() {
debugLog('[TestLevel] initialize() called');
debugLog('[TestLevel] Scene info:', {
meshCount: DefaultScene.MainScene.meshes.length,
lightCount: DefaultScene.MainScene.lights.length
});
if (this._initialized) {
debugLog('[TestLevel] Already initialized, skipping');
return;
}
// Create a simple directional light
const light = new DirectionalLight(
"testLight",
new Vector3(-1, -2, 1),
DefaultScene.MainScene
);
light.intensity = 1.0;
debugLog('[TestLevel] Created directional light:', {
name: light.name,
direction: light.direction.toString(),
intensity: light.intensity
});
// Create a simple colored box
const box = MeshBuilder.CreateBox(
"testBox",
{ size: 2 },
DefaultScene.MainScene
);
box.position = new Vector3(0, 1, 5); // In front of camera
// Create a simple material
const material = new StandardMaterial("testMaterial", DefaultScene.MainScene);
material.diffuseColor = new Color3(1, 0, 0); // Red
material.specularColor = new Color3(0.5, 0.5, 0.5);
box.material = material;
debugLog('[TestLevel] Created test box:', {
name: box.name,
position: box.position.toString(),
size: 2,
color: 'red'
});
// Create a ground plane for reference
const ground = MeshBuilder.CreateGround(
"testGround",
{ width: 10, height: 10 },
DefaultScene.MainScene
);
ground.position.y = 0;
const groundMaterial = new StandardMaterial("groundMaterial", DefaultScene.MainScene);
groundMaterial.diffuseColor = new Color3(0.3, 0.3, 0.3); // Grey
ground.material = groundMaterial;
debugLog('[TestLevel] Created ground plane:', {
name: ground.name,
dimensions: '10x10',
position: ground.position.toString()
});
debugLog('[TestLevel] Final scene state:', {
totalMeshes: DefaultScene.MainScene.meshes.length,
totalLights: DefaultScene.MainScene.lights.length,
meshNames: DefaultScene.MainScene.meshes.map(m => m.name)
});
this._initialized = true;
debugLog('[TestLevel] Initialization complete - scene ready for XR');
// Notify that initialization is complete
this._onReadyObservable.notifyObservers(this);
}
}