implement update_matching_velocity_target()

This commit is contained in:
yuni 2024-11-30 02:49:12 +01:00
parent cde59dcdd0
commit 67703072d7
4 changed files with 92 additions and 6 deletions

View file

@ -79,6 +79,7 @@ impl Plugin for ActorPlugin {
handle_input.run_if(in_control).run_if(game_running),
handle_collisions.run_if(game_running),
handle_damage.run_if(game_running),
update_matching_velocity_target.run_if(game_running),
),
);
app.add_systems(
@ -86,6 +87,10 @@ impl Plugin for ActorPlugin {
(handle_vehicle_enter_exit.run_if(game_running),),
);
app.add_event::<VehicleEnterExitEvent>();
app.insert_resource(MatchingVelocityTargetUpdateTimer(Timer::from_seconds(
0.25,
TimerMode::Repeating,
)));
}
}
@ -173,11 +178,13 @@ impl Default for ExperiencesGForce {
}
#[derive(Component, Default)]
pub struct MatchingVelocity {
pub struct MatchingVelocityTarget {
pub entity: Option<Entity>,
pub pos: Option<DVec3>,
pub v: DVec3,
}
#[derive(Resource)]
pub struct MatchingVelocityTargetUpdateTimer(Timer);
#[derive(Component, Default)]
pub struct WantsAcceleration {
@ -1221,3 +1228,80 @@ fn handle_atmosphere(
settings.atmo_drag = None;
}
}
pub fn update_matching_velocity_target(
time: Res<Time>,
mut timer: ResMut<MatchingVelocityTargetUpdateTimer>,
jupiter_pos: Res<game::JupiterPos>,
mut q_actor: Query<
(
Entity,
&Transform,
&Position,
&mut LinearVelocity,
Option<&mut MatchingVelocityTarget>,
Option<&WantsAcceleration>,
Option<&hud::IsTargeted>,
Option<&PlayerCamera>,
),
(Without<visual::IsEffect>, Without<HiddenInsideVehicle>),
>,
) {
if timer.0.tick(time.delta()).just_finished() {
return;
}
let mut closest_map: HashMap<Entity, DVec3> = HashMap::new();
for (entity, _, pos, _, matching, _, _, is_player) in &q_actor {
// We only care about entities that ever need to match their velocity
if matching.is_none() {
continue;
}
let mut target_v: Option<DVec3> = None;
// First, if this is the player, check whether they targeted anything
// so we can match velocity to the target.
if is_player.is_some() {
for (_, _, _, v, _, _, is_target, _) in &q_actor {
if is_target.is_some() {
target_v = Some(v.0);
break;
}
}
}
// If not, simply look for the closest object and match velocity to that.
if target_v.is_none() {
let mut closest_distance = camera::MAX_DIST_FOR_MATCH_VELOCITY;
for (testentity, _, testpos, v, _, _, _, _) in &q_actor {
if entity != testentity {
let distance = (pos.0 - testpos.0).length();
if distance < closest_distance {
target_v = Some(v.0);
closest_distance = distance;
}
}
}
}
// Last resort: Match velocity to the orbital velocity around Jupiter
if target_v.is_none() {
let relative_pos = pos.0 - jupiter_pos.0;
target_v = Some(nature::orbital_velocity(relative_pos, nature::JUPITER_MASS));
}
if let Some(target_v) = target_v {
closest_map.insert(entity, target_v);
}
}
for (entity, _, _, _, matching, _, _, _) in &mut q_actor {
if let Some(mut matching) = matching {
if let Some(target_v) = closest_map.get(&entity) {
matching.v = *target_v;
}
}
}
}

View file

@ -1513,7 +1513,7 @@ fn spawn_entities(
actor.insert(actor::ExperiencesAtmosphere);
}
if state.is_player || state.is_vehicle {
actor.insert(MatchingVelocity::default());
actor.insert(MatchingVelocityTarget::default());
// previously used to apply mouse movement to actor rotation, but currently unused
actor.insert(ExternalTorque::ZERO.with_persistence(false));
}

View file

@ -1338,7 +1338,10 @@ fn update_target_selectagon(
fn update_motion_marker(
settings: Res<Settings>,
q_player: Query<(&Transform, &LinearVelocity, &MatchingVelocity), With<actor::PlayerCamera>>,
q_player: Query<
(&Transform, &LinearVelocity, &MatchingVelocityTarget),
With<actor::PlayerCamera>,
>,
mut q_retrograde: Query<
(&mut Transform, &mut Visibility),
(With<MarkerMotionRetrograde>, Without<actor::PlayerCamera>),
@ -1350,8 +1353,7 @@ fn update_motion_marker(
let dv = player_v.0 - player_mv.v;
if dv.length() > 1.0 {
*vis = Visibility::Inherited;
trans.translation =
player_trans.translation - (dv.as_vec3().normalize() * 2.0);
trans.translation = player_trans.translation - (dv.as_vec3().normalize() * 2.0);
trans.look_at(player_trans.translation, player_trans.up());
} else {
*vis = Visibility::Hidden;

View file

@ -34,7 +34,7 @@ pub mod prelude {
pub use crate::{
actor, audio, camera, chat, cmd, common, game, hud, load, menu, nature, var, visual, world,
};
pub use actor::MatchingVelocity;
pub use actor::MatchingVelocityTarget;
pub use game::Cycle::Next;
pub use game::Turn::Toggle;
pub use game::{GameEvent, Turn};