added audio + visual effects for battery overload

This commit is contained in:
yuni 2024-09-22 05:50:01 +02:00
parent ebe028d567
commit b5e969f0f7
8 changed files with 141 additions and 9 deletions

View file

@ -47,6 +47,8 @@
- achieve.ogg: [UI Completed Status Alert Notification by Headphaze, CC BY 4.0](https://freesound.org/s/277033/) - achieve.ogg: [UI Completed Status Alert Notification by Headphaze, CC BY 4.0](https://freesound.org/s/277033/)
- drink.ogg: [Pouring Beer into Short Glass by megashroom, CC0](https://freesound.org/s/390336/) - drink.ogg: [Pouring Beer into Short Glass by megashroom, CC0](https://freesound.org/s/390336/)
- enter.ogg, exit.ogg: [Getting Out of Car.wav by kingsrow, CC0](https://freesound.org/s/181568/) - enter.ogg, exit.ogg: [Getting Out of Car.wav by kingsrow, CC0](https://freesound.org/s/181568/)
- powerdown.ogg: [Energy Drain by qubodup, CC0](https://freesound.org/people/qubodup/sounds/742835/)
- spark.ogg: [Socket Connect Disconnect by JustHallowed, CC BY 4.0](https://freesound.org/people/JustHallowed/sounds/691007/), Tempo -40, Amplify 4
- Takeoff.ogg: [By Serat, CC BY 4.0](https://freemusicarchive.org/music/serat/route-remastered/takeoff-remastered/) - Takeoff.ogg: [By Serat, CC BY 4.0](https://freemusicarchive.org/music/serat/route-remastered/takeoff-remastered/)
- JupiterRecording.ogg: An [actual Jupiter recording by NASA](https://archive.org/download/voyager-1-and-2-1990-jupiter-nasa-voyager-space-sounds-electronic), public domain. - JupiterRecording.ogg: An [actual Jupiter recording by NASA](https://archive.org/download/voyager-1-and-2-1990-jupiter-nasa-voyager-space-sounds-electronic), public domain.
- Processed by cutting out min 1:47-3:47 and applying a 10s linear crossfade at the end. Exported as ogg with quality=3, see [.kdenlive file](src/audio/JupiterRecording.kdenlive). - Processed by cutting out min 1:47-3:47 and applying a 10s linear crossfade at the end. Exported as ogg with quality=3, see [.kdenlive file](src/audio/JupiterRecording.kdenlive).

BIN
assets/sounds/powerdown.ogg Normal file

Binary file not shown.

BIN
assets/sounds/spark.ogg Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -258,6 +258,7 @@ pub struct Battery {
pub power: f32, // Watt-seconds pub power: f32, // Watt-seconds
pub capacity: f32, // Watt-seconds pub capacity: f32, // Watt-seconds
pub reactor: f32, // Watt (production) pub reactor: f32, // Watt (production)
pub overloaded_recovering: bool,
} }
impl Default for Battery { impl Default for Battery {
@ -266,6 +267,7 @@ impl Default for Battery {
power: 10e3 * 3600.0, power: 10e3 * 3600.0,
capacity: 10e3 * 3600.0, // 10kWh capacity: 10e3 * 3600.0, // 10kWh
reactor: 2000e3, // 2MW reactor: 2000e3, // 2MW
overloaded_recovering: false,
} }
} }
} }
@ -279,13 +281,14 @@ pub fn update_power(
mut ew_sfx: EventWriter<audio::PlaySfxEvent>, mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
mut ew_game: EventWriter<game::GameEvent>, mut ew_game: EventWriter<game::GameEvent>,
) { ) {
let mut power_down = false;
let d = time.delta_seconds(); let d = time.delta_seconds();
for (mut battery, mut engine) in &mut q_battery { for (mut battery, mut engine) in &mut q_battery {
if settings.flashlight_active { if settings.flashlight_active {
battery.power -= POWER_DRAIN_FLASHLIGHT[prefs.flashlight_power] * d; // 2.4MW battery.power -= POWER_DRAIN_FLASHLIGHT[prefs.flashlight_power] * d; // 2.4MW
if battery.power <= 0.0 { if battery.power <= 0.0 {
power_down = true;
settings.flashlight_active = false; settings.flashlight_active = false;
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Switch));
for mut flashlight_vis in &mut q_flashlight { for mut flashlight_vis in &mut q_flashlight {
*flashlight_vis = Visibility::Hidden; *flashlight_vis = Visibility::Hidden;
} }
@ -296,26 +299,39 @@ pub fn update_power(
hud_drain += prefs.light_amp as f32 * 200e3; // 200kW per level hud_drain += prefs.light_amp as f32 * 200e3; // 200kW per level
battery.power -= hud_drain * d; battery.power -= hud_drain * d;
if battery.power <= 0.0 { if battery.power <= 0.0 {
power_down = true;
ew_game.send(GameEvent::SetAR(Turn::Off)); ew_game.send(GameEvent::SetAR(Turn::Off));
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Switch));
for mut flashlight_vis in &mut q_flashlight { for mut flashlight_vis in &mut q_flashlight {
*flashlight_vis = Visibility::Hidden; *flashlight_vis = Visibility::Hidden;
} }
} }
} }
let drain = POWER_DRAIN_THRUSTER[prefs.thruster_boost]; let drain = POWER_DRAIN_THRUSTER[prefs.thruster_boost];
let boosting = prefs.thruster_boost != 2 let boosting = !battery.overloaded_recovering
&& (battery.power > drain * d * 20.0) && prefs.thruster_boost != 2
&& (prefs.thruster_boost == 1 || engine.currently_matching_velocity); && (prefs.thruster_boost == 1 || engine.currently_matching_velocity);
if boosting { if boosting {
if battery.power > drain * d * 100.0 {
engine.current_boost_factor = THRUSTER_BOOST_FACTOR[prefs.thruster_boost]; engine.current_boost_factor = THRUSTER_BOOST_FACTOR[prefs.thruster_boost];
if engine.currently_firing { if engine.currently_firing {
battery.power -= drain * d; battery.power -= drain * d;
} }
} else { } else {
power_down = true;
battery.overloaded_recovering = true;
engine.current_boost_factor = 1.0; engine.current_boost_factor = 1.0;
} }
} else {
engine.current_boost_factor = 1.0;
}
if power_down {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::PowerDown));
}
battery.power = (battery.power + battery.reactor * d).clamp(0.0, battery.capacity); battery.power = (battery.power + battery.reactor * d).clamp(0.0, battery.capacity);
if battery.overloaded_recovering && battery.power > battery.capacity * 0.5 {
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::PowerUp));
battery.overloaded_recovering = false;
}
} }
} }

