- Switch from svelte-spa-router to svelte-routing for clean URLs without hashes - Fix relative asset paths to absolute paths (prevents 404s on nested routes) - Fix physics engine disposal using scene.disablePhysicsEngine() - Fix Ship observer cleanup to prevent stale callbacks after level disposal - Add _gameplayStarted flag to prevent false game-end triggers during init - Add hasAsteroidsToDestroy check to prevent false victory on restart - Add RockFactory.reset() to properly reinitialize asteroid mesh between games - Add null safety checks throughout RockFactory for static properties 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
80 lines
3.0 KiB
TypeScript
80 lines
3.0 KiB
TypeScript
import {
|
|
AbstractMesh, Color3, GlowLayer,
|
|
MeshBuilder,
|
|
ParticleSystem,
|
|
StandardMaterial,
|
|
Texture,
|
|
TransformNode,
|
|
Vector3
|
|
} from "@babylonjs/core";
|
|
import {DefaultScene} from "../core/defaultScene";
|
|
|
|
type MainEngine = {
|
|
transformNode: TransformNode;
|
|
particleSystem: ParticleSystem;
|
|
}
|
|
export class ShipEngine {
|
|
private _ship: TransformNode;
|
|
private _leftMainEngine: MainEngine;
|
|
private _rightMainEngine: MainEngine;
|
|
|
|
constructor(ship: TransformNode) {
|
|
this._ship = ship;
|
|
this.initialize();
|
|
}
|
|
|
|
private initialize() {
|
|
|
|
this._leftMainEngine = this.createEngine(new Vector3(-.44, .37, -1.1));
|
|
this._rightMainEngine = this.createEngine(new Vector3(.44, .37, -1.1));
|
|
}
|
|
public idle() {
|
|
this._leftMainEngine.particleSystem.emitRate = 1;
|
|
this._rightMainEngine.particleSystem.emitRate = 1;
|
|
}
|
|
public forwardback(value: number) {
|
|
|
|
if (Math.sign(value) > 0) {
|
|
(this._leftMainEngine.particleSystem.emitter as AbstractMesh).rotation.y = 0;
|
|
(this._rightMainEngine.particleSystem.emitter as AbstractMesh).rotation.y = 0;
|
|
} else {
|
|
(this._leftMainEngine.particleSystem.emitter as AbstractMesh).rotation.y = Math.PI;
|
|
(this._rightMainEngine.particleSystem.emitter as AbstractMesh).rotation.y = Math.PI;
|
|
}
|
|
this._leftMainEngine.particleSystem.emitRate = Math.abs(value) * 10;
|
|
this._rightMainEngine.particleSystem.emitRate = Math.abs(value) * 10;
|
|
}
|
|
|
|
private createEngine(position: Vector3) : MainEngine{
|
|
const MAIN_ROTATION = Math.PI / 2;
|
|
const engine = new TransformNode("engine", DefaultScene.MainScene);
|
|
engine.parent = this._ship;
|
|
engine.position = position;
|
|
const leftDisc = MeshBuilder.CreateIcoSphere("engineSphere", {radius: .07}, DefaultScene.MainScene);
|
|
|
|
const material = new StandardMaterial("material", DefaultScene.MainScene);
|
|
material.emissiveColor = new Color3(.5, .5, .1);
|
|
leftDisc.material = material;
|
|
leftDisc.parent = engine;
|
|
leftDisc.rotation.x = MAIN_ROTATION;
|
|
const particleSystem = this.createParticleSystem(leftDisc);
|
|
return {transformNode: engine, particleSystem: particleSystem};
|
|
}
|
|
private createParticleSystem(mesh: AbstractMesh): ParticleSystem {
|
|
const myParticleSystem = new ParticleSystem("particles", 1000, DefaultScene.MainScene);
|
|
myParticleSystem.emitRate = 1;
|
|
//myParticleSystem.minEmitPower = 2;
|
|
//myParticleSystem.maxEmitPower = 10;
|
|
|
|
myParticleSystem.particleTexture = new Texture("/flare.png");
|
|
myParticleSystem.emitter = mesh;
|
|
const coneEmitter = myParticleSystem.createConeEmitter(0.1, Math.PI / 9);
|
|
myParticleSystem.addSizeGradient(0, .01);
|
|
myParticleSystem.addSizeGradient(1, .3);
|
|
myParticleSystem.isLocal = true;
|
|
|
|
myParticleSystem.start(); //S
|
|
return myParticleSystem;
|
|
|
|
}
|
|
} |