feat(game): Stellaris-style single-ship control with real flight physics
The player ship was never wired to its own movement systems — it lacked MaxSpeed/TurnRate (so steer_to_target skipped it) and the Player marker (so click-to-move skipped it). Only integrate_velocity matched, leaving the ship drifting on a hardcoded undock vector and ignoring all input. Left-click was also bound to camera drag, selection, and move at once, and "Approach" started a cosmetic timer that moved nothing. New control scheme (single ship, like Stellaris minus fleet selection): - Right-click issues a move order (was left-click, which conflicted with selection + camera drag). - Left-click cursor-selects the target under the cursor (was nearest-to-camera) and deselects on empty space. - "Approach" now actually flies to the selected target, homing onto it via ApproachTarget even as it orbits. - Smooth acceleration + stopping-distance arrival deceleration + turn-rate-limited banking replace instant velocity snapping. - A pulsing destination waypoint ring gives on-world move-order feedback. - Undock holds position (zero velocity + at-ship MoveTarget) instead of drifting off on a stale vector. - Follow-cam now allows free-look rotate/zoom so the player can find and click targets while the camera tracks the ship. Steering is shared: the player ship and AI ships use one physics model. AI spawn bundle gets the new required components (Acceleration, ArrivalRadius). Also fixes a B0001 panic in the destination-marker system: the marker query now carries Without<PlayerShip> so it is provably disjoint from the player Transform read. Includes the in-system action-panel rebuild-on-change optimization (buttons and their Interaction state persist between frames so clicks register), which the Approach/Dock flow depends on. Flight tuning lives in in_system/scene.rs (PLAYER_MAX_SPEED, PLAYER_ACCELERATION, PLAYER_TURN_RATE, PLAYER_ARRIVAL_RADIUS).
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
pub mod components;
|
||||
pub mod input;
|
||||
pub mod kinematic;
|
||||
@@ -9,18 +11,24 @@ pub struct MovementPlugin;
|
||||
|
||||
impl Plugin for MovementPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
// No state gating for slice 1: systems are no-ops when no Player exists.
|
||||
// When AppState::InGame is wired up, gate these on `in_state(AppState::InGame)`
|
||||
// and consider moving them to FixedUpdate for SpacetimeDB determinism.
|
||||
app.add_systems(
|
||||
Update,
|
||||
(
|
||||
input::click_to_move,
|
||||
kinematic::steer_to_target,
|
||||
kinematic::integrate_velocity,
|
||||
orbit::update_orbits,
|
||||
)
|
||||
.chain(),
|
||||
);
|
||||
app.add_event::<input::MoveOrderEvent>()
|
||||
// Orbital motion is scene-wide (used by the galaxy inspection scene
|
||||
// too), so it runs in every state.
|
||||
.add_systems(Update, orbit::update_orbits)
|
||||
// Flight steering chain: order → track approach → steer → integrate.
|
||||
// Gated to InGame — these only do something while entities with the
|
||||
// flight-physics components exist. Right-click input additionally
|
||||
// requires the player to be in flight, not docked.
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
input::right_click_to_move.run_if(input::when_in_flight),
|
||||
kinematic::track_approach_target,
|
||||
kinematic::steer_to_target,
|
||||
kinematic::integrate_velocity,
|
||||
)
|
||||
.chain()
|
||||
.run_if(in_state(AppState::InGame)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user