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
|
# v0.11.1
|
||||||
|
|
||||||
- Added space suit thruster particle effects
|
- 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
|
- [ ] 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?
|
||||||
|
|
||||||
|
|
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;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
18
src/menu.rs
18
src/menu.rs
|
@ -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);
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
Loading…
Reference in a new issue