add thruster boost feature

This commit is contained in:
yuni 2024-09-22 04:34:36 +02:00
parent c48e5cdb3a
commit ebe028d567
6 changed files with 62 additions and 7 deletions

View file

@ -1,3 +1,9 @@
# v0.12.0-dev
- Add power-hungry optional thruster boost
- Add different flashlight power settings
- Add different light amplification settings
# v0.11.1 # v0.11.1
- Added space suit thruster particle effects - Added space suit thruster particle effects

View file

@ -118,8 +118,6 @@ A variety of relatively simple game systems should interact with each other to c
- [ ] Thruster boost - [ ] Thruster boost
- [ ] G-force dampeners - [ ] G-force dampeners
- [ ] Life support, material recyclers (air, water, etc) - [ ] Life support, material recyclers (air, water, etc)
- [ ] Noise cancellation?
- [ ] Radio?
- [ ] High energy particle shield? - [ ] High energy particle shield?
- [ ] Micrometeorite shield? - [ ] Micrometeorite shield?

View file

@ -21,6 +21,8 @@ use bevy_xpbd_3d::prelude::*;
pub const ENGINE_SPEED_FACTOR: f32 = 30.0; pub const ENGINE_SPEED_FACTOR: f32 = 30.0;
const MAX_TRANSMISSION_DISTANCE: f32 = 100.0; const MAX_TRANSMISSION_DISTANCE: f32 = 100.0;
const MAX_INTERACT_DISTANCE: f32 = 50.0; const MAX_INTERACT_DISTANCE: f32 = 50.0;
const POWER_DRAIN_THRUSTER: [f32; 3] = [3e6, 3e6, 0.0];
const THRUSTER_BOOST_FACTOR: [f64; 3] = [3.0, 3.0, 0.0];
const POWER_DRAIN_FLASHLIGHT: [f32; 3] = [200e3, 1500e3, 2500e3]; const POWER_DRAIN_FLASHLIGHT: [f32; 3] = [200e3, 1500e3, 2500e3];
pub const FLASHLIGHT_INTENSITY: [f32; 3] = [10e6, 400e6, 2e9]; // in lumens pub const FLASHLIGHT_INTENSITY: [f32; 3] = [10e6, 400e6, 2e9]; // in lumens
@ -212,6 +214,9 @@ pub struct Engine {
pub engine_type: EngineType, pub engine_type: EngineType,
pub warmup_seconds: f32, pub warmup_seconds: f32,
pub current_warmup: f32, // between 0.0 and 1.0 pub current_warmup: f32, // between 0.0 and 1.0
pub current_boost_factor: f64,
pub currently_firing: bool,
pub currently_matching_velocity: bool,
} }
impl Default for Engine { impl Default for Engine {
fn default() -> Self { fn default() -> Self {
@ -223,6 +228,9 @@ impl Default for Engine {
engine_type: EngineType::Monopropellant, engine_type: EngineType::Monopropellant,
warmup_seconds: 1.5, warmup_seconds: 1.5,
current_warmup: 0.0, current_warmup: 0.0,
current_boost_factor: 1.0,
currently_firing: false,
currently_matching_velocity: false,
} }
} }
} }
@ -266,13 +274,13 @@ pub fn update_power(
time: Res<Time>, time: Res<Time>,
mut settings: ResMut<Settings>, mut settings: ResMut<Settings>,
prefs: Res<Preferences>, prefs: Res<Preferences>,
mut q_battery: Query<&mut Battery, With<Player>>, mut q_battery: Query<(&mut Battery, &mut Engine), With<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>,
mut ew_game: EventWriter<game::GameEvent>, mut ew_game: EventWriter<game::GameEvent>,
) { ) {
let d = time.delta_seconds(); let d = time.delta_seconds();
for mut battery 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 {
@ -295,6 +303,18 @@ pub fn update_power(
} }
} }
} }
let drain = POWER_DRAIN_THRUSTER[prefs.thruster_boost];
let boosting = prefs.thruster_boost != 2
&& (battery.power > drain * d * 20.0)
&& (prefs.thruster_boost == 1 || engine.currently_matching_velocity);
if boosting {
engine.current_boost_factor = THRUSTER_BOOST_FACTOR[prefs.thruster_boost];
if engine.currently_firing {
battery.power -= drain * d;
}
} else {
engine.current_boost_factor = 1.0;
}
battery.power = (battery.power + battery.reactor * d).clamp(0.0, battery.capacity); battery.power = (battery.power + battery.reactor * d).clamp(0.0, battery.capacity);
} }
} }

View file

