-
🎨 Graphics Quality
-
- Higher quality settings may impact performance on lower-end devices.
-
-
-
-
-
-
-
-
⚛️ Physics
diff --git a/public/assets/themes/default/models/base.glb b/public/assets/themes/default/models/base.glb
index ecdea59..be5e245 100644
Binary files a/public/assets/themes/default/models/base.glb and b/public/assets/themes/default/models/base.glb differ
diff --git a/public/assets/themes/default/models/ship.glb b/public/assets/themes/default/models/ship.glb
index 2d0ae63..cd81881 100644
Binary files a/public/assets/themes/default/models/ship.glb and b/public/assets/themes/default/models/ship.glb differ
diff --git a/public/ship1.stl b/public/ship1.stl
deleted file mode 100644
index c23cb96..0000000
Binary files a/public/ship1.stl and /dev/null differ
diff --git a/src/gameConfig.ts b/src/gameConfig.ts
index 5ca80b7..4c0feba 100644
--- a/src/gameConfig.ts
+++ b/src/gameConfig.ts
@@ -1,13 +1,3 @@
-/**
- * Texture detail levels for game objects
- */
-export enum TextureLevel {
- WIREFRAME = 'WIREFRAME',
- SIMPLE_MATERIAL = 'SIMPLE_MATERIAL',
- FULL_TEXTURE = 'FULL_TEXTURE',
- PBR_TEXTURE = 'PBR_TEXTURE'
-}
-
/**
* Global game configuration settings
* Singleton class for managing game-wide settings
@@ -15,10 +5,6 @@ export enum TextureLevel {
export class GameConfig {
private static _instance: GameConfig;
- // Texture detail settings
- public planetTextureLevel: TextureLevel = TextureLevel.FULL_TEXTURE;
- public asteroidTextureLevel: TextureLevel = TextureLevel.FULL_TEXTURE;
- public sunTextureLevel: TextureLevel = TextureLevel.FULL_TEXTURE;
public debug: boolean = false;
// Physics settings
public physicsEnabled: boolean = true;
@@ -46,9 +32,6 @@ export class GameConfig {
*/
public save(): void {
const config = {
- planetTextureLevel: this.planetTextureLevel,
- asteroidTextureLevel: this.asteroidTextureLevel,
- sunTextureLevel: this.sunTextureLevel,
physicsEnabled: this.physicsEnabled,
debug: this.debug
};
@@ -63,9 +46,6 @@ export class GameConfig {
const stored = localStorage.getItem('game-config');
if (stored) {
const config = JSON.parse(stored);
- this.planetTextureLevel = config.planetTextureLevel ?? TextureLevel.FULL_TEXTURE;
- this.asteroidTextureLevel = config.asteroidTextureLevel ?? TextureLevel.FULL_TEXTURE;
- this.sunTextureLevel = config.sunTextureLevel ?? TextureLevel.FULL_TEXTURE;
this.physicsEnabled = config.physicsEnabled ?? true;
this.debug = config.debug ?? false;
} else {
@@ -80,9 +60,6 @@ export class GameConfig {
* Reset to default settings
*/
public reset(): void {
- this.planetTextureLevel = TextureLevel.FULL_TEXTURE;
- this.asteroidTextureLevel = TextureLevel.FULL_TEXTURE;
- this.sunTextureLevel = TextureLevel.FULL_TEXTURE;
this.physicsEnabled = true;
this.debug = false;
this.save();
diff --git a/src/level1.ts b/src/level1.ts
index 4753e2f..0b52817 100644
--- a/src/level1.ts
+++ b/src/level1.ts
@@ -30,6 +30,7 @@ export class Level1 implements Level {
this._deserializer = new LevelDeserializer(levelConfig);
this._ship = new Ship(audioEngine);
+
const xr = DefaultScene.XR;
debugLog('Level1 constructor - Setting up XR observables');
@@ -45,7 +46,7 @@ export class Level1 implements Level {
this._ship.addController(controller);
});
});
- this.initialize();
+ // Don't call initialize here - let Main call it after registering the observable
}
getReadyObservable(): Observable
{
@@ -92,9 +93,10 @@ export class Level1 implements Level {
public async initialize() {
debugLog('Initializing level from config:', this._levelConfig.difficulty);
if (this._initialized) {
+ console.error('Initialize called twice');
return;
}
-
+ await this._ship.initialize();
setLoadingMessage("Loading level from configuration...");
// Use deserializer to create all entities from config
diff --git a/src/levelDeserializer.ts b/src/levelDeserializer.ts
index 8fc0c1c..0ac5084 100644
--- a/src/levelDeserializer.ts
+++ b/src/levelDeserializer.ts
@@ -2,6 +2,8 @@ import {
AbstractMesh,
MeshBuilder,
Observable,
+ PBRMaterial,
+ Texture,
Vector3
} from "@babylonjs/core";
import { DefaultScene } from "./defaultScene";
@@ -14,7 +16,8 @@ import {
validateLevelConfig
} from "./levelConfig";
import { GameConfig } from "./gameConfig";
-import { MaterialFactory } from "./materialFactory";
+import { FireProceduralTexture } from "@babylonjs/procedural-textures";
+import { createSphereLightmap } from "./sphereLightmap";
import debugLog from './debug';
import StarBase from "./starBase";
@@ -71,8 +74,7 @@ export class LevelDeserializer {
* Create the start base from config
*/
private async createStartBase(): Promise {
- const position = this?.config?.startBase?.position?this.arrayToVector3(this?.config?.startBase?.position):null;
- return await StarBase.buildStarBase(position);
+ return await StarBase.buildStarBase();
}
/**
@@ -85,18 +87,13 @@ export class LevelDeserializer {
segments: 32
}, this.scene);
sun.position = this.arrayToVector3(config.position);
- // Create material using GameConfig texture level
- const gameConfig = GameConfig.getInstance();
- const material = MaterialFactory.createSunMaterial(
- "sunMaterial",
- gameConfig.sunTextureLevel,
- this.scene
- );
- sun.material = material;
- // Create glow layer
- //const gl = new GlowLayer("glow", this.scene);
- //gl.intensity = 1;
+ // Create PBR sun material with fire texture
+ const material = new PBRMaterial("sunMaterial", this.scene);
+ material.emissiveTexture = new FireProceduralTexture("fire", 1024, this.scene);
+ material.emissiveColor.set(0.5, 0.5, 0.1);
+ material.unlit = true;
+ sun.material = material;
return sun;
}
@@ -122,16 +119,28 @@ export class LevelDeserializer {
// Calculate direction from planet to sun
const toSun = sunPosition.subtract(planetPosition).normalize();
- // Create material using GameConfig texture level
- const config = GameConfig.getInstance();
- const material = MaterialFactory.createPlanetMaterial(
- planetConfig.name + "-material",
- planetConfig.texturePath,
- config.planetTextureLevel,
+ // Create PBR planet material
+ const material = new PBRMaterial(planetConfig.name + "-material", this.scene);
+ const texture = new Texture(planetConfig.texturePath, this.scene);
+
+ // Create lightmap with bright light pointing toward sun
+ const lightmap = createSphereLightmap(
+ planetConfig.name + "-lightmap",
+ 256,
this.scene,
- toSun
+ toSun,
+ 1,
+ toSun.negate(),
+ 0.3,
+ 0.3
);
+ material.albedoTexture = texture;
+ material.lightmapTexture = lightmap;
+ material.useLightmapAsShadowmap = true;
+ material.roughness = 0.8;
+ material.metallic = 0;
+
planet.material = material;
planets.push(planet);
diff --git a/src/main.ts b/src/main.ts
index bcbdbd0..5768993 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -46,20 +46,31 @@ export class Main {
setLoadingMessage("This browser does not support WebXR");
return;
}
- this.initialize();
+
// Listen for level selection event
window.addEventListener('levelSelected', async (e: CustomEvent) => {
+ this._started = true;
+ await this.initialize();
const {levelName, config} = e.detail as {levelName: string, config: LevelConfig};
debugLog(`Starting level: ${levelName}`);
- // Show loading UI again
+ // Hide all UI elements
const mainDiv = document.querySelector('#mainDiv');
const levelSelect = document.querySelector('#levelSelect') as HTMLElement;
+ const editorLink = document.querySelector('.editor-link') as HTMLElement;
+ const settingsLink = document.querySelector('.settings-link') as HTMLElement;
+
if (levelSelect) {
levelSelect.style.display = 'none';
}
+ if (editorLink) {
+ editorLink.style.display = 'none';
+ }
+ if (settingsLink) {
+ settingsLink.style.display = 'none';
+ }
setLoadingMessage("Initializing Level...");
// Unlock audio engine on user interaction
@@ -80,10 +91,15 @@ export class Main {
this.play();
}, 500);
});
+
+ // Now initialize the level (after observable is registered)
+ await this._currentLevel.initialize();
});
// Listen for test level button click
window.addEventListener('DOMContentLoaded', () => {
+ const levelSelect = document.querySelector('#levelSelect');
+ levelSelect.classList.add('ready');
debugLog('[Main] DOMContentLoaded fired, looking for test button...');
const testLevelBtn = document.querySelector('#testLevelBtn');
debugLog('[Main] Test button found:', !!testLevelBtn);
@@ -92,9 +108,12 @@ export class Main {
testLevelBtn.addEventListener('click', async () => {
debugLog('[Main] ========== TEST LEVEL BUTTON CLICKED ==========');
- // Show loading UI
+ // Hide all UI elements
const mainDiv = document.querySelector('#mainDiv');
const levelSelect = document.querySelector('#levelSelect') as HTMLElement;
+ const editorLink = document.querySelector('.editor-link') as HTMLElement;
+ const settingsLink = document.querySelector('.settings-link') as HTMLElement;
+
debugLog('[Main] mainDiv exists:', !!mainDiv);
debugLog('[Main] levelSelect exists:', !!levelSelect);
@@ -102,6 +121,12 @@ export class Main {
levelSelect.style.display = 'none';
debugLog('[Main] levelSelect hidden');
}
+ if (editorLink) {
+ editorLink.style.display = 'none';
+ }
+ if (settingsLink) {
+ settingsLink.style.display = 'none';
+ }
setLoadingMessage("Initializing Test Scene...");
// Unlock audio engine on user interaction
@@ -193,7 +218,6 @@ export class Main {
// photoDome1.position = DefaultScene.MainScene.activeCamera.globalPosition;
// photoDome2.position = DefaultScene.MainScene.activeCamera.globalPosition;
});
- setLoadingMessage("Select a difficulty to begin!");
}
private async setupScene() {
@@ -236,11 +260,7 @@ export class Main {
window.setTimeout(()=>{
if (!this._started) {
this._started = true;
- const levelSelect = document.querySelector('#levelSelect');
- if (levelSelect) {
- levelSelect.classList.add('ready');
- setLoadingMessage("Ready!");
- }
+ setLoadingMessage("Ready!");
}
})
@@ -250,6 +270,7 @@ export class Main {
}
private async setupPhysics() {
+ //DefaultScene.MainScene.useRightHandedSystem = true;
const havok = await HavokPhysics();
const havokPlugin = new HavokPlugin(true, havok);
//DefaultScene.MainScene.ambientColor = new Color3(.1, .1, .1);
diff --git a/src/materialFactory.ts b/src/materialFactory.ts
deleted file mode 100644
index a9197d5..0000000
--- a/src/materialFactory.ts
+++ /dev/null
@@ -1,305 +0,0 @@
-import {
- Color3,
- DynamicTexture,
- NoiseProceduralTexture,
- PBRMaterial,
- Scene,
- StandardMaterial,
- Texture,
- Vector3
-} from "@babylonjs/core";
-import { TextureLevel } from "./gameConfig";
-import { FireProceduralTexture } from "@babylonjs/procedural-textures";
-import { createSphereLightmap } from "./sphereLightmap";
-
-/**
- * Factory for creating materials at different quality levels
- */
-export class MaterialFactory {
- /**
- * Create a planet material based on texture level
- */
- public static createPlanetMaterial(
- name: string,
- texturePath: string,
- textureLevel: TextureLevel,
- scene: Scene,
- sunDirection: Vector3
- ): StandardMaterial | PBRMaterial {
- switch (textureLevel) {
- case TextureLevel.WIREFRAME:
- return this.createWireframeMaterial(name, scene, new Color3(0.5, 0.5, 0.8));
-
- case TextureLevel.SIMPLE_MATERIAL:
- return this.createSimplePlanetMaterial(name, scene);
-
- case TextureLevel.FULL_TEXTURE:
- return this.createFullTexturePlanetMaterial(name, texturePath, scene, sunDirection);
-
- case TextureLevel.PBR_TEXTURE:
- return this.createPBRPlanetMaterial(name, texturePath, scene, sunDirection);
-
- default:
- return this.createFullTexturePlanetMaterial(name, texturePath, scene, sunDirection);
- }
- }
-
- /**
- * Create an asteroid material based on texture level
- */
- public static createAsteroidMaterial(
- name: string,
- textureLevel: TextureLevel,
- scene: Scene,
- originalMaterial?: PBRMaterial
- ): StandardMaterial | PBRMaterial {
- switch (textureLevel) {
- case TextureLevel.WIREFRAME:
- return this.createWireframeMaterial(name, scene, new Color3(0.5, 0.5, 0.5));
-
- case TextureLevel.SIMPLE_MATERIAL:
- return this.createSimpleAsteroidMaterial(name, scene);
-
- case TextureLevel.FULL_TEXTURE:
- return this.createFullTextureAsteroidMaterial(name, scene, originalMaterial);
-
- case TextureLevel.PBR_TEXTURE:
- return this.createPBRAsteroidMaterial(name, scene, originalMaterial);
-
- default:
- return this.createFullTextureAsteroidMaterial(name, scene, originalMaterial);
- }
- }
-
- /**
- * Create a sun material based on texture level
- */
- public static createSunMaterial(
- name: string,
- textureLevel: TextureLevel,
- scene: Scene
- ): StandardMaterial | PBRMaterial {
- switch (textureLevel) {
- case TextureLevel.WIREFRAME:
- return this.createWireframeMaterial(name, scene, new Color3(1, 1, 0));
-
- case TextureLevel.SIMPLE_MATERIAL:
- return this.createSimpleSunMaterial(name, scene);
-
- case TextureLevel.FULL_TEXTURE:
- return this.createFullTextureSunMaterial(name, scene);
-
- case TextureLevel.PBR_TEXTURE:
- return this.createPBRSunMaterial(name, scene);
-
- default:
- return this.createFullTextureSunMaterial(name, scene);
- }
- }
-
- // ========== Private helper methods ==========
-
- /**
- * Create wireframe material
- */
- private static createWireframeMaterial(
- name: string,
- scene: Scene,
- color: Color3
- ): StandardMaterial {
- const material = new StandardMaterial(name, scene);
- material.wireframe = true;
- material.emissiveColor = color;
- material.disableLighting = true;
- return material;
- }
-
- /**
- * Create simple planet material with solid color
- */
- private static createSimplePlanetMaterial(name: string, scene: Scene): StandardMaterial {
- const material = new StandardMaterial(name, scene);
- material.diffuseColor = new Color3(0.4, 0.6, 0.8);
- material.specularColor = Color3.Black();
- return material;
- }
-
- /**
- * Create full texture planet material (current implementation)
- */
- private static createFullTexturePlanetMaterial(
- name: string,
- texturePath: string,
- scene: Scene,
- sunDirection: Vector3
- ): StandardMaterial {
- const material = new StandardMaterial(name, scene);
- const texture = new Texture(texturePath, scene);
-
- // Create lightmap with bright light pointing toward sun
- const lightmap = createSphereLightmap(
- name + "-lightmap",
- 256,
- scene,
- sunDirection,
- 1,
- sunDirection.negate(),
- 0.3,
- 0.3
- );
-
- material.emissiveTexture = texture;
- material.lightmapTexture = lightmap;
- material.useLightmapAsShadowmap = true;
- material.disableLighting = true;
- material.roughness = 1;
- material.specularColor = Color3.Black();
- material.freeze();
-
- return material;
- }
-
- /**
- * Create PBR planet material
- */
- private static createPBRPlanetMaterial(
- name: string,
- texturePath: string,
- scene: Scene,
- sunDirection: Vector3
- ): PBRMaterial {
- const material = new PBRMaterial(name, scene);
- const texture = new Texture(texturePath, scene);
-
- // Create lightmap with bright light pointing toward sun
- const lightmap = createSphereLightmap(
- name + "-lightmap",
- 256,
- scene,
- sunDirection,
- 1,
- sunDirection.negate(),
- 0.3,
- 0.3
- );
-
- material.albedoTexture = texture;
- material.lightmapTexture = lightmap;
- material.useLightmapAsShadowmap = true;
- material.roughness = 0.8;
- material.metallic = 0;
-
- return material;
- }
-
- /**
- * Create simple asteroid material with solid color
- */
- private static createSimpleAsteroidMaterial(name: string, scene: Scene): StandardMaterial {
- const material = new StandardMaterial(name, scene);
- material.diffuseColor = new Color3(0.4, 0.4, 0.4);
- material.specularColor = Color3.Black();
- return material;
- }
-
- /**
- * Create full texture asteroid material (current implementation)
- */
- private static createFullTextureAsteroidMaterial(name: string, scene: Scene, originalMaterial?: PBRMaterial): StandardMaterial {
- // If we have the original material from GLB, use it as a base
- if (originalMaterial) {
- // Clone the original material to preserve bump texture and other properties
- const material = originalMaterial.clone(name) as PBRMaterial;
-
- // Create noise texture for color variation
- const noiseTexture = new NoiseProceduralTexture(name + "-noise", 256, scene);
- noiseTexture.brightness = 0.6;
- noiseTexture.octaves = 4;
-
- // Replace only the albedo texture, keeping bump and other textures
- material.albedoTexture = noiseTexture;
- material.roughness = 1;
-
- return material as any as StandardMaterial;
- }
-
- // Fallback if no original material
- const material = new StandardMaterial(name, scene);
- const noiseTexture = new NoiseProceduralTexture(name + "-noise", 256, scene);
- noiseTexture.brightness = 0.6;
- noiseTexture.octaves = 4;
-
- material.ambientTexture = noiseTexture;
- material.diffuseTexture = noiseTexture;
- material.roughness = 1;
-
- return material;
- }
-
- /**
- * Create PBR asteroid material
- */
- private static createPBRAsteroidMaterial(name: string, scene: Scene, originalMaterial?: PBRMaterial): PBRMaterial {
- // If we have the original material from GLB, use it as a base
- if (originalMaterial) {
- // Clone the original material to preserve bump texture and other properties
- const material = originalMaterial.clone(name) as PBRMaterial;
-
- // Create noise texture for color variation
- const noiseTexture = new NoiseProceduralTexture(name + "-noise", 256, scene);
- noiseTexture.brightness = 0.6;
- noiseTexture.octaves = 4;
-
- // Replace only the albedo texture, keeping bump and other textures
- material.albedoTexture = noiseTexture;
- material.roughness = 1;
- material.metallic = 0;
-
- return material;
- }
-
- // Fallback if no original material
- const material = new PBRMaterial(name, scene);
- const noiseTexture = new NoiseProceduralTexture(name + "-noise", 256, scene);
- noiseTexture.brightness = 0.6;
- noiseTexture.octaves = 4;
-
- material.albedoTexture = noiseTexture;
- material.roughness = 1;
- material.metallic = 0;
-
- return material;
- }
-
- /**
- * Create simple sun material with solid color
- */
- private static createSimpleSunMaterial(name: string, scene: Scene): StandardMaterial {
- const material = new StandardMaterial(name, scene);
- material.emissiveColor = new Color3(1, 0.9, 0.2);
- material.disableLighting = true;
- return material;
- }
-
- /**
- * Create full texture sun material (current implementation)
- */
- private static createFullTextureSunMaterial(name: string, scene: Scene): StandardMaterial {
- const material = new StandardMaterial(name, scene);
- material.emissiveTexture = new FireProceduralTexture("fire", 1024, scene);
- material.emissiveColor = new Color3(0.5, 0.5, 0.1);
- material.disableLighting = true;
- return material;
- }
-
- /**
- * Create PBR sun material
- */
- private static createPBRSunMaterial(name: string, scene: Scene): PBRMaterial {
- const material = new PBRMaterial(name, scene);
- material.emissiveTexture = new FireProceduralTexture("fire", 1024, scene);
- material.emissiveColor = new Color3(0.5, 0.5, 0.1);
- material.unlit = true;
- return material;
- }
-}
diff --git a/src/rockFactory.ts b/src/rockFactory.ts
index f2f97f2..5b9671f 100644
--- a/src/rockFactory.ts
+++ b/src/rockFactory.ts
@@ -55,7 +55,7 @@ export class RockFactory {
private static async loadMesh() {
debugLog('loading mesh');
this._asteroidMesh = (await loadAsset("asteroid.glb")).meshes.get('Asteroid');
- this._asteroidMesh.setParent(null);
+ //this._asteroidMesh.setParent(null);
this._asteroidMesh.setEnabled(false);
debugLog(this._asteroidMesh);
}
diff --git a/src/settingsScreen.ts b/src/settingsScreen.ts
index 41ef983..3a88255 100644
--- a/src/settingsScreen.ts
+++ b/src/settingsScreen.ts
@@ -1,4 +1,4 @@
-import { GameConfig, TextureLevel } from "./gameConfig";
+import { GameConfig } from "./gameConfig";
/**
* Initialize the settings screen
@@ -7,9 +7,6 @@ export function initializeSettingsScreen(): void {
const config = GameConfig.getInstance();
// Get form elements
- const planetTextureSelect = document.getElementById('planetTextureLevel') as HTMLSelectElement;
- const asteroidTextureSelect = document.getElementById('asteroidTextureLevel') as HTMLSelectElement;
- const sunTextureSelect = document.getElementById('sunTextureLevel') as HTMLSelectElement;
const physicsEnabledCheckbox = document.getElementById('physicsEnabled') as HTMLInputElement;
const debugEnabledCheckbox = document.getElementById('debugEnabled') as HTMLInputElement;
@@ -39,9 +36,6 @@ export function initializeSettingsScreen(): void {
* Load current settings into form
*/
function loadSettings(): void {
- if (planetTextureSelect) planetTextureSelect.value = config.planetTextureLevel;
- if (asteroidTextureSelect) asteroidTextureSelect.value = config.asteroidTextureLevel;
- if (sunTextureSelect) sunTextureSelect.value = config.sunTextureLevel;
if (physicsEnabledCheckbox) physicsEnabledCheckbox.checked = config.physicsEnabled;
if (debugEnabledCheckbox) debugEnabledCheckbox.checked = config.debug;
}
@@ -50,9 +44,6 @@ export function initializeSettingsScreen(): void {
* Save form settings to GameConfig
*/
function saveSettings(): void {
- config.planetTextureLevel = planetTextureSelect.value as TextureLevel;
- config.asteroidTextureLevel = asteroidTextureSelect.value as TextureLevel;
- config.sunTextureLevel = sunTextureSelect.value as TextureLevel;
config.physicsEnabled = physicsEnabledCheckbox.checked;
config.debug = debugEnabledCheckbox.checked;
config.save();
diff --git a/src/ship.ts b/src/ship.ts
index 7090253..2e56bb3 100644
--- a/src/ship.ts
+++ b/src/ship.ts
@@ -8,7 +8,6 @@ import {
PhysicsAggregate,
PhysicsMotionType,
PhysicsShapeType,
- SceneLoader,
StandardMaterial,
TransformNode,
Vector2,
@@ -23,10 +22,12 @@ import { GameConfig } from "./gameConfig";
import { Sight } from "./sight";
import debugLog from './debug';
import {Scoreboard} from "./scoreboard";
+import loadAsset from "./utils/loadAsset";
+import {Debug} from "@babylonjs/core/Legacy/legacy";
const MAX_LINEAR_VELOCITY = 200;
-const MAX_ANGULAR_VELOCITY = 1.8;
-const LINEAR_FORCE_MULTIPLIER = 1200;
-const ANGULAR_FORCE_MULTIPLIER = 20;
+const MAX_ANGULAR_VELOCITY = 1.4;
+const LINEAR_FORCE_MULTIPLIER = 800;
+const ANGULAR_FORCE_MULTIPLIER = 15;
const controllerComponents = [
'a-button',
@@ -69,8 +70,6 @@ export class Ship {
constructor( audioEngine?: AudioEngineV2) {
this._audioEngine = audioEngine;
- this.setup();
- this.initialize();
}
private async initializeSounds() {
@@ -102,8 +101,8 @@ export class Ship {
this._shot?.play();
const ammo = new InstancedMesh("ammo", this._ammoBaseMesh as Mesh);
ammo.parent = this._ship;
- ammo.position.y = .5;
- ammo.position.z = 7.1;
+ ammo.position.y = .1;
+ ammo.position.z = 8.4;
//ammo.rotation.x = Math.PI / 2;
ammo.setParent(null);
const ammoAggregate = new PhysicsAggregate(ammo, PhysicsShapeType.SPHERE, {
@@ -141,13 +140,48 @@ export class Ship {
})
}
- private setup() {
- this._ship = new TransformNode("ship", DefaultScene.MainScene);
+ public async initialize() {
+ this._scoreboard = new Scoreboard();
+ this._ship = new TransformNode("shipBawe", DefaultScene.MainScene);
+ //this._ship.rotation.y = Math.PI;
+ const data = await loadAsset('ship.glb');
+ const axes = new Debug.AxesViewer(DefaultScene.MainScene, 1);
+ //axes.xAxis.parent = data.container.rootNodes[0];
+ //axes.yAxis.parent = data.container.rootNodes[0];
+ axes.zAxis.parent = data.container.transformNodes[0];
+ //data.container.transformNodes[0].parent = this._ship;
+ this._ship = data.container.transformNodes[0];
+ this._ship.position.y = 5;
+
+ const config = GameConfig.getInstance();
+ if (config.physicsEnabled) {
+ console.log('Physics Enabled for Ship');
+ if (this._ship) {
+ const agg = new PhysicsAggregate(
+ this._ship,
+ PhysicsShapeType.MESH,
+ {
+ mass: 10,
+ mesh: data.container.rootNodes[0].getChildMeshes()[0] as Mesh
+ },
+ DefaultScene.MainScene
+ );
+
+ agg.body.setMotionType(PhysicsMotionType.DYNAMIC);
+ agg.body.setLinearDamping(.2);
+ agg.body.setAngularDamping(.4);
+ agg.body.setAngularVelocity(new Vector3(0, 0, 0));
+ agg.body.setCollisionCallbackEnabled(true);
+
+ } else {
+ console.warn("No geometry mesh found, cannot create physics");
+ }
+ }
+ //shipMesh.position.z = -1;
- // Create sounds asynchronously if audio engine is available
if (this._audioEngine) {
- this.initializeSounds();
+ await this.initializeSounds();
}
this._ammoMaterial = new StandardMaterial("ammoMaterial", DefaultScene.MainScene);
this._ammoMaterial.emissiveColor = new Color3(1, 1, 0);
@@ -158,8 +192,8 @@ export class Ship {
//const landingLight = new SpotLight("landingLight", new Vector3(0, 0, 0), new Vector3(0, -.5, .5), 1.5, .5, DefaultScene.MainScene);
- // landingLight.parent = this._ship;
- // landingLight.position.z = 5;
+ // landingLight.parent = this._ship;
+ // landingLight.position.z = 5;
// Physics will be set up after mesh loads in initialize()
@@ -171,11 +205,11 @@ export class Ship {
DefaultScene.MainScene);
this._camera.parent = this._ship;
- DefaultScene.MainScene.setActiveCameraByName("Flat Camera");
+ //DefaultScene.MainScene.setActiveCameraByName("Flat Camera");
// Create sight reticle
this._sight = new Sight(DefaultScene.MainScene, this._ship, {
- position: new Vector3(0, .5, 125),
+ position: new Vector3(0, .1, 125),
circleRadius: 2,
crosshairLength: 1.5,
lineThickness: 0.1,
@@ -183,78 +217,20 @@ export class Ship {
renderingGroupId: 3,
centerGap: 0.5
});
+ console.log(data.meshes.get('Screen'));
+ const screen = DefaultScene.MainScene.getMaterialById('Screen').getBindedMeshes()[0] as Mesh
+ console.log(screen);
+ const old = screen.parent;
+ screen.setParent(null);
+ screen.setPivotPoint(screen.getBoundingInfo().boundingSphere.center);
+ screen.setParent(old);
+ screen.rotation.y = Math.PI;
+ console.log(screen.rotation);
+ console.log(screen.scaling);
- }
+ this._scoreboard.initialize(screen);
- 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();
- if (config.physicsEnabled) {
- // Find the actual geometry mesh (usually meshes[1] or a child)
- //const geometryMesh = importMesh.meshes.find(m => m instanceof Mesh && m.getTotalVertices() > 0) as Mesh;
- const geo = shipMesh.getChildMeshes()[0]
- if (geo) {
-
-
- // Create physics aggregate on the ship TransformNode using the mesh shape
- const agg = new PhysicsAggregate(this._ship, PhysicsShapeType.CONVEX_HULL, {
- mass: 100,
- mesh: (geo as Mesh) // Use the actual ship geometry
- }, DefaultScene.MainScene);
-
-
- agg.body.setMotionType(PhysicsMotionType.DYNAMIC);
- agg.body.setLinearDamping(.2);
- agg.body.setAngularDamping(.3);
- agg.body.setAngularVelocity(new Vector3(0, 0, 0));
- agg.body.setCollisionCallbackEnabled(true);
- } else {
- console.warn("No geometry mesh found in ship1.glb, falling back to box shape");
- // Fallback to box shape if mesh not found
- const agg = new PhysicsAggregate(this._ship, PhysicsShapeType.BOX, {
- mass: 100,
- extents: new Vector3(4, 4, 7.4),
- center: new Vector3(0, 1, 1.8)
- }, DefaultScene.MainScene);
-
- agg.body.setMotionType(PhysicsMotionType.DYNAMIC);
- agg.body.setLinearDamping(.1);
- agg.body.setAngularDamping(.2);
- agg.body.setAngularVelocity(new Vector3(0, 0, 0));
- agg.body.setCollisionCallbackEnabled(true);
- }
- }
- //shipMesh.rotation.y = Angle.FromDegrees(90).radians();
- //shipMesh.rotation.y = Math.PI;
- //shipMesh.position.y = 1;
- shipMesh.position.z = -1;
- // shipMesh.renderingGroupId = 3;
- //const light = new PointLight("ship.light", new Vector3(0, .5, .1), DefaultScene.MainScene);
- //light.intensity = 4;
- /*light.includedOnlyMeshes = [shipMesh];
- for (const mesh of shipMesh.getChildMeshes()) {
- // mesh.renderingGroupId = 3;
- if (mesh.material.id.indexOf('glass') === -1) {
- light.includedOnlyMeshes.push(mesh);
- }
- }
- 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);
}
@@ -287,7 +263,8 @@ export class Ship {
// Transform to world space - TransformNode vectors are in local space!
const worldDirection = Vector3.TransformNormal(localDirection, this._ship.getWorldMatrix());
const force = worldDirection.scale(LINEAR_FORCE_MULTIPLIER);
- body.applyForce(force, this._ship.physicsBody.transformNode.absolutePosition);
+ const thrustPoint = Vector3.TransformCoordinates(this._ship.physicsBody.getMassProperties().centerOfMass.add(new Vector3(0,1,0)), this._ship.getWorldMatrix());
+ body.applyForce(force, thrustPoint);
}
@@ -318,9 +295,9 @@ export class Ship {
// Only apply torque if we haven't reached max angular velocity
if (currentAngularSpeed < MAX_ANGULAR_VELOCITY) {
- const yaw = this._leftStickVector.x;
- const pitch = -this._rightStickVector.y;
- const roll = -this._rightStickVector.x;
+ const yaw = -this._leftStickVector.x;
+ const pitch = this._rightStickVector.y;
+ const roll = this._rightStickVector.x;
// Create torque in local space, then transform to world space
const localTorque = new Vector3(pitch, yaw, roll).scale(ANGULAR_FORCE_MULTIPLIER);
diff --git a/src/starBase.ts b/src/starBase.ts
index 0e884fc..dc4d152 100644
--- a/src/starBase.ts
+++ b/src/starBase.ts
@@ -1,6 +1,6 @@
import {
AbstractMesh,
- HavokPlugin,
+ HavokPlugin, Mesh,
PhysicsAggregate,
PhysicsMotionType,
PhysicsShapeType,
@@ -17,13 +17,14 @@ import loadAsset from "./utils/loadAsset";
* @returns Promise resolving to the loaded star base mesh
*/
export default class StarBase {
- public static async buildStarBase(position: Vector3): Promise {
+ public static async buildStarBase(): Promise {
const config = GameConfig.getInstance();
const scene = DefaultScene.MainScene;
const importMeshes = await loadAsset('base.glb');
+
const baseMesh = importMeshes.meshes.get('Base');
const landingMesh = importMeshes.meshes.get('BaseLandingZone');
- clearParent(importMeshes.meshes, position);
+
if (config.physicsEnabled) {
@@ -38,14 +39,14 @@ export default class StarBase {
const landingAgg = new PhysicsAggregate(landingMesh, PhysicsShapeType.MESH);
landingAgg.body.setMotionType(PhysicsMotionType.ANIMATED);
- landingAgg.body.getCollisionObservable().add((collidedCollidedBody) => {
- console.log(collidedCollidedBody);
- });
+ /*landingAgg.body.getCollisionObservable().add((collidedCollidedBody) => {
+
+ });*/
landingAgg.shape.isTrigger = true;
- (DefaultScene.MainScene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin).onTriggerCollisionObservable.add((eventdata, eventState) => {
+ /*(DefaultScene.MainScene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin).onTriggerCollisionObservable.add((eventdata, eventState) => {
console.log(eventState);
console.log(eventdata);
- })
+ })*/
landingAgg.body.setCollisionCallbackEnabled(true);
}
//importMesh.rootNodes[0].dispose();
diff --git a/src/utils/loadAsset.ts b/src/utils/loadAsset.ts
index 83ae0c1..861d1e0 100644
--- a/src/utils/loadAsset.ts
+++ b/src/utils/loadAsset.ts
@@ -8,7 +8,12 @@ export type LoadedAsset = {
export default async function loadAsset(file: string, theme: string = "default"): Promise {
const container = await LoadAssetContainerAsync(`assets/themes/${theme}/models/${file}`, DefaultScene.MainScene);
const map: Map = new Map();
+ container.addAllToScene();
for (const mesh of container.rootNodes[0].getChildMeshes(false)) {
+ console.log(mesh.id, mesh);
+ //mesh.setParent(null);
+ //mesh.rotation.y = Math.PI /2;
+ //mesh.rotation.z = Math.PI;
map.set(mesh.id, mesh);
}
return {container: container, meshes: map};
diff --git a/themes/default/base.blend b/themes/default/base.blend
index 2e7c090..9909936 100644
Binary files a/themes/default/base.blend and b/themes/default/base.blend differ
diff --git a/themes/default/base.blend1 b/themes/default/base.blend1
new file mode 100644
index 0000000..2e7c090
Binary files /dev/null and b/themes/default/base.blend1 differ
diff --git a/themes/default/ship.blend b/themes/default/ship.blend
index 31d1d95..c48d5b6 100644
Binary files a/themes/default/ship.blend and b/themes/default/ship.blend differ
diff --git a/themes/default/ship.blend1 b/themes/default/ship.blend1
new file mode 100644
index 0000000..31d1d95
Binary files /dev/null and b/themes/default/ship.blend1 differ