Make ship physics constants configurable via GameConfig with UI
All checks were successful
Build / build (push) Successful in 1m14s
All checks were successful
Build / build (push) Successful in 1m14s
Implemented Option 5: Integrate ship physics constants into centralized GameConfig Changes to gameConfig.ts: - Added shipPhysics object with 4 tunable parameters: - maxLinearVelocity (default: 200) - maxAngularVelocity (default: 1.4) - linearForceMultiplier (default: 800) - angularForceMultiplier (default: 15) - Updated save() to persist shipPhysics to localStorage - Updated loadFromStorage() to load shipPhysics with fallback defaults - Updated reset() to restore shipPhysics defaults Changes to shipPhysics.ts: - Removed hardcoded constants - Added GameConfig import - Updated applyForces() to read values from GameConfig.getInstance().shipPhysics - Now reads physics parameters dynamically at runtime Changes to index.html: - Added Ship Physics section in Settings UI - 4 number inputs with appropriate min/max/step values - Help text explaining each parameter's effect on ship handling - Section positioned after Developer settings Changes to settingsScreen.ts: - Added input element references for ship physics controls - Updated loadSettings() to populate ship physics inputs from config - Updated saveSettings() to save ship physics values to config - Values persist across sessions via localStorage Benefits: - Ship physics now tunable in real-time via settings UI - Parameters persist across sessions - Easy to reset to defaults - Centralized configuration management - No need to edit code to adjust ship handling 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
72573054dd
commit
0988805652
40
index.html
40
index.html
@ -349,6 +349,46 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ship Physics Settings -->
|
||||
<div class="section">
|
||||
<h2>🚀 Ship Physics</h2>
|
||||
<p style="color: #aaa; font-size: 0.9em; margin-bottom: 20px;">
|
||||
Advanced tuning parameters for ship movement and handling. Adjust these to customize how the ship responds to controls.
|
||||
</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="maxLinearVelocity">Max Linear Velocity</label>
|
||||
<input type="number" id="maxLinearVelocity" value="200" step="10" min="50" max="1000">
|
||||
<div class="help-text">
|
||||
Maximum forward/backward speed of the ship. Higher values allow faster movement.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="maxAngularVelocity">Max Angular Velocity</label>
|
||||
<input type="number" id="maxAngularVelocity" value="1.4" step="0.1" min="0.5" max="5.0">
|
||||
<div class="help-text">
|
||||
Maximum rotation speed of the ship. Higher values allow faster turning.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="linearForceMultiplier">Linear Force Multiplier</label>
|
||||
<input type="number" id="linearForceMultiplier" value="800" step="50" min="100" max="3000">
|
||||
<div class="help-text">
|
||||
Acceleration power for forward/backward thrust. Higher values = faster acceleration.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="angularForceMultiplier">Angular Force Multiplier</label>
|
||||
<input type="number" id="angularForceMultiplier" value="15" step="1" min="5" max="50">
|
||||
<div class="help-text">
|
||||
Torque power for rotation. Higher values = faster rotational acceleration.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Section -->
|
||||
<div class="section">
|
||||
<h2>ℹ️ Quality Level Guide</h2>
|
||||
|
||||
@ -9,6 +9,14 @@ export class GameConfig {
|
||||
// Physics settings
|
||||
public physicsEnabled: boolean = true;
|
||||
|
||||
// Ship physics tuning parameters
|
||||
public shipPhysics = {
|
||||
maxLinearVelocity: 200,
|
||||
maxAngularVelocity: 1.4,
|
||||
linearForceMultiplier: 800,
|
||||
angularForceMultiplier: 15
|
||||
};
|
||||
|
||||
/**
|
||||
* Private constructor for singleton pattern
|
||||
*/
|
||||
@ -33,7 +41,8 @@ export class GameConfig {
|
||||
public save(): void {
|
||||
const config = {
|
||||
physicsEnabled: this.physicsEnabled,
|
||||
debug: this.debug
|
||||
debug: this.debug,
|
||||
shipPhysics: this.shipPhysics
|
||||
};
|
||||
localStorage.setItem('game-config', JSON.stringify(config));
|
||||
}
|
||||
@ -48,6 +57,16 @@ export class GameConfig {
|
||||
const config = JSON.parse(stored);
|
||||
this.physicsEnabled = config.physicsEnabled ?? true;
|
||||
this.debug = config.debug ?? false;
|
||||
|
||||
// Load ship physics with fallback to defaults
|
||||
if (config.shipPhysics) {
|
||||
this.shipPhysics = {
|
||||
maxLinearVelocity: config.shipPhysics.maxLinearVelocity ?? 200,
|
||||
maxAngularVelocity: config.shipPhysics.maxAngularVelocity ?? 1.4,
|
||||
linearForceMultiplier: config.shipPhysics.linearForceMultiplier ?? 800,
|
||||
angularForceMultiplier: config.shipPhysics.angularForceMultiplier ?? 15
|
||||
};
|
||||
}
|
||||
} else {
|
||||
this.save();
|
||||
}
|
||||
@ -62,6 +81,12 @@ export class GameConfig {
|
||||
public reset(): void {
|
||||
this.physicsEnabled = true;
|
||||
this.debug = false;
|
||||
this.shipPhysics = {
|
||||
maxLinearVelocity: 200,
|
||||
maxAngularVelocity: 1.4,
|
||||
linearForceMultiplier: 800,
|
||||
angularForceMultiplier: 15
|
||||
};
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,12 @@ export function initializeSettingsScreen(): void {
|
||||
const physicsEnabledCheckbox = document.getElementById('physicsEnabled') as HTMLInputElement;
|
||||
const debugEnabledCheckbox = document.getElementById('debugEnabled') as HTMLInputElement;
|
||||
|
||||
// Ship physics inputs
|
||||
const maxLinearVelocityInput = document.getElementById('maxLinearVelocity') as HTMLInputElement;
|
||||
const maxAngularVelocityInput = document.getElementById('maxAngularVelocity') as HTMLInputElement;
|
||||
const linearForceMultiplierInput = document.getElementById('linearForceMultiplier') as HTMLInputElement;
|
||||
const angularForceMultiplierInput = document.getElementById('angularForceMultiplier') as HTMLInputElement;
|
||||
|
||||
const saveBtn = document.getElementById('saveSettingsBtn');
|
||||
const resetBtn = document.getElementById('resetSettingsBtn');
|
||||
const messageDiv = document.getElementById('settingsMessage');
|
||||
@ -38,6 +44,12 @@ export function initializeSettingsScreen(): void {
|
||||
function loadSettings(): void {
|
||||
if (physicsEnabledCheckbox) physicsEnabledCheckbox.checked = config.physicsEnabled;
|
||||
if (debugEnabledCheckbox) debugEnabledCheckbox.checked = config.debug;
|
||||
|
||||
// Load ship physics settings
|
||||
if (maxLinearVelocityInput) maxLinearVelocityInput.value = config.shipPhysics.maxLinearVelocity.toString();
|
||||
if (maxAngularVelocityInput) maxAngularVelocityInput.value = config.shipPhysics.maxAngularVelocity.toString();
|
||||
if (linearForceMultiplierInput) linearForceMultiplierInput.value = config.shipPhysics.linearForceMultiplier.toString();
|
||||
if (angularForceMultiplierInput) angularForceMultiplierInput.value = config.shipPhysics.angularForceMultiplier.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,6 +58,13 @@ export function initializeSettingsScreen(): void {
|
||||
function saveSettings(): void {
|
||||
config.physicsEnabled = physicsEnabledCheckbox.checked;
|
||||
config.debug = debugEnabledCheckbox.checked;
|
||||
|
||||
// Save ship physics settings
|
||||
config.shipPhysics.maxLinearVelocity = parseFloat(maxLinearVelocityInput.value);
|
||||
config.shipPhysics.maxAngularVelocity = parseFloat(maxAngularVelocityInput.value);
|
||||
config.shipPhysics.linearForceMultiplier = parseFloat(linearForceMultiplierInput.value);
|
||||
config.shipPhysics.angularForceMultiplier = parseFloat(angularForceMultiplierInput.value);
|
||||
|
||||
config.save();
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
import { PhysicsBody, TransformNode, Vector2, Vector3 } from "@babylonjs/core";
|
||||
|
||||
// Physics constants
|
||||
const MAX_LINEAR_VELOCITY = 200;
|
||||
const MAX_ANGULAR_VELOCITY = 1.4;
|
||||
const LINEAR_FORCE_MULTIPLIER = 800;
|
||||
const ANGULAR_FORCE_MULTIPLIER = 15;
|
||||
import { GameConfig } from "./gameConfig";
|
||||
|
||||
export interface InputState {
|
||||
leftStick: Vector2;
|
||||
@ -18,7 +13,7 @@ export interface ForceApplicationResult {
|
||||
|
||||
/**
|
||||
* Handles physics force calculations and application for the ship
|
||||
* Pure calculation logic with no external dependencies
|
||||
* Reads physics parameters from GameConfig for runtime tuning
|
||||
*/
|
||||
export class ShipPhysics {
|
||||
/**
|
||||
@ -39,6 +34,9 @@ export class ShipPhysics {
|
||||
|
||||
const { leftStick, rightStick } = inputState;
|
||||
|
||||
// Get physics config
|
||||
const config = GameConfig.getInstance().shipPhysics;
|
||||
|
||||
// Get current velocities for velocity cap checks
|
||||
const currentLinearVelocity = physicsBody.getLinearVelocity();
|
||||
const currentAngularVelocity = physicsBody.getAngularVelocity();
|
||||
@ -52,7 +50,7 @@ export class ShipPhysics {
|
||||
linearMagnitude = Math.abs(leftStick.y);
|
||||
|
||||
// Only apply force if we haven't reached max velocity
|
||||
if (currentSpeed < MAX_LINEAR_VELOCITY) {
|
||||
if (currentSpeed < config.maxLinearVelocity) {
|
||||
// Get local direction (Z-axis for forward/backward thrust)
|
||||
const localDirection = new Vector3(0, 0, -leftStick.y);
|
||||
// Transform to world space
|
||||
@ -60,7 +58,7 @@ export class ShipPhysics {
|
||||
localDirection,
|
||||
transformNode.getWorldMatrix()
|
||||
);
|
||||
const force = worldDirection.scale(LINEAR_FORCE_MULTIPLIER);
|
||||
const force = worldDirection.scale(config.linearForceMultiplier);
|
||||
|
||||
// Calculate thrust point: center of mass + offset (0, 1, 0) in world space
|
||||
const thrustPoint = Vector3.TransformCoordinates(
|
||||
@ -83,14 +81,14 @@ export class ShipPhysics {
|
||||
const currentAngularSpeed = currentAngularVelocity.length();
|
||||
|
||||
// Only apply torque if we haven't reached max angular velocity
|
||||
if (currentAngularSpeed < MAX_ANGULAR_VELOCITY) {
|
||||
if (currentAngularSpeed < config.maxAngularVelocity) {
|
||||
const yaw = -leftStick.x;
|
||||
const pitch = rightStick.y;
|
||||
const roll = rightStick.x;
|
||||
|
||||
// Create torque in local space, then transform to world space
|
||||
const localTorque = new Vector3(pitch, yaw, roll).scale(
|
||||
ANGULAR_FORCE_MULTIPLIER
|
||||
config.angularForceMultiplier
|
||||
);
|
||||
const worldTorque = Vector3.TransformNormal(
|
||||
localTorque,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user