@ -543,13 +543,20 @@ pub fn apply_input_to_player(
let factor = DVec3::new(right_factor as f64, up_factor as f64, forward_factor as f64); let factor = DVec3::new(right_factor as f64, up_factor as f64, forward_factor as f64);
if axis_input.length_squared() > 0.003 { if axis_input.length_squared() > 0.003 {
engine.currently_firing = true;
let acceleration_global: DVec3 = let acceleration_global: DVec3 =
DVec3::from(player_transform.rotation * (axis_input * factor).as_vec3()); DVec3::from(player_transform.rotation * (axis_input * factor).as_vec3());
let boost = if bike.is_none() {
engine.current_boost_factor
} else {
1.0
};
let mut acceleration_total: DVec3 = let mut acceleration_total: DVec3 =
(actor::ENGINE_SPEED_FACTOR * dt) as f64 * acceleration_global; (actor::ENGINE_SPEED_FACTOR * dt) as f64 * boost * acceleration_global;
let threshold = 1e-5; let threshold = 1e-5;
if key_input.pressed(settings.key_stop) { if key_input.pressed(settings.key_stop) {
// Decelerate (or match velocity to target_v) // Decelerate (or match velocity to target_v)
engine.currently_matching_velocity = true;
let dv = v.0 - target_v; let dv = v.0 - target_v;
for i in 0..3 { for i in 0..3 {
if dv[i].abs() < threshold { if dv[i].abs() < threshold {
@ -560,6 +567,8 @@ pub fn apply_input_to_player(
acceleration_total[i] = 0.0; acceleration_total[i] = 0.0;
} }
} }
} else {
engine.currently_matching_velocity = false;
} }
// TODO: handle mass // TODO: handle mass
v.0 += acceleration_total; v.0 += acceleration_total;
@ -571,7 +580,7 @@ pub fn apply_input_to_player(
if bike.is_none() && acceleration_total.length_squared() > 1e-4 { if bike.is_none() && acceleration_total.length_squared() > 1e-4 {
let thruster_direction = acceleration_total.normalize(); let thruster_direction = acceleration_total.normalize();
let thruster_pos = pos.0 - 0.3 * thruster_direction; let thruster_pos = pos.0 - 0.3 * thruster_direction;
let thruster_v = v.0 - 5.0 * thruster_direction; let thruster_v = v.0 - boost * 5.0 * thruster_direction;
ew_effect.send(visual::SpawnEffectEvent { ew_effect.send(visual::SpawnEffectEvent {
duration: 2.0, duration: 2.0,
class: visual::Effects::ThrusterParticle( class: visual::Effects::ThrusterParticle(
@ -581,6 +590,8 @@ pub fn apply_input_to_player(
}); });
} }
} else { } else {
engine.currently_firing = false;
engine.currently_matching_velocity = false;
engine.current_warmup = engine.current_warmup =
(engine.current_warmup - dt / engine.warmup_seconds).clamp(0.0, 1.0); (engine.current_warmup - dt / engine.warmup_seconds).clamp(0.0, 1.0);
} }

View file

@ -68,6 +68,7 @@ pub const MENUDEF: &[(&str, MenuAction)] = &[
("", MenuAction::ChangeARAvatar), ("", MenuAction::ChangeARAvatar),
("", MenuAction::ModLightAmp), ("", MenuAction::ModLightAmp),
("", MenuAction::ModFlashlightPower), ("", MenuAction::ModFlashlightPower),
("", MenuAction::ModThrusterBoost),
("", MenuAction::ToggleSound), ("", MenuAction::ToggleSound),
("", MenuAction::ToggleMusic), ("", MenuAction::ToggleMusic),
("", MenuAction::ToggleCamera), ("", MenuAction::ToggleCamera),
@ -84,6 +85,7 @@ pub enum MenuAction {
ChangeARAvatar, ChangeARAvatar,
ModLightAmp, ModLightAmp,
ModFlashlightPower, ModFlashlightPower,
ModThrusterBoost,
ToggleSound, ToggleSound,
ToggleMusic, ToggleMusic,
ToggleCamera, ToggleCamera,
@ -494,6 +496,15 @@ pub fn update_menu(
let n = prefs.flashlight_power + 1; let n = prefs.flashlight_power + 1;
text.sections[i].value = format!("Flashlight Power: {n}/3\n"); text.sections[i].value = format!("Flashlight Power: {n}/3\n");
} }
MenuAction::ModThrusterBoost => {
let state = match prefs.thruster_boost {
0 => "Only when slowing down",
1 => "MAX POWER",
2 => "Off",
_ => "ERROR",
};
text.sections[i].value = format!("Thruster Boost: {state}\n");
}
MenuAction::ChangeARAvatar => { MenuAction::ChangeARAvatar => {
if let Some(ava) = hud::PLAYER_AR_AVATARS.get(settings.ar_avatar) { if let Some(ava) = hud::PLAYER_AR_AVATARS.get(settings.ar_avatar) {
let avatar_title = ava.3; let avatar_title = ava.3;
@ -608,6 +619,13 @@ pub fn handle_input(
ew_game.send(GameEvent::UpdateFlashlight); ew_game.send(GameEvent::UpdateFlashlight);
ew_updatemenu.send(UpdateMenuEvent); ew_updatemenu.send(UpdateMenuEvent);
} }
MenuAction::ModThrusterBoost => {
prefs.thruster_boost += 1;
if prefs.thruster_boost > 2 {
prefs.thruster_boost = 0;
}
ew_updatemenu.send(UpdateMenuEvent);
}
MenuAction::ToggleMusic => { MenuAction::ToggleMusic => {
ew_game.send(GameEvent::SetMusic(Next)); ew_game.send(GameEvent::SetMusic(Next));
ew_updatemenu.send(UpdateMenuEvent); ew_updatemenu.send(UpdateMenuEvent);

View file

@ -454,6 +454,7 @@ pub struct Preferences {
pub avatar: usize, pub avatar: usize,
pub light_amp: usize, // 0-3 pub light_amp: usize, // 0-3
pub flashlight_power: usize, // 0-2 pub flashlight_power: usize, // 0-2
pub thruster_boost: usize, // 0-2
#[serde(skip)] #[serde(skip)]
pub source_file: Option<String>, pub source_file: Option<String>,
@ -576,6 +577,7 @@ pub fn load_prefs() -> Preferences {
prefs.source_file = path; prefs.source_file = path;
prefs.flashlight_power = prefs.flashlight_power.clamp(0, 2); prefs.flashlight_power = prefs.flashlight_power.clamp(0, 2);
prefs.light_amp = prefs.light_amp.clamp(0, 3); prefs.light_amp = prefs.light_amp.clamp(0, 3);
prefs.thruster_boost = prefs.thruster_boost.clamp(0, 2);
prefs prefs
} }
Err(error) => { Err(error) => {