add death screen

This commit is contained in:
yuni 2024-05-12 22:17:17 +02:00
parent 7aa6885509
commit 182659eff0
5 changed files with 186 additions and 23 deletions

View file

@ -18,7 +18,8 @@ use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*; use bevy_xpbd_3d::prelude::*;
use bevy::scene::SceneInstance; use bevy::scene::SceneInstance;
use bevy::math::DVec3; use bevy::math::DVec3;
use crate::{actor, audio, camera, chat, commands, hud, nature, var, visual, world}; use crate::prelude::*;
use crate::{actor, audio, camera, chat, commands, hud, menu, nature, visual, world};
use std::collections::HashMap; use std::collections::HashMap;
pub const ENGINE_SPEED_FACTOR: f32 = 30.0; pub const ENGINE_SPEED_FACTOR: f32 = 30.0;
@ -229,7 +230,7 @@ impl Default for Battery {
pub fn update_power( pub fn update_power(
time: Res<Time>, time: Res<Time>,
mut settings: ResMut<var::Settings>, mut settings: ResMut<Settings>,
mut q_battery: Query<(&mut Battery, Option<&Player>)>, mut q_battery: Query<(&mut Battery, Option<&Player>)>,
mut q_flashlight: Query<&mut Visibility, With<PlayersFlashLight>>, mut q_flashlight: Query<&mut Visibility, With<PlayersFlashLight>>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>, mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
@ -299,7 +300,7 @@ pub fn update_physics_lifeforms(
pub fn handle_input( pub fn handle_input(
mut commands: Commands, mut commands: Commands,
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,
mut settings: ResMut<var::Settings>, mut settings: ResMut<Settings>,
q_talker: Query<(&chat::Talker, &Transform), (Without<actor::Player>, Without<Camera>)>, q_talker: Query<(&chat::Talker, &Transform), (Without<actor::Player>, Without<Camera>)>,
player: Query<Entity, With<actor::Player>>, player: Query<Entity, With<actor::Player>>,
q_camera: Query<&Transform, With<Camera>>, q_camera: Query<&Transform, With<Camera>>,
@ -382,7 +383,7 @@ pub fn handle_input(
pub fn handle_vehicle_enter_exit( pub fn handle_vehicle_enter_exit(
mut commands: Commands, mut commands: Commands,
mut settings: ResMut<var::Settings>, mut settings: ResMut<Settings>,
mut er_vehicle: EventReader<VehicleEnterExitEvent>, mut er_vehicle: EventReader<VehicleEnterExitEvent>,
mut q_playerflashlight: Query<&mut Visibility, (With<PlayersFlashLight>, Without<ActorVehicleBeingEntered>, Without<ActorEnteringVehicle>)>, mut q_playerflashlight: Query<&mut Visibility, (With<PlayersFlashLight>, Without<ActorVehicleBeingEntered>, Without<ActorEnteringVehicle>)>,
mut q_drivers: Query<(Entity, &mut Visibility, Option<&Collider>), (Without<ActorVehicleBeingEntered>, With<ActorEnteringVehicle>)>, mut q_drivers: Query<(Entity, &mut Visibility, Option<&Collider>), (Without<ActorVehicleBeingEntered>, With<ActorEnteringVehicle>)>,
@ -505,10 +506,10 @@ fn handle_player_death(
ew_spawn: EventWriter<commands::SpawnEvent>, ew_spawn: EventWriter<commands::SpawnEvent>,
mut scene_spawner: ResMut<SceneSpawner>, mut scene_spawner: ResMut<SceneSpawner>,
mut active_asteroids: ResMut<world::ActiveAsteroids>, mut active_asteroids: ResMut<world::ActiveAsteroids>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
mut ew_effect: EventWriter<visual::SpawnEffectEvent>, mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
mut ew_deathscreen: EventWriter<menu::DeathScreenEvent>,
mut log: ResMut<hud::Log>, mut log: ResMut<hud::Log>,
mut settings: ResMut<var::Settings>, mut settings: ResMut<Settings>,
) { ) {
for death in er_playerdies.read() { for death in er_playerdies.read() {
if settings.god_mode { if settings.god_mode {
@ -528,20 +529,28 @@ fn handle_player_death(
match death.0 { match death.0 {
DamageType::Mental => { DamageType::Mental => {
settings.death_cause = "Brain Damage".to_string();
ew_effect.send(visual::SpawnEffectEvent { ew_effect.send(visual::SpawnEffectEvent {
class: visual::Effects::FadeIn(Color::BLACK), class: visual::Effects::FadeIn(Color::BLACK),
duration: 4.0, duration: 4.0,
}); });
} }
DamageType::Asphyxiation => { DamageType::Asphyxiation => {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::WakeUp)); settings.death_cause = "Suffocation".to_string();
ew_effect.send(visual::SpawnEffectEvent { ew_effect.send(visual::SpawnEffectEvent {
class: visual::Effects::FadeIn(Color::BLACK), class: visual::Effects::FadeIn(Color::BLACK),
duration: 1.0, duration: 1.0,
}); });
} }
DamageType::Trauma | _ => { DamageType::Trauma => {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::WakeUp)); settings.death_cause = "Trauma".to_string();
ew_effect.send(visual::SpawnEffectEvent {
class: visual::Effects::FadeIn(Color::MAROON),
duration: 1.0,
});
}
_ => {
settings.death_cause = "Unknown".to_string();
ew_effect.send(visual::SpawnEffectEvent { ew_effect.send(visual::SpawnEffectEvent {
class: visual::Effects::FadeIn(Color::MAROON), class: visual::Effects::FadeIn(Color::MAROON),
duration: 1.0, duration: 1.0,
@ -549,7 +558,7 @@ fn handle_player_death(
} }
} }
commands::load_defs(ew_spawn); ew_deathscreen.send(menu::DeathScreenEvent::Show);
return; return;
} }
} }
@ -557,7 +566,7 @@ fn handle_player_death(
fn handle_damage( fn handle_damage(
mut ew_playerdies: EventWriter<PlayerDiesEvent>, mut ew_playerdies: EventWriter<PlayerDiesEvent>,
mut q_hp: Query<(&mut HitPoints, Option<&Player>), Changed<HitPoints>>, mut q_hp: Query<(&mut HitPoints, Option<&Player>), Changed<HitPoints>>,
settings: Res<var::Settings>, settings: Res<Settings>,
) { ) {
for (mut hp, player_maybe) in &mut q_hp { for (mut hp, player_maybe) in &mut q_hp {
if player_maybe.is_some() { if player_maybe.is_some() {
@ -621,7 +630,7 @@ fn handle_cheats(
mut q_life: Query<(&mut actor::LifeForm, &mut actor::ExperiencesGForce), With<actor::Player>>, mut q_life: Query<(&mut actor::LifeForm, &mut actor::ExperiencesGForce), With<actor::Player>>,
q_target: Query<(&Transform, &Position, Option<&LinearVelocity>), (With<hud::IsTargeted>, Without<actor::PlayerCamera>)>, q_target: Query<(&Transform, &Position, Option<&LinearVelocity>), (With<hud::IsTargeted>, Without<actor::PlayerCamera>)>,
mut ew_playerdies: EventWriter<actor::PlayerDiesEvent>, mut ew_playerdies: EventWriter<actor::PlayerDiesEvent>,
mut settings: ResMut<var::Settings>, mut settings: ResMut<Settings>,
id2pos: Res<actor::Id2Pos>, id2pos: Res<actor::Id2Pos>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>, mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
) { ) {

View file

@ -22,7 +22,6 @@ use std::collections::VecDeque;
use std::time::SystemTime; use std::time::SystemTime;
pub const HUD_REFRESH_TIME: f32 = 0.1; pub const HUD_REFRESH_TIME: f32 = 0.1;
pub const FONT: &str = "fonts/Yupiter-Regular.ttf";
pub const LOG_MAX_TIME_S: f64 = 30.0; pub const LOG_MAX_TIME_S: f64 = 30.0;
pub const LOG_MAX_ROWS: usize = 30; pub const LOG_MAX_ROWS: usize = 30;
pub const LOG_MAX: usize = LOG_MAX_ROWS; pub const LOG_MAX: usize = LOG_MAX_ROWS;
@ -214,7 +213,7 @@ impl Log {
} }
} }
fn setup( pub fn setup(
mut commands: Commands, mut commands: Commands,
settings: Res<Settings>, settings: Res<Settings>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
@ -1138,11 +1137,3 @@ fn update_overlay_visibility(
AMBIENT_LIGHT AMBIENT_LIGHT
}; };
} }
fn bool2vis(parameter: bool) -> Visibility {
if parameter {
Visibility::Inherited
} else {
Visibility::Hidden
}
}

View file

@ -18,6 +18,7 @@ mod chat;
mod commands; mod commands;
mod hud; mod hud;
mod load; mod load;
mod menu;
mod var; mod var;
mod visual; mod visual;
mod world; mod world;
@ -26,8 +27,15 @@ mod world;
mod nature; mod nature;
pub mod prelude { pub mod prelude {
pub use crate::var::Settings; pub use crate::var::{FONT, Settings};
pub use crate::load::load_asset; pub use crate::load::load_asset;
pub fn bool2vis(boolean: bool) -> bevy::prelude::Visibility {
if boolean {
bevy::prelude::Visibility::Inherited
} else {
bevy::prelude::Visibility::Hidden
}
}
} }
use bevy::window::{Window, WindowMode, PrimaryWindow, CursorGrabMode}; use bevy::window::{Window, WindowMode, PrimaryWindow, CursorGrabMode};
@ -133,6 +141,7 @@ impl Plugin for OutFlyPlugin {
camera::CameraPlugin, camera::CameraPlugin,
chat::ChatPlugin, chat::ChatPlugin,
commands::CommandsPlugin, commands::CommandsPlugin,
menu::MenuPlugin,
visual::VisualPlugin, visual::VisualPlugin,
hud::HudPlugin, hud::HudPlugin,
load::LoadPlugin, load::LoadPlugin,

144
src/menu.rs Normal file
View file

@ -0,0 +1,144 @@
// ▄████████▄ + ███ + ▄█████████ ███ +
// ███▀ ▀███ + + ███ ███▀ + ███ + +
// ███ + ███ ███ ███ █████████ ███ ███ ███ ███
// ███ +███ ███ ███ ███ ███▐██████ ███ ███ ███
// ███ + ███ ███+ ███ +███ ███ + ███ ███ + ███
// ███▄ ▄███ ███▄ ███ ███ + ███ + ███ ███▄ ███
// ▀████████▀ + ▀███████ ███▄ ███▄ ▀████ ▀███████
// + + + ███
// + ▀████████████████████████████████████████████████████▀
//
// This plugin manages game menus and the player death screen
use crate::prelude::*;
use crate::{audio, hud, visual};
use bevy::prelude::*;
pub struct MenuPlugin;
impl Plugin for MenuPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, setup.after(hud::setup));
app.add_systems(PreUpdate, show_deathscreen.run_if(on_event::<DeathScreenEvent>()));
app.add_systems(Update, handle_deathscreen_input);
app.add_event::<DeathScreenEvent>();
}
}
#[derive(Component)] pub struct DeathScreenElement;
#[derive(Component)] pub struct BlackScreen;
#[derive(Component)] pub struct DeathText;
#[derive(Event, PartialEq)] pub enum DeathScreenEvent { Show, Hide }
pub fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
settings: Res<Settings>,
) {
commands.spawn((
BlackScreen,
DeathScreenElement,
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(),
visibility: Visibility::Hidden,
..default()
},
));
let font_handle = asset_server.load(FONT);
let style_death = TextStyle {
font: font_handle.clone(),
font_size: settings.font_size_deathtext,
color: settings.hud_color_subtitles,
..default()
};
let style_death_subtext = TextStyle {
font: font_handle.clone(),
font_size: settings.font_size_deathsubtext,
color: settings.hud_color_subtitles,
..default()
};
let style_death_subsubtext = TextStyle {
font: font_handle.clone(),
font_size: settings.font_size_deathsubtext * 0.8,
color: settings.hud_color_subtitles,
..default()
};
commands.spawn((
DeathScreenElement,
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::SpaceAround,
..default()
},
visibility: Visibility::Hidden,
..default()
},
)).with_children(|builder| {
builder.spawn((
DeathText,
TextBundle {
text: Text {
sections: vec![
TextSection::new("You are dead.\n", style_death),
TextSection::new("Cause: ", style_death_subtext.clone()),
TextSection::new("Unknown", style_death_subtext),
TextSection::new("\n\n\nPress E to begin anew.", style_death_subsubtext),
],
justify: JustifyText::Center,
..default()
},
..default()
},
));
});
}
pub fn show_deathscreen(
mut er_deathscreen: EventReader<DeathScreenEvent>,
mut q_vis: Query<&mut Visibility, With<DeathScreenElement>>,
mut q_text: Query<&mut Text, With<DeathText>>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
mut settings: ResMut<Settings>,
) {
for event in er_deathscreen.read() {
let show = *event == DeathScreenEvent::Show;
for mut vis in &mut q_vis {
*vis = bool2vis(show);
}
settings.deathscreen_active = show;
if show {
if let Ok(mut text) = q_text.get_single_mut() {
text.sections[2].value = settings.death_cause.clone();
}
} else {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::WakeUp));
ew_effect.send(visual::SpawnEffectEvent { class: visual::Effects::FadeIn(Color::BLACK), duration: 0.3 });
}
}
}
pub fn handle_deathscreen_input(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut ew_deathscreen: EventWriter<DeathScreenEvent>,
settings: ResMut<Settings>,
) {
if !settings.deathscreen_active {
return;
}
if keyboard_input.pressed(settings.key_interact) {
ew_deathscreen.send(DeathScreenEvent::Hide);
}
}

View file

@ -19,6 +19,8 @@ use toml_edit::DocumentMut;
use std::env; use std::env;
use std::fs; use std::fs;
pub const FONT: &str = "fonts/Yupiter-Regular.ttf";
pub const SCOPE_SEPARATOR: &str = "$"; pub const SCOPE_SEPARATOR: &str = "$";
pub const TOKEN_EQUALS: &str = "=="; pub const TOKEN_EQUALS: &str = "==";
@ -50,6 +52,8 @@ pub struct Settings {
pub font_size_choices: f32, pub font_size_choices: f32,
pub font_size_console: f32, pub font_size_console: f32,
pub font_size_speedometer: f32, pub font_size_speedometer: f32,
pub font_size_deathtext: f32,
pub font_size_deathsubtext: f32,
pub hud_color: Color, pub hud_color: Color,
pub hud_color_console: Color, pub hud_color_console: Color,
pub hud_color_console_warn: Color, pub hud_color_console_warn: Color,
@ -62,6 +66,8 @@ pub struct Settings {
pub flashlight_active: bool, pub flashlight_active: bool,
pub hud_active: bool, pub hud_active: bool,
pub map_active: bool, pub map_active: bool,
pub deathscreen_active: bool,
pub death_cause: String,
pub is_zooming: bool, pub is_zooming: bool,
pub third_person: bool, pub third_person: bool,
pub rotation_stabilizer_active: bool, pub rotation_stabilizer_active: bool,
@ -157,6 +163,8 @@ impl Default for Settings {
font_size_choices: 28.0, font_size_choices: 28.0,
font_size_console: 20.0, font_size_console: 20.0,
font_size_speedometer: 34.0, font_size_speedometer: 34.0,
font_size_deathtext: 64.0,
font_size_deathsubtext: 32.0,
hud_color: Color::hex("#BE1251").unwrap(), hud_color: Color::hex("#BE1251").unwrap(),
hud_color_console: Color::hex("#BE1251").unwrap(), hud_color_console: Color::hex("#BE1251").unwrap(),
hud_color_console_warn: Color::hex("#CCCCCC").unwrap(), hud_color_console_warn: Color::hex("#CCCCCC").unwrap(),
@ -169,6 +177,8 @@ impl Default for Settings {
flashlight_active: false, flashlight_active: false,
hud_active: true, hud_active: true,
map_active: false, map_active: false,
deathscreen_active: false,
death_cause: "Unknown".to_string(),
is_zooming: false, is_zooming: false,
third_person: true, third_person: true,
rotation_stabilizer_active: true, rotation_stabilizer_active: true,