All checks were successful
Build / build (push) Successful in 1m21s
Major Refactoring: - Extracted input handling, physics, audio, and weapons into separate modules - Reduced Ship class from 542 lines to 305 lines (44% reduction) - Ship now acts as coordinator between modular systems New Modules Created: - src/shipPhysics.ts - Pure force calculation and application logic - No external dependencies, fully testable in isolation - Handles linear/angular forces with velocity caps - Returns force magnitudes for audio feedback - src/keyboardInput.ts - Keyboard and mouse input handling - Combines both input methods in unified interface - Exposes observables for shoot and camera change events - Clean getInputState() API - src/controllerInput.ts - VR controller input handling - Maps WebXR controllers to input state - Handles thumbstick and button events - Observables for shooting and camera adjustments - src/shipAudio.ts - Audio management system - Manages thrust sounds (primary and secondary) - Weapon fire sounds - Dynamic volume based on force magnitudes - src/weaponSystem.ts - Projectile creation and lifecycle - Creates and manages ammo instances - Physics setup for projectiles - Auto-disposal timer Ship Class Changes: - Removed all input handling code (keyboard, mouse, VR) - Removed force calculation logic - Removed audio management code - Removed weapon creation code - Now wires up modular systems via observables - Maintains same external API (backward compatible) Material Improvements: - Updated planet materials to use emissive texture - Enhanced sun material with better color settings - Set planets to unlit mode for better performance Benefits: - Each system independently testable - Clear separation of concerns - Easier to maintain and extend - Better code organization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
110 lines
3.2 KiB
TypeScript
110 lines
3.2 KiB
TypeScript
import type { AudioEngineV2, StaticSound } from "@babylonjs/core";
|
|
|
|
/**
|
|
* Manages ship audio (thrust sounds and weapon fire)
|
|
*/
|
|
export class ShipAudio {
|
|
private _audioEngine: AudioEngineV2;
|
|
private _primaryThrustSound: StaticSound;
|
|
private _secondaryThrustSound: StaticSound;
|
|
private _weaponSound: StaticSound;
|
|
private _primaryThrustPlaying: boolean = false;
|
|
private _secondaryThrustPlaying: boolean = false;
|
|
|
|
constructor(audioEngine?: AudioEngineV2) {
|
|
this._audioEngine = audioEngine;
|
|
}
|
|
|
|
/**
|
|
* Initialize sound assets
|
|
*/
|
|
public async initialize(): Promise<void> {
|
|
if (!this._audioEngine) return;
|
|
|
|
this._primaryThrustSound = await this._audioEngine.createSoundAsync(
|
|
"thrust",
|
|
"/thrust5.mp3",
|
|
{
|
|
loop: true,
|
|
volume: 0.2,
|
|
}
|
|
);
|
|
|
|
this._secondaryThrustSound = await this._audioEngine.createSoundAsync(
|
|
"thrust2",
|
|
"/thrust5.mp3",
|
|
{
|
|
loop: true,
|
|
volume: 0.5,
|
|
}
|
|
);
|
|
|
|
this._weaponSound = await this._audioEngine.createSoundAsync(
|
|
"shot",
|
|
"/shot.mp3",
|
|
{
|
|
loop: false,
|
|
volume: 0.5,
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Update thrust audio based on current force magnitudes
|
|
* @param linearMagnitude - Forward/backward thrust magnitude (0-1)
|
|
* @param angularMagnitude - Rotation thrust magnitude (0-3)
|
|
*/
|
|
public updateThrustAudio(
|
|
linearMagnitude: number,
|
|
angularMagnitude: number
|
|
): void {
|
|
// Handle primary thrust sound (forward/backward movement)
|
|
if (linearMagnitude > 0) {
|
|
if (this._primaryThrustSound && !this._primaryThrustPlaying) {
|
|
this._primaryThrustSound.play();
|
|
this._primaryThrustPlaying = true;
|
|
}
|
|
if (this._primaryThrustSound) {
|
|
this._primaryThrustSound.volume = linearMagnitude;
|
|
}
|
|
} else {
|
|
if (this._primaryThrustSound && this._primaryThrustPlaying) {
|
|
this._primaryThrustSound.stop();
|
|
this._primaryThrustPlaying = false;
|
|
}
|
|
}
|
|
|
|
// Handle secondary thrust sound (rotation)
|
|
if (angularMagnitude > 0.1) {
|
|
if (this._secondaryThrustSound && !this._secondaryThrustPlaying) {
|
|
this._secondaryThrustSound.play();
|
|
this._secondaryThrustPlaying = true;
|
|
}
|
|
if (this._secondaryThrustSound) {
|
|
this._secondaryThrustSound.volume = angularMagnitude * 0.4;
|
|
}
|
|
} else {
|
|
if (this._secondaryThrustSound && this._secondaryThrustPlaying) {
|
|
this._secondaryThrustSound.stop();
|
|
this._secondaryThrustPlaying = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Play weapon fire sound
|
|
*/
|
|
public playWeaponSound(): void {
|
|
this._weaponSound?.play();
|
|
}
|
|
|
|
/**
|
|
* Cleanup audio resources
|
|
*/
|
|
public dispose(): void {
|
|
this._primaryThrustSound?.dispose();
|
|
this._secondaryThrustSound?.dispose();
|
|
this._weaponSound?.dispose();
|
|
}
|
|
}
|