View file

@ -77,6 +77,8 @@ const PATHS: &[(SfxType, Sfx, &str)] = &[
"sounds/connect.ogg", "sounds/connect.ogg",
), ),
(SfxType::OneOff, Sfx::Ping, "sounds/connect.ogg"), (SfxType::OneOff, Sfx::Ping, "sounds/connect.ogg"),
(SfxType::OneOff, Sfx::PowerDown, "sounds/powerdown.ogg"),
(SfxType::OneOff, Sfx::PowerUp, "sounds/spark.ogg"),
(SfxType::OneOff, Sfx::Switch, "sounds/click2.ogg"), (SfxType::OneOff, Sfx::Switch, "sounds/click2.ogg"),
(SfxType::OneOff, Sfx::Refill, "sounds/refill.ogg"), (SfxType::OneOff, Sfx::Refill, "sounds/refill.ogg"),
(SfxType::OneOff, Sfx::WakeUp, "sounds/wakeup.ogg"), (SfxType::OneOff, Sfx::WakeUp, "sounds/wakeup.ogg"),
@ -103,6 +105,8 @@ pub enum Sfx {
IncomingChatMessage, IncomingChatMessage,
Ion, Ion,
Ping, Ping,
PowerDown,
PowerUp,
Refill, Refill,
Switch, Switch,
Thruster, Thruster,
@ -125,6 +129,8 @@ pub fn str2sfx(sfx_label: &str) -> Sfx {
"zoom" => Sfx::Zoom, "zoom" => Sfx::Zoom,
"chat" => Sfx::IncomingChatMessage, "chat" => Sfx::IncomingChatMessage,
"ping" => Sfx::Ping, "ping" => Sfx::Ping,
"powerdown" => Sfx::PowerDown,
"powerup" => Sfx::PowerUp,
"connect" => Sfx::Connect, "connect" => Sfx::Connect,
"refill" => Sfx::Refill, "refill" => Sfx::Refill,
"entervehicle" => Sfx::EnterVehicle, "entervehicle" => Sfx::EnterVehicle,

View file

@ -38,6 +38,7 @@ pub const DASHBOARD_DEF: &[(Dashboard, &str)] = &[
(Dashboard::Leak, "leak"), (Dashboard::Leak, "leak"),
(Dashboard::RotationStabiliser, "rotation_stabiliser"), (Dashboard::RotationStabiliser, "rotation_stabiliser"),
(Dashboard::CruiseControl, "cruise_control"), (Dashboard::CruiseControl, "cruise_control"),
(Dashboard::Battery, "battery"),
(Dashboard::Radioactivity, "radioactivity"), (Dashboard::Radioactivity, "radioactivity"),
]; ];
@ -142,6 +143,7 @@ pub enum Dashboard {
RotationStabiliser, RotationStabiliser,
CruiseControl, CruiseControl,
Radioactivity, Radioactivity,
Battery,
} }
#[derive(Component, Debug, Copy, Clone)] #[derive(Component, Debug, Copy, Clone)]
@ -681,7 +683,7 @@ fn update_dashboard(
timer: ResMut<FPSUpdateTimer>, timer: ResMut<FPSUpdateTimer>,
mut q_dashboard: Query<(&mut Visibility, &Dashboard)>, mut q_dashboard: Query<(&mut Visibility, &Dashboard)>,
id2pos: Res<game::Id2Pos>, id2pos: Res<game::Id2Pos>,
q_player: Query<(&actor::Suit, &Position), With<actor::Player>>, q_player: Query<(&actor::Suit, &actor::Battery, &Position), With<actor::Player>>,
settings: Res<Settings>, settings: Res<Settings>,
) { ) {
if !settings.hud_active || !timer.0.just_finished() { if !settings.hud_active || !timer.0.just_finished() {
@ -691,12 +693,13 @@ fn update_dashboard(
if player.is_err() { if player.is_err() {
return; return;
} }
let (suit, pos) = player.unwrap(); let (suit, battery, pos) = player.unwrap();
for (mut vis, icon) in &mut q_dashboard { for (mut vis, icon) in &mut q_dashboard {
*vis = bool2vis(match icon { *vis = bool2vis(match icon {
Dashboard::Flashlight => settings.flashlight_active, Dashboard::Flashlight => settings.flashlight_active,
Dashboard::Leak => suit.integrity < 0.5, Dashboard::Leak => suit.integrity < 0.5,
Dashboard::Battery => battery.overloaded_recovering,
Dashboard::RotationStabiliser => !settings.rotation_stabilizer_active, Dashboard::RotationStabiliser => !settings.rotation_stabilizer_active,
Dashboard::CruiseControl => settings.cruise_control_active, Dashboard::CruiseControl => settings.cruise_control_active,
Dashboard::Radioactivity => { Dashboard::Radioactivity => {

View file

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="256"
height="256"
viewBox="0 0 67.733334 67.733334"
version="1.1"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="dashboard_battery.svg"
xml:space="preserve"
inkscape:export-filename="../../assets/sprites/dashboard_battery.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#000000"
bordercolor="#252525"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#000000"
inkscape:document-units="px"
inkscape:zoom="1.6542969"
inkscape:cx="107.59858"
inkscape:cy="110.92326"
inkscape:window-width="1440"
inkscape:window-height="820"
inkscape:window-x="0"
inkscape:window-y="60"
inkscape:window-maximized="1"
inkscape:current-layer="g227"
showgrid="true"
inkscape:export-bgcolor="#00000000"><inkscape:grid
id="grid1"
units="px"
originx="0"
originy="0"
spacingx="0.26458334"
spacingy="0.26458334"
empcolor="#0099e5"
empopacity="0.30196078"
color="#0099e5"
opacity="0.14901961"
empspacing="8"
dotted="false"
gridanglex="30"
gridanglez="30"
visible="true" /></sodipodi:namedview><defs
id="defs1"><filter
style="color-interpolation-filters:sRGB"
id="filter1"
inkscape:label="bloom"
x="-0.13048332"
y="-0.15460972"
width="1.2609666"
height="1.3092194"><feConvolveMatrix
order="1 1"
kernelMatrix="1.0000000 "
id="feConvolveMatrix1"
result="result1"
bias="0"
preserveAlpha="true"
edgeMode="none"
divisor="0" /><feGaussianBlur
stdDeviation="2"
id="feGaussianBlur1"
in="SourceGraphic" /><feComposite
id="feComposite1"
operator="arithmetic"
k1="1"
k2="0.99999999999999922"
k3="1"
k4="0"
in2="result1" /></filter></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"><g
id="g227"
style="filter:url(#filter1)"><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1-5"
transform="matrix(0.86486189,0,0,0.86486189,5.6836111,4.3940895)"><path
style="font-variation-settings:'wght' 400;fill:none;fill-opacity:1;stroke:#be1251;stroke-width:3.05926;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 6.7381087,16.059295 4.5e-6,40.702599 54.2571138,-2.5e-5 -3e-6,-40.702598 h -7.398697 l -14.797395,2.4e-5 14.797397,8.8e-5 -2e-6,-5.087942 H 41.265364 v 5.08783 l -14.797395,2.4e-5 -14.180835,2.4e-5 14.180837,6.4e-5 -2e-6,-5.087918 H 14.136807 v 5.08783 z"
id="path9"
sodipodi:nodetypes="ccccccccccccccccc" /><path
style="font-variation-settings:'wght' 400;fill:none;fill-opacity:1;stroke:#be1251;stroke-width:5.29167;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 13.758334,30.691669 H 27.516668"
id="path10"
sodipodi:nodetypes="cc" /><path
style="font-variation-settings:'wght' 400;fill:none;fill-opacity:1;stroke:#be1251;stroke-width:5.29167;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 20.637501,23.283335 V 38.100002"
id="path11"
sodipodi:nodetypes="cc" /><path
style="font-variation-settings:'wght' 400;fill:none;fill-opacity:1;stroke:#be1251;stroke-width:5.29167;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 40.216669,30.691669 H 53.975003"
id="path12"
sodipodi:nodetypes="cc" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB