implement g-forces and passing out

This commit is contained in:
yuni 2024-04-06 01:11:11 +02:00
parent 7d655ca6c6
commit a869a7704e
5 changed files with 81 additions and 11 deletions

View file

@ -18,6 +18,7 @@ impl Plugin for ActorPlugin {
update_physics_lifeforms, update_physics_lifeforms,
handle_wants_maxrotation, handle_wants_maxrotation,
handle_wants_maxvelocity, handle_wants_maxvelocity,
handle_gforce,
)); ));
app.add_systems(Update, ( app.add_systems(Update, (
handle_input, handle_input,
@ -73,6 +74,22 @@ impl Default for HitPoints {
} }
} }
#[derive(Component)]
pub struct ExperiencesGForce {
pub gforce: f32,
pub damage_threshold: f32,
pub blackout_threshold: f32,
pub blackout: f32,
pub last_linear_velocity: DVec3,
}
impl Default for ExperiencesGForce { fn default() -> Self { Self {
gforce: 0.0,
damage_threshold: 50.0,
blackout_threshold: 20.0,
blackout: 0.0,
last_linear_velocity: DVec3::splat(0.0),
}}}
#[derive(Component)] pub struct Player; // Attached to the suit of the player #[derive(Component)] pub struct Player; // Attached to the suit of the player
#[derive(Component)] pub struct PlayerDrivesThis; // Attached to the entered vehicle #[derive(Component)] pub struct PlayerDrivesThis; // Attached to the entered vehicle
#[derive(Component)] pub struct PlayerCamera; // Attached to the actor to use as point of view #[derive(Component)] pub struct PlayerCamera; // Attached to the actor to use as point of view
@ -312,9 +329,9 @@ fn handle_collisions(
mut collision_event_reader: EventReader<CollisionStarted>, mut collision_event_reader: EventReader<CollisionStarted>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>, mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
q_player: Query<(Entity, Option<&Player>), With<PlayerCamera>>, q_player: Query<(Entity, Option<&Player>), With<PlayerCamera>>,
mut q_player_lifeform: Query<(&mut LifeForm, &mut Suit, &mut HitPoints), With<Player>>, mut q_player_lifeform: Query<(&mut LifeForm, &mut Suit), With<Player>>,
) { ) {
if let (Ok((player, player_maybe)), Ok((mut lifeform, mut suit, mut hp))) = (q_player.get_single(), q_player_lifeform.get_single_mut()) { if let (Ok((player, player_maybe)), Ok((mut lifeform, mut suit))) = (q_player.get_single(), q_player_lifeform.get_single_mut()) {
for CollisionStarted(entity1, entity2) in collision_event_reader.read() { for CollisionStarted(entity1, entity2) in collision_event_reader.read() {
if *entity1 == player || *entity2 == player { if *entity1 == player || *entity2 == player {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Crash)); ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Crash));
@ -322,10 +339,6 @@ fn handle_collisions(
if player_maybe.is_some() { if player_maybe.is_some() {
suit.integrity -= 0.03; suit.integrity -= 0.03;
hp.damage += 10.0;
}
else {
hp.damage += 3.0;
} }
} }
} }
@ -423,3 +436,28 @@ fn handle_damage(
} }
} }
} }
fn handle_gforce(
time: Res<Time>,
mut q_actor: Query<(&LinearVelocity, &mut HitPoints, &mut ExperiencesGForce)>,
) {
let dt = time.delta_seconds();
let factor = 1.0 / dt / 9.81;
for (v, mut hp, mut gforce) in &mut q_actor {
gforce.gforce = factor * (v.0 - gforce.last_linear_velocity).length() as f32;
gforce.last_linear_velocity = v.0;
if gforce.gforce > gforce.damage_threshold {
hp.damage += (gforce.gforce - gforce.damage_threshold).powf(2.0) / 3000.0;
}
if gforce.blackout > 0.0001 {
gforce.blackout *= 0.998;
}
else if gforce.blackout > 0.0 {
gforce.blackout = 0.0;
}
if gforce.gforce > gforce.blackout_threshold {
gforce.blackout += (gforce.gforce - gforce.blackout_threshold).powf(2.0) / 300000.0
}
}
}

View file

