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,
handle_wants_maxrotation,
handle_wants_maxvelocity,
handle_gforce,
));
app.add_systems(Update, (
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 PlayerDrivesThis; // Attached to the entered vehicle
#[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 ew_sfx: EventWriter<audio::PlaySfxEvent>,
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() {
if *entity1 == player || *entity2 == player {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Crash));
@ -322,10 +339,6 @@ fn handle_collisions(
if player_maybe.is_some() {
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 {
actor.insert(actor::LifeForm::default());
actor.insert(actor::ExperiencesGForce::default());
actor.insert(actor::Suit {
oxygen: state.oxygen,
oxygen_max: nature::OXY_D,

View file

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

View file

@ -1,5 +1,5 @@
use bevy::prelude::*;
use crate::{settings, camera};
use crate::{actor, camera, settings};
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(Update, spawn_effects);
app.add_systems(Update, update_fadeblack);
app.add_systems(Update, update_blackout);
app.add_event::<SpawnEffectEvent>();
}
}
@ -18,6 +19,7 @@ pub enum Effects {
FadeIn(Color),
}
#[derive(Component)] pub struct BlackOutOverlay;
#[derive(Component)] pub struct FadeBlack;
#[derive(Component)]
pub struct Effect {
@ -32,12 +34,28 @@ pub struct SpawnEffectEvent {
}
pub fn setup(
mut commands: Commands,
settings: Res<settings::Settings>,
mut ew_effect: EventWriter<SpawnEffectEvent>,
) {
if !settings.dev_mode {
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(
@ -90,3 +108,15 @@ pub fn update_fadeblack(
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>,
time: Res<Time>,
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>>,
mut timer: ResMut<FPSUpdateTimer>,
mut query: Query<&mut Text, With<GaugesText>>,
@ -479,7 +479,7 @@ fn update(
let q_camera_result = q_camera.get_single();
let player = player.get_single();
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();
for mut text in &mut query {
text.sections[3].value = format!("2524-03-12 03:02");
@ -505,7 +505,8 @@ fn update(
let adrenaline = lifeform.adrenaline * 990.0 + 10.0;
text.sections[11].value = format!("{adrenaline:.0}pg/mL");
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();
text.sections[15].value = format!("{all_actors:.0}");
let integrity = suit.integrity * 100.0;