diff --git a/CONTROLLER_THRUST.md b/CONTROLLER_THRUST.md new file mode 100644 index 0000000..6f02cd3 --- /dev/null +++ b/CONTROLLER_THRUST.md @@ -0,0 +1,327 @@ +# Controller Thrust System Analysis + +## Overview + +The ship's thrust system uses VR controller thumbsticks to apply physics forces and torques to the ship. The system applies forces gradually up to a maximum velocity, providing momentum-based movement with velocity caps. + +## Control Mapping + +### Left Thumbstick +- **Y Axis (up/down)**: Linear thrust forward/backward +- **X Axis (left/right)**: Yaw rotation (turning left/right) + +### Right Thumbstick +- **Y Axis (up/down)**: Pitch rotation (nose up/down) +- **X Axis (left/right)**: Roll rotation (barrel roll) + +### Trigger +- Fires weapons + +--- + +## Constants & Configuration + +Located in `src/ship.ts:26-29`: + +```typescript +const MAX_LINEAR_VELOCITY = 80; // Maximum forward/backward speed +const MAX_ANGULAR_VELOCITY = 1.9; // Maximum rotation speed +const LINEAR_FORCE_MULTIPLIER = 600; // Thrust force strength +const ANGULAR_FORCE_MULTIPLIER = 18; // Torque strength +``` + +--- + +## Linear Thrust Implementation + +### Code Location +`src/ship.ts:321-366` - Inside `updateVelocity()` method + +### How It Works + +1. **Input Detection**: Checks if left stick Y axis has significant deflection (`> 0.01`) + +2. **Velocity Check**: Gets current speed from physics body + ```typescript + const currentSpeed = currentLinearVelocity.length(); + ``` + +3. **Force Calculation**: + ```typescript + const forceDirection = this._ship.forward.scale(-this._leftStickVector.y); + const force = forceDirection.scale(LINEAR_FORCE_MULTIPLIER); + ``` + +4. **Force Application**: Only applies force if below max velocity + ```typescript + if (currentSpeed < MAX_LINEAR_VELOCITY) { + body.applyForce(force, this._ship.absolutePosition); + } + ``` + +5. **Velocity Clamping**: After force application, clamps total velocity + ```typescript + if (currentSpeed > MAX_LINEAR_VELOCITY) { + const clampedVelocity = currentLinearVelocity.normalize().scale(MAX_LINEAR_VELOCITY); + body.setLinearVelocity(clampedVelocity); + } + ``` + +### Key Assumptions About Babylon.js APIs + +#### ✅ VERIFIED from code and user confirmation: +- `this._ship.forward` returns a unit vector in **local space** (NOT world space) +- `body.getLinearVelocity()` returns current velocity vector in world space +- `body.applyForce(force, position)` applies force at a point (standard physics API) +- `body.applyForce()` expects forces in **world space** coordinates + +#### ⚠️ ASSUMED (not verified from documentation): +- `this._ship.absolutePosition` is the correct point to apply force for center-of-mass thrust + +### Current Issues + +**CRITICAL PROBLEM #1**: `this._ship.forward` returns a vector in **local space**, but `body.applyForce()` expects **world space** coordinates. The local direction vector must be transformed to world space before applying force. + +**What's happening**: +- `this._ship.forward` = Local -Z axis vector (NOT in world space) +- This local vector is passed directly to `applyForce()` which expects world space +- Force is applied incorrectly because of coordinate space mismatch + +**What's needed**: +- Use Z-axis for forward/backward thrust (matches bullet direction) +- Transform local direction to world space using `Vector3.TransformNormal(localDir, this._ship.getWorldMatrix())` + +--- + +## Angular Thrust Implementation + +### Code Location +`src/ship.ts:368-440` - Inside `updateVelocity()` method + +### How It Works + +1. **Input Collection**: + ```typescript + const yaw = this._leftStickVector.x; // Left stick X + const pitch = -this._rightStickVector.y; // Right stick Y (inverted) + const roll = -this._rightStickVector.x; // Right stick X (inverted) + ``` + +2. **Torque Calculation**: + ```typescript + const torque = new Vector3(pitch, yaw, roll).scale(ANGULAR_FORCE_MULTIPLIER); + ``` + +3. **Apply Angular Impulse**: + ```typescript + body.applyAngularImpulse(torque); + ``` + +4. **Angular Velocity Clamping**: + ```typescript + if (currentAngularSpeed > MAX_ANGULAR_VELOCITY) { + const clampedAngularVelocity = currentAngularVelocity.normalize().scale(MAX_ANGULAR_VELOCITY); + body.setAngularVelocity(clampedAngularVelocity); + } + ``` + +### Key Assumptions About Babylon.js APIs + +#### ✅ VERIFIED from code: +- Angular impulse is applied every frame based on stick input +- Angular velocity is clamped to maximum rotation speed + +#### ⚠️ ASSUMED (not verified): +- `body.applyAngularImpulse(torque)` expects torque vector in **world space** coordinates +- The torque vector components `(X, Y, Z)` directly map to rotation around world axes +- Angular impulse accumulates with existing angular velocity + +### Current Issues + +**CRITICAL PROBLEM**: The torque is being constructed as a simple vector `(pitch, yaw, roll)` in what appears to be local space, but `body.applyAngularImpulse()` expects **world space** coordinates. + +**What's happening**: +- Torque = `Vector3(pitch, yaw, roll)` - intended as local space rotations +- Passed directly to `applyAngularImpulse()` which expects world space +- Ship rotates around wrong axes because of coordinate space mismatch + +**What's needed**: +- Define torque in local space: X=pitch, Y=yaw, Z=roll +- Transform to world space before applying +- Pitch: Rotation around ship's local X-axis (right vector) +- Yaw: Rotation around ship's local Y-axis (up vector) +- Roll: Rotation around ship's local Z-axis (forward vector) + +**Required Fix**: Transform the torque from local space to world space: +```typescript +const localTorque = new Vector3(pitch, yaw, roll).scale(ANGULAR_FORCE_MULTIPLIER); +const worldTorque = Vector3.TransformNormal(localTorque, this._ship.getWorldMatrix()); +body.applyAngularImpulse(worldTorque); +``` + +--- + +## Debug Visualization + +### Activation +- Press `d` key to toggle debug mode (currently defaults to ON) +- Debug lines are drawn in rendering group 3 (always on top) + +### Visual Indicators + +**Linear Force** (Yellow line): +- Drawn from camera position +- Shows direction and magnitude of thrust force +- Only visible when applying forward/backward thrust + +**Angular Forces**: +- **Red line**: Pitch torque around ship's right axis (X) +- **Green line**: Yaw torque around ship's up axis (Y) +- **Blue line**: Roll torque around ship's forward axis (Z) + +### Debug Visualization Code Location +`src/ship.ts:221-232` - `drawDebugVector()` method + +### How Debug Lines Are Positioned + +```typescript +const cameraPos = this._camera.globalPosition.clone(); +const cameraForward = this._camera.getFrontPosition(1); +const start = cameraPos.add(cameraForward.scale(1)).add(offset); +``` + +#### ⚠️ ASSUMPTION: +- `this._camera.getFrontPosition(1)` returns a position 1 unit in front of camera +- This is not a standard Babylon.js API method (expected `getDirection()` instead) +- May be causing debug lines to not render correctly + +--- + +## Physics Body Properties + +The ship physics body is configured with: + +```typescript +mass: 100 +linearDamping: 0.1 // Causes gradual velocity decay +angularDamping: 0.2 // Causes gradual rotation decay +motionType: DYNAMIC // Affected by forces and gravity (if enabled) +``` + +### How Damping Affects Movement + +**Linear Damping (0.1)**: +- When no thrust is applied, ship gradually slows down +- 10% velocity reduction per physics step (approximate) +- Creates "drag in space" effect + +**Angular Damping (0.2)**: +- When no rotation input, ship gradually stops spinning +- 20% angular velocity reduction per physics step (approximate) +- Prevents indefinite spinning + +--- + +## Expected Behavior vs Current Implementation + +### Linear Thrust + +| Expected | Current Implementation | Status | +|----------|----------------------|--------| +| Thrust along local Z-axis | Thrust along local Z-axis (forward) | ✅ **CORRECT** | +| Gradual acceleration | ✅ Applies force up to max velocity | ✅ Correct | +| Velocity clamping | ✅ Clamps to MAX_LINEAR_VELOCITY | ✅ Correct | +| World-space force | ✅ Transforms to world space | ✅ **CORRECT** | + +### Angular Thrust + +| Expected | Current Implementation | Status | +|----------|----------------------|--------| +| Rotation around local axes | ✅ Transforms to world space | ✅ **CORRECT** | +| Torque transformation | ✅ Uses Vector3.TransformNormal | ✅ **CORRECT** | +| Velocity clamping | ✅ Clamps angular velocity | ✅ Correct | + +--- + +## Audio Feedback + +### Primary Thrust Sound +- Triggered when left stick Y > 0.1 +- Volume scales with stick deflection +- Looping thrust sound + +### Secondary Thrust Sound +- Triggered when any rotation input detected +- Volume scales with combined rotation input magnitude +- Looping thrust sound + +--- + +## Recommended Fixes + +### 1. Fix Linear Thrust Direction and Coordinate Space ✅ FIXED +**Changed** from: +```typescript +const forceDirection = this._ship.forward.scale(-this._leftStickVector.y); +const force = forceDirection.scale(LINEAR_FORCE_MULTIPLIER); +``` + +To: +```typescript +// Get local direction (Z-axis for forward/backward thrust) +const localDirection = new Vector3(0, 0, -this._leftStickVector.y); +// Transform to world space +const worldDirection = Vector3.TransformNormal(localDirection, this._ship.getWorldMatrix()); +const force = worldDirection.scale(LINEAR_FORCE_MULTIPLIER); +``` + +### 2. Fix Angular Thrust Coordinate Space +**Change lines 382-383** from: +```typescript +const torque = new Vector3(pitch, yaw, roll).scale(ANGULAR_FORCE_MULTIPLIER); +body.applyAngularImpulse(torque); +``` + +To: +```typescript +const localTorque = new Vector3(pitch, yaw, roll).scale(ANGULAR_FORCE_MULTIPLIER); +const worldTorque = Vector3.TransformNormal(localTorque, this._ship.getWorldMatrix()); +body.applyAngularImpulse(worldTorque); +``` + +### 3. Fix Debug Visualization Camera Method +**Change line 224** from: +```typescript +const cameraForward = this._camera.getFrontPosition(1); +``` + +To: +```typescript +const cameraForward = this._camera.getDirection(Vector3.Forward()); +``` + +--- + +## Open Questions + +1. **Force Application Point**: Is `this._ship.absolutePosition` the center of mass, or should force be applied at a specific offset? + +2. **Coordinate System Convention**: What is the ship's default orientation in local space? + - Is +Y up, +Z forward, +X right? (Standard) + - Or does the ship model use a different convention? + +3. **Angular Impulse vs Torque**: Should we use `applyAngularImpulse()` or a continuous torque application method? + +4. **Velocity Check Logic**: Currently checks total speed before applying force. Should we instead check velocity component in the thrust direction? + +--- + +## Testing Recommendations + +With debug mode enabled, verify: + +1. **Yellow thrust line** points in intended thrust direction when moving stick +2. **Red/Green/Blue rotation lines** show rotation axes correctly aligned with ship orientation +3. Ship accelerates smoothly without hitting velocity cap too quickly +4. Ship rotates around its own axes, not around world axes +5. Damping brings ship to rest when sticks are released diff --git a/public/ship2.glb b/public/ship2.glb new file mode 100644 index 0000000..b61d626 Binary files /dev/null and b/public/ship2.glb differ diff --git a/src/backgroundStars.ts b/src/backgroundStars.ts index 4bde1f2..6410e41 100644 --- a/src/backgroundStars.ts +++ b/src/backgroundStars.ts @@ -103,7 +103,7 @@ export class BackgroundStars { mat.disableDepthWrite = true; // Stars should be in the background - mesh.renderingGroupId = 0; + // mesh.renderingGroupId = 0; // Make stars always render behind everything else mesh.isPickable = false; diff --git a/src/explosionManager.ts b/src/explosionManager.ts index ae31ff2..9a03d4e 100644 --- a/src/explosionManager.ts +++ b/src/explosionManager.ts @@ -213,13 +213,13 @@ export class ExplosionManager { maxForce: this.config.explosionForce }); - // Animate the explosion by calling explode() each frame with increasing values + // Animate the explosion using Babylon's render loop instead of requestAnimationFrame const startTime = Date.now(); const animationDuration = this.config.duration; const maxForce = this.config.explosionForce; let frameCount = 0; - const animate = () => { + const animationObserver = this.scene.onBeforeRenderObservable.add(() => { const elapsed = Date.now() - startTime; const progress = Math.min(elapsed / animationDuration, 1.0); @@ -254,18 +254,16 @@ export class ExplosionManager { } // Continue animation if not complete - if (progress < 1.0) { - requestAnimationFrame(animate); - } else { - // Animation complete - clean up + if (progress >= 1.0) { + // Animation complete - remove observer and clean up console.log(`[ExplosionManager] Animation complete after ${frameCount} frames, cleaning up`); + this.scene.onBeforeRenderObservable.remove(animationObserver); this.cleanupExplosion(meshPieces); } - }; + }); - // Start the animation + // Log that animation loop is registered console.log('[ExplosionManager] Starting animation loop...'); - animate(); } catch (error) { console.error('[ExplosionManager] ERROR creating MeshExploder:', error); // Clean up pieces if exploder failed diff --git a/src/level1.ts b/src/level1.ts index e443565..9935e1b 100644 --- a/src/level1.ts +++ b/src/level1.ts @@ -38,7 +38,7 @@ export class Level1 implements Level { this._levelConfig = levelConfig; this._audioEngine = audioEngine; this._deserializer = new LevelDeserializer(levelConfig); - this._ship = new Ship(undefined, audioEngine); + this._ship = new Ship(audioEngine); this._scoreboard = new Scoreboard(); const xr = DefaultScene.XR; diff --git a/src/scoreboard.ts b/src/scoreboard.ts index 515f7d7..b994c71 100644 --- a/src/scoreboard.ts +++ b/src/scoreboard.ts @@ -39,7 +39,7 @@ export class Scoreboard { console.log('Scoreboard parent:', parent); console.log('Initializing scoreboard'); const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene); - scoreboard.renderingGroupId = 3; + // scoreboard.renderingGroupId = 3; const material = new StandardMaterial("scoreboard", scene); scoreboard.parent =parent; diff --git a/src/ship.ts b/src/ship.ts index 2d9021a..a5ef201 100644 --- a/src/ship.ts +++ b/src/ship.ts @@ -1,16 +1,14 @@ import { - AbstractMesh, Angle, + AbstractMesh, Color3, - DirectionalLight, FreeCamera, - GlowLayer, InstancedMesh, Mesh, + InstancedMesh, Mesh, MeshBuilder, Observable, PhysicsAggregate, PhysicsMotionType, PhysicsShapeType, PointLight, SceneLoader, - SpotLight, StandardMaterial, TransformNode, Vector2, @@ -23,7 +21,10 @@ import type {AudioEngineV2, StaticSound} from "@babylonjs/core"; import {DefaultScene} from "./defaultScene"; import { GameConfig } from "./gameConfig"; import { Sight } from "./sight"; -const MAX_FORWARD_THRUST = 40; +const MAX_LINEAR_VELOCITY = 80; +const MAX_ANGULAR_VELOCITY = 1.8; +const LINEAR_FORCE_MULTIPLIER = 800; +const ANGULAR_FORCE_MULTIPLIER = 20; const controllerComponents = [ 'a-button', @@ -47,18 +48,11 @@ type ControllerEvent = { } -enum ControllerStickMode { - BEGINNER, - ARCADE, - REALISTIC -} export class Ship { private _ship: TransformNode; private _controllerObservable: Observable = new Observable(); private _ammoMaterial: StandardMaterial; - private _forwardNode: TransformNode; - private _rotationNode: TransformNode; private _primaryThrustVectorSound: StaticSound; private _secondaryThrustVectorSound: StaticSound; private _shot: StaticSound; @@ -67,19 +61,14 @@ export class Ship { private _shooting: boolean = false; private _camera: FreeCamera; private _ammoBaseMesh: AbstractMesh; - private _controllerMode: ControllerStickMode; - private _active = false; private _audioEngine: AudioEngineV2; private _sight: Sight; - constructor(mode: ControllerStickMode = ControllerStickMode.BEGINNER, audioEngine?: AudioEngineV2) { - this._controllerMode = mode; + + constructor( audioEngine?: AudioEngineV2) { this._audioEngine = audioEngine; this.setup(); this.initialize(); } - public set controllerMode(mode: ControllerStickMode) { - this._controllerMode = mode; - } private async initializeSounds() { if (!this._audioEngine) return; @@ -171,10 +160,6 @@ export class Ship { this.setupKeyboard(); this.setupMouse(); this._controllerObservable.add(this.controllerCallback); - this._forwardNode = new TransformNode("forward", DefaultScene.MainScene); - this._rotationNode = new TransformNode("rotation", DefaultScene.MainScene); - this._forwardNode.parent = this._ship; - this._rotationNode.parent = this._ship; this._camera = new FreeCamera("Flat Camera", new Vector3(0, .5, 0), DefaultScene.MainScene); @@ -193,17 +178,11 @@ export class Ship { centerGap: 0.5 }); - let i = 0; - DefaultScene.MainScene.onBeforeRenderObservable.add(() => { - if (i++ % 10 == 0) { - this.applyForce(); - } - }); - - this._active = true; } + + private async initialize() { - const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "ship1.glb", DefaultScene.MainScene); + const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "ship2.glb", DefaultScene.MainScene); const shipMesh = importMesh.meshes[0]; shipMesh.id = "shipMesh"; shipMesh.name = "shipMesh"; @@ -224,9 +203,10 @@ export class Ship { mesh: (geo as Mesh) // Use the actual ship geometry }, DefaultScene.MainScene); + agg.body.setMotionType(PhysicsMotionType.DYNAMIC); - agg.body.setLinearDamping(.1); - agg.body.setAngularDamping(.2); + agg.body.setLinearDamping(.2); + agg.body.setAngularDamping(.3); agg.body.setAngularVelocity(new Vector3(0, 0, 0)); agg.body.setCollisionCallbackEnabled(true); } else { @@ -249,12 +229,12 @@ export class Ship { //shipMesh.rotation.y = Math.PI; //shipMesh.position.y = 1; shipMesh.position.z = -1; - shipMesh.renderingGroupId = 3; + // 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; + // mesh.renderingGroupId = 3; if (mesh.material.id.indexOf('glass') === -1) { light.includedOnlyMeshes.push(mesh); } @@ -266,10 +246,6 @@ export class Ship { private _leftStickVector = Vector2.Zero().clone(); private _rightStickVector = Vector2.Zero().clone(); - private _forwardValue = 0; - private _yawValue = 0; - private _rollValue = 0; - private _pitchValue = 0; private _mouseDown = false; private _mousePos = new Vector2(0, 0); @@ -277,74 +253,91 @@ export class Ship { return this._ship; } - - private applyForce() { + private applyForces() { if (!this?._ship?.physicsBody) { return; } const body = this._ship.physicsBody; - //If we're moving over MAX_FORWARD_THRUST, we can't add any more thrust, - //just continue at MAX_FORWARD_THRUST - if (Math.abs(this._forwardValue) > MAX_FORWARD_THRUST) { - this._forwardValue = Math.sign(this._forwardValue) * MAX_FORWARD_THRUST; - } - //if forward thrust is under 40 we can apply more thrust - if (Math.abs(this._forwardValue) <= MAX_FORWARD_THRUST) { - if (Math.abs(this._leftStickVector.y) > .1) { - if (this._primaryThrustVectorSound && !this._primaryThrustPlaying) { - this._primaryThrustVectorSound.play(); - this._primaryThrustPlaying = true; - } - if (this._primaryThrustVectorSound) { - this._primaryThrustVectorSound.volume = Math.abs(this._leftStickVector.y); - } - this._forwardValue += this._leftStickVector.y * .8; - } else { - if (this._primaryThrustVectorSound && this._primaryThrustPlaying) { - this._primaryThrustVectorSound.stop(); - this._primaryThrustPlaying = false; - } - this._forwardValue = decrementValue(this._forwardValue, .98); + // Get current velocities for velocity cap checks + const currentLinearVelocity = body.getLinearVelocity(); + const currentAngularVelocity = body.getAngularVelocity(); + const currentSpeed = currentLinearVelocity.length(); + + // Apply linear force from left stick Y (forward/backward) + if (Math.abs(this._leftStickVector.y) > .1) { + // Only apply force if we haven't reached max velocity + if (currentSpeed < MAX_LINEAR_VELOCITY) { + // Get local direction (Z-axis for forward/backward thrust) + const localDirection = new Vector3(0, 0, -this._leftStickVector.y); + // 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); + + } + + // Handle primary thrust sound + if (this._primaryThrustVectorSound && !this._primaryThrustPlaying) { + this._primaryThrustVectorSound.play(); + this._primaryThrustPlaying = true; + } + if (this._primaryThrustVectorSound) { + this._primaryThrustVectorSound.volume = Math.abs(this._leftStickVector.y); + } + } else { + // Stop thrust sound when no input + if (this._primaryThrustVectorSound && this._primaryThrustPlaying) { + this._primaryThrustVectorSound.stop(); + this._primaryThrustPlaying = false; } } - this._yawValue = adjustStickValue(this._leftStickVector.x, this._yawValue); - this._rollValue = adjustStickValue(this._rightStickVector.x, this._rollValue); - this._pitchValue = adjustStickValue(this._rightStickVector.y, this._pitchValue); - - this._forwardNode.position.z = this._forwardValue; - this._rotationNode.position.y = this._yawValue; - this._rotationNode.position.z = -this._rollValue; - this._rotationNode.position.x = -this._pitchValue; - - const thrust2 = Math.abs(this._rightStickVector.y) + + // Calculate rotation magnitude for torque and sound + const rotationMagnitude = Math.abs(this._rightStickVector.y) + Math.abs(this._rightStickVector.x) + Math.abs(this._leftStickVector.x); - if (thrust2 > .01) { + // Apply angular forces if any stick has significant rotation input + if (rotationMagnitude > .1) { + const currentAngularSpeed = currentAngularVelocity.length(); + + // 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; + + // Create torque in local space, then transform to world space + const localTorque = new Vector3(pitch, yaw, roll).scale(ANGULAR_FORCE_MULTIPLIER); + const worldTorque = Vector3.TransformNormal(localTorque, this._ship.getWorldMatrix()); + + body.applyAngularImpulse(worldTorque); + + // Debug visualization for angular forces + } + + // Handle secondary thrust sound for rotation if (this._secondaryThrustVectorSound && !this._secondaryThrustPlaying) { this._secondaryThrustVectorSound.play(); this._secondaryThrustPlaying = true; } if (this._secondaryThrustVectorSound) { - this._secondaryThrustVectorSound.volume = thrust2 * .4; + this._secondaryThrustVectorSound.volume = rotationMagnitude * .4; } } else { + // Stop rotation thrust sound when no input if (this._secondaryThrustVectorSound && this._secondaryThrustPlaying) { this._secondaryThrustVectorSound.stop(); this._secondaryThrustPlaying = false; } - } - body.setAngularVelocity(this._rotationNode.absolutePosition.subtract(this._ship.absolutePosition)); - body.setLinearVelocity(this._forwardNode.absolutePosition.subtract(this._ship.absolutePosition).scale(-1)); } + private controllerCallback = (controllerEvent: ControllerEvent) => { // Log first few events to verify they're firing - if (controllerEvent.type == 'thumbstick') { if (controllerEvent.hand == 'left') { this._leftStickVector.x = controllerEvent.axisData.x; @@ -354,9 +347,8 @@ export class Ship { if (controllerEvent.hand == 'right') { this._rightStickVector.x = controllerEvent.axisData.x; this._rightStickVector.y = controllerEvent.axisData.y; - } - this.applyForce(); + this.applyForces(); } if (controllerEvent.type == 'button') { if (controllerEvent.component.type == 'trigger') { @@ -401,6 +393,7 @@ export class Ship { } else { this._rightStickVector.y = Math.sign(yInc); } + this.applyForces(); }; } @@ -443,6 +436,7 @@ export class Ship { break; } + this.applyForces(); }; } @@ -534,21 +528,7 @@ export class Ship { if (this._sight) { this._sight.dispose(); } + // Add other cleanup as needed } } -function decrementValue(value: number, increment: number = .8): number { - if (Math.abs(value) < .01) { - return 0; - } else { - return value * increment; - } -} - -function adjustStickValue(stickVector: number, thrustValue: number): number { - if (Math.abs(stickVector) > .03) { - return thrustValue + (Math.pow(stickVector, 3) * .1); - } else { - return decrementValue(thrustValue, .85); - } -} diff --git a/src/sight.ts b/src/sight.ts index 412d77d..c51d924 100644 --- a/src/sight.ts +++ b/src/sight.ts @@ -79,7 +79,7 @@ export class Sight { }, this.scene); this.circle.parent = this.reticleGroup; 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); @@ -102,7 +102,7 @@ export class Sight { topLine.parent = this.reticleGroup; topLine.position.y = gap + length / 2; topLine.material = material; - topLine.renderingGroupId = this.config.renderingGroupId; + // topLine.renderingGroupId = this.config.renderingGroupId; this.crosshairLines.push(topLine); // Bottom line @@ -114,7 +114,7 @@ export class Sight { bottomLine.parent = this.reticleGroup; bottomLine.position.y = -(gap + length / 2); bottomLine.material = material; - bottomLine.renderingGroupId = this.config.renderingGroupId; + // bottomLine.renderingGroupId = this.config.renderingGroupId; this.crosshairLines.push(bottomLine); // Left line @@ -126,7 +126,7 @@ export class Sight { leftLine.parent = this.reticleGroup; leftLine.position.x = -(gap + length / 2); leftLine.material = material; - leftLine.renderingGroupId = this.config.renderingGroupId; + // leftLine.renderingGroupId = this.config.renderingGroupId; this.crosshairLines.push(leftLine); // Right line @@ -138,7 +138,7 @@ export class Sight { rightLine.parent = this.reticleGroup; rightLine.position.x = gap + length / 2; rightLine.material = material; - rightLine.renderingGroupId = this.config.renderingGroupId; + // rightLine.renderingGroupId = this.config.renderingGroupId; this.crosshairLines.push(rightLine); // Center dot (optional, very small) @@ -147,7 +147,7 @@ export class Sight { }, this.scene); centerDot.parent = this.reticleGroup; centerDot.material = material; - centerDot.renderingGroupId = this.config.renderingGroupId; + // centerDot.renderingGroupId = this.config.renderingGroupId; this.crosshairLines.push(centerDot); } diff --git a/src/testLevel.ts b/src/testLevel.ts index 1d650a5..b39f9d0 100644 --- a/src/testLevel.ts +++ b/src/testLevel.ts @@ -157,7 +157,6 @@ export class TestLevel implements Level { public async initialize() { console.log('[TestLevel] initialize() called'); console.log('[TestLevel] Scene info:', { - name: DefaultScene.MainScene.name, meshCount: DefaultScene.MainScene.meshes.length, lightCount: DefaultScene.MainScene.lights.length });