@ -651,6 +651,7 @@ fn spawn_entities(
} }
if state.is_lifeform { if state.is_lifeform {
actor.insert(actor::LifeForm::default()); actor.insert(actor::LifeForm::default());
actor.insert(actor::ExperiencesGForce::default());
actor.insert(actor::Suit { actor.insert(actor::Suit {
oxygen: state.oxygen, oxygen: state.oxygen,
oxygen_max: nature::OXY_D, oxygen_max: nature::OXY_D,

View file

@ -29,7 +29,7 @@ actor 10 -30 20 MeteorAceGT
relativeto player relativeto player
scale 5 scale 5
vehicle yes vehicle yes
thrust 70 13.7 9.4 200000 20 thrust 35 6.85 4.7 200000 20
engine ion engine ion
collider sphere 1.5 collider sphere 1.5
camdistance 50 camdistance 50

View file

@ -1,5 +1,5 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::{settings, camera}; use crate::{actor, camera, settings};
pub struct EffectsPlugin; pub struct EffectsPlugin;
@ -9,6 +9,7 @@ impl Plugin for EffectsPlugin {
app.add_systems(Startup, spawn_effects.after(setup).after(camera::setup_camera)); app.add_systems(Startup, spawn_effects.after(setup).after(camera::setup_camera));
app.add_systems(Update, spawn_effects); app.add_systems(Update, spawn_effects);
app.add_systems(Update, update_fadeblack); app.add_systems(Update, update_fadeblack);
app.add_systems(Update, update_blackout);
app.add_event::<SpawnEffectEvent>(); app.add_event::<SpawnEffectEvent>();
} }
} }
@ -18,6 +19,7 @@ pub enum Effects {
FadeIn(Color), FadeIn(Color),
} }
#[derive(Component)] pub struct BlackOutOverlay;
#[derive(Component)] pub struct FadeBlack; #[derive(Component)] pub struct FadeBlack;
#[derive(Component)] #[derive(Component)]
pub struct Effect { pub struct Effect {
@ -32,12 +34,28 @@ pub struct SpawnEffectEvent {
} }
pub fn setup( pub fn setup(
mut commands: Commands,
settings: Res<settings::Settings>, settings: Res<settings::Settings>,
mut ew_effect: EventWriter<SpawnEffectEvent>, mut ew_effect: EventWriter<SpawnEffectEvent>,
) { ) {
if !settings.dev_mode { if !settings.dev_mode {
ew_effect.send(SpawnEffectEvent { class: Effects::FadeIn(Color::BLACK), duration: 4.0 }); ew_effect.send(SpawnEffectEvent { class: Effects::FadeIn(Color::BLACK), duration: 4.0 });
} }
commands.spawn((
BlackOutOverlay,
NodeBundle {
style: Style {
width: Val::Vw(100.0),
height: Val::Vh(100.0),
position_type: PositionType::Absolute,
top: Val::Px(0.0),
left: Val::Px(0.0),
..default()
},
background_color: Color::BLACK.into(),
..default()
},
));
} }
pub fn spawn_effects( pub fn spawn_effects(
@ -90,3 +108,15 @@ pub fn update_fadeblack(
bgcolor.0.set_a(alpha as f32); bgcolor.0.set_a(alpha as f32);
} }
} }
pub fn update_blackout(
mut q_effect: Query<&mut BackgroundColor, With<BlackOutOverlay>>,
q_player: Query<&actor::ExperiencesGForce, With<actor::Player>>
) {
if let (Ok(gforce), Ok(mut bgcolor)) = (q_player.get_single(), q_effect.get_single_mut()) {
let threshold = 0.3;
let factor = 1.0 / (1.0 - threshold);
let alpha = (factor * (gforce.blackout - threshold)).clamp(0.0, 1.0);
bgcolor.0.set_a(alpha as f32);
}
}

View file

@ -464,7 +464,7 @@ fn update(
diagnostics: Res<DiagnosticsStore>, diagnostics: Res<DiagnosticsStore>,
time: Res<Time>, time: Res<Time>,
mut log: ResMut<Log>, mut log: ResMut<Log>,
player: Query<(&actor::HitPoints, &actor::Suit, &actor::LifeForm), With<actor::Player>>, player: Query<(&actor::HitPoints, &actor::Suit, &actor::LifeForm, &actor::ExperiencesGForce), With<actor::Player>>,
q_camera: Query<(&Position, &LinearVelocity), With<actor::PlayerCamera>>, q_camera: Query<(&Position, &LinearVelocity), With<actor::PlayerCamera>>,
mut timer: ResMut<FPSUpdateTimer>, mut timer: ResMut<FPSUpdateTimer>,
mut query: Query<&mut Text, With<GaugesText>>, mut query: Query<&mut Text, With<GaugesText>>,
@ -479,7 +479,7 @@ fn update(
let q_camera_result = q_camera.get_single(); let q_camera_result = q_camera.get_single();
let player = player.get_single(); let player = player.get_single();
if player.is_ok() && q_camera_result.is_ok() { if player.is_ok() && q_camera_result.is_ok() {
let (hp, suit, lifeform) = player.unwrap(); let (hp, suit, lifeform, gforce) = player.unwrap();
let (pos, cam_v) = q_camera_result.unwrap(); let (pos, cam_v) = q_camera_result.unwrap();
for mut text in &mut query { for mut text in &mut query {
text.sections[3].value = format!("2524-03-12 03:02"); text.sections[3].value = format!("2524-03-12 03:02");
@ -505,7 +505,8 @@ fn update(
let adrenaline = lifeform.adrenaline * 990.0 + 10.0; let adrenaline = lifeform.adrenaline * 990.0 + 10.0;
text.sections[11].value = format!("{adrenaline:.0}pg/mL"); text.sections[11].value = format!("{adrenaline:.0}pg/mL");
let vitals = 100.0 * hp.current / hp.max; let vitals = 100.0 * hp.current / hp.max;
text.sections[13].value = format!("{vitals:.0}%"); let gforce = gforce.gforce;
text.sections[13].value = format!("{vitals:.0}% [{gforce}g]");
let all_actors = query_all_actors.iter().len(); let all_actors = query_all_actors.iter().len();
text.sections[15].value = format!("{all_actors:.0}"); text.sections[15].value = format!("{all_actors:.0}");
let integrity = suit.integrity * 100.0; let integrity = suit.integrity * 100.0;