add thruster boost feature
This commit is contained in:
parent
c48e5cdb3a
commit
ebe028d567
|
@ -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
|
||||
|
||||
- Added space suit thruster particle effects
|
||||
|
|
|
@ -118,8 +118,6 @@ A variety of relatively simple game systems should interact with each other to c
|
|||
- [ ] Thruster boost
|
||||
- [ ] G-force dampeners
|
||||
- [ ] Life support, material recyclers (air, water, etc)
|
||||
- [ ] Noise cancellation?
|
||||
- [ ] Radio?
|
||||
- [ ] High energy particle shield?
|
||||
- [ ] Micrometeorite shield?
|
||||
|
||||
|
|
24
src/actor.rs
24
src/actor.rs
|
@ -21,6 +21,8 @@ use bevy_xpbd_3d::prelude::*;
|
|||
pub const ENGINE_SPEED_FACTOR: f32 = 30.0;
|
||||
const MAX_TRANSMISSION_DISTANCE: f32 = 100.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];
|
||||
pub const FLASHLIGHT_INTENSITY: [f32; 3] = [10e6, 400e6, 2e9]; // in lumens
|
||||
|
||||
|
@ -212,6 +214,9 @@ pub struct Engine {
|
|||
pub engine_type: EngineType,
|
||||
pub warmup_seconds: f32,
|
||||
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 {
|
||||
fn default() -> Self {
|
||||
|
@ -223,6 +228,9 @@ impl Default for Engine {
|
|||
engine_type: EngineType::Monopropellant,
|
||||
warmup_seconds: 1.5,
|
||||
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>,
|
||||
mut settings: ResMut<Settings>,
|
||||
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 ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||
mut ew_game: EventWriter<game::GameEvent>,
|
||||
) {
|
||||
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 {
|
||||
battery.power -= POWER_DRAIN_FLASHLIGHT[prefs.flashlight_power] * d; // 2.4MW
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
if axis_input.length_squared() > 0.003 {
|
||||
engine.currently_firing = true;
|
||||
let acceleration_global: DVec3 =
|
||||
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 =
|
||||
(actor::ENGINE_SPEED_FACTOR * dt) as f64 * acceleration_global;
|
||||
(actor::ENGINE_SPEED_FACTOR * dt) as f64 * boost * acceleration_global;
|
||||
let threshold = 1e-5;
|
||||
if key_input.pressed(settings.key_stop) {
|
||||
// Decelerate (or match velocity to target_v)
|
||||
engine.currently_matching_velocity = true;
|
||||
let dv = v.0 - target_v;
|
||||
for i in 0..3 {
|
||||
if dv[i].abs() < threshold {
|
||||
|
@ -560,6 +567,8 @@ pub fn apply_input_to_player(
|
|||
acceleration_total[i] = 0.0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
engine.currently_matching_velocity = false;
|
||||
}
|
||||
// TODO: handle mass
|
||||
v.0 += acceleration_total;
|
||||
|
@ -571,7 +580,7 @@ pub fn apply_input_to_player(
|
|||
if bike.is_none() && acceleration_total.length_squared() > 1e-4 {
|
||||
let thruster_direction = acceleration_total.normalize();
|
||||
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 {
|
||||
duration: 2.0,
|
||||
class: visual::Effects::ThrusterParticle(
|
||||
|
@ -581,6 +590,8 @@ pub fn apply_input_to_player(
|
|||
});
|
||||
}
|
||||
} else {
|
||||
engine.currently_firing = false;
|
||||
engine.currently_matching_velocity = false;
|
||||
engine.current_warmup =
|
||||
(engine.current_warmup - dt / engine.warmup_seconds).clamp(0.0, 1.0);
|
||||
}
|
||||
|
|
18
src/menu.rs
18
src/menu.rs
|
@ -68,6 +68,7 @@ pub const MENUDEF: &[(&str, MenuAction)] = &[
|
|||
("", MenuAction::ChangeARAvatar),
|
||||
("", MenuAction::ModLightAmp),
|
||||
("", MenuAction::ModFlashlightPower),
|
||||
("", MenuAction::ModThrusterBoost),
|
||||
("", MenuAction::ToggleSound),
|
||||
("", MenuAction::ToggleMusic),
|
||||
("", MenuAction::ToggleCamera),
|
||||
|
@ -84,6 +85,7 @@ pub enum MenuAction {
|
|||
ChangeARAvatar,
|
||||
ModLightAmp,
|
||||
ModFlashlightPower,
|
||||
ModThrusterBoost,
|
||||
ToggleSound,
|
||||
ToggleMusic,
|
||||
ToggleCamera,
|
||||
|
@ -494,6 +496,15 @@ pub fn update_menu(
|
|||
let n = prefs.flashlight_power + 1;
|
||||
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 => {
|
||||
if let Some(ava) = hud::PLAYER_AR_AVATARS.get(settings.ar_avatar) {
|
||||
let avatar_title = ava.3;
|
||||
|
@ -608,6 +619,13 @@ pub fn handle_input(
|
|||
ew_game.send(GameEvent::UpdateFlashlight);
|
||||
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 => {
|
||||
ew_game.send(GameEvent::SetMusic(Next));
|
||||
ew_updatemenu.send(UpdateMenuEvent);
|
||||
|
|
|
@ -454,6 +454,7 @@ pub struct Preferences {
|
|||
pub avatar: usize,
|
||||
pub light_amp: usize, // 0-3
|
||||
pub flashlight_power: usize, // 0-2
|
||||
pub thruster_boost: usize, // 0-2
|
||||
|
||||
#[serde(skip)]
|
||||
pub source_file: Option<String>,
|
||||
|
@ -576,6 +577,7 @@ pub fn load_prefs() -> Preferences {
|
|||
prefs.source_file = path;
|
||||
prefs.flashlight_power = prefs.flashlight_power.clamp(0, 2);
|
||||
prefs.light_amp = prefs.light_amp.clamp(0, 3);
|
||||
prefs.thruster_boost = prefs.thruster_boost.clamp(0, 2);
|
||||
prefs
|
||||
}
|
||||
Err(error) => {
|
||||
|
|
Loading…
Reference in a new issue