Merge branch 'gravity'
This commit is contained in:
commit
1a94c31d62
|
@ -35,6 +35,8 @@ The `SPACE` key helps you move more intuitively by slowing you down. Hold it fo
|
||||||
|
|
||||||
When you're ready, take a look around, explore the starting area. There is a friendly person floating nearby in a red space suit that would love to talk to you.
|
When you're ready, take a look around, explore the starting area. There is a friendly person floating nearby in a red space suit that would love to talk to you.
|
||||||
|
|
||||||
|
The game is a bit dark, since it's meant to be played in the night. But maybe you're unlucky and you start with a planet or moon eclipsing the sun, making everything extra dark. (Yes, all celestial objects move in real time and have different positions depending on when you play.) If it's too dark, try the flashlight (`f` key), turning off the shadows in the menu, and make sure that Augmented Reality is on (`TAB` key) which gives you a little extra light amplification.
|
||||||
|
|
||||||
Press the `ESC` key for the menu to restart the game if you get lost, explore more key bindings, game features, and the **achievements** to get some guidance on what you can do in the game.
|
Press the `ESC` key for the menu to restart the game if you get lost, explore more key bindings, game features, and the **achievements** to get some guidance on what you can do in the game.
|
||||||
|
|
||||||
But in the end, OutFly is an open world game with no true goals other than the ones you set for yourself. Just lean back, get cozy, and drift towards whatever catches your eye :)
|
But in the end, OutFly is an open world game with no true goals other than the ones you set for yourself. Just lean back, get cozy, and drift towards whatever catches your eye :)
|
||||||
|
|
86
src/actor.rs
86
src/actor.rs
|
@ -30,8 +30,9 @@ impl Plugin for ActorPlugin {
|
||||||
(
|
(
|
||||||
update_physics_lifeforms,
|
update_physics_lifeforms,
|
||||||
update_power,
|
update_power,
|
||||||
|
handle_gravity,
|
||||||
handle_wants_maxrotation,
|
handle_wants_maxrotation,
|
||||||
handle_wants_maxvelocity,
|
handle_wants_maxvelocity.run_if(any_with_component::<WantsMaxVelocity>),
|
||||||
handle_wants_lookat.run_if(alive),
|
handle_wants_lookat.run_if(alive),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -118,6 +119,7 @@ pub struct ExperiencesGForce {
|
||||||
pub visual_effect_threshold: f32,
|
pub visual_effect_threshold: f32,
|
||||||
pub visual_effect: f32,
|
pub visual_effect: f32,
|
||||||
pub last_linear_velocity: DVec3,
|
pub last_linear_velocity: DVec3,
|
||||||
|
pub gravitational_component: DVec3,
|
||||||
pub ignore_gforce_seconds: f32,
|
pub ignore_gforce_seconds: f32,
|
||||||
}
|
}
|
||||||
impl Default for ExperiencesGForce {
|
impl Default for ExperiencesGForce {
|
||||||
|
@ -127,8 +129,9 @@ impl Default for ExperiencesGForce {
|
||||||
damage_threshold: 100.0,
|
damage_threshold: 100.0,
|
||||||
visual_effect_threshold: 20.0,
|
visual_effect_threshold: 20.0,
|
||||||
visual_effect: 0.0,
|
visual_effect: 0.0,
|
||||||
last_linear_velocity: DVec3::splat(0.0),
|
last_linear_velocity: DVec3::ZERO,
|
||||||
ignore_gforce_seconds: 0.0,
|
gravitational_component: DVec3::ZERO,
|
||||||
|
ignore_gforce_seconds: 0.01,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +159,11 @@ pub struct WantsMaxVelocity(pub f64);
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct WantsToLookAt(pub String);
|
pub struct WantsToLookAt(pub String);
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
pub struct WantsMatchVelocityWith(pub String);
|
||||||
|
#[derive(Component)]
|
||||||
pub struct Identifier(pub String);
|
pub struct Identifier(pub String);
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct OrbitsJupiter;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct LifeForm {
|
pub struct LifeForm {
|
||||||
|
@ -535,25 +542,53 @@ fn handle_wants_maxrotation(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Slows down NPC's movement until they reach their target velocity.
|
||||||
fn handle_wants_maxvelocity(
|
fn handle_wants_maxvelocity(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut query: Query<(&mut LinearVelocity, &Engine, &WantsMaxVelocity)>,
|
mut query: Query<(
|
||||||
|
&Position,
|
||||||
|
&mut LinearVelocity,
|
||||||
|
&Engine,
|
||||||
|
&WantsMaxVelocity,
|
||||||
|
Option<&OrbitsJupiter>,
|
||||||
|
Option<&WantsMatchVelocityWith>,
|
||||||
|
)>,
|
||||||
|
id2v: Res<game::Id2V>,
|
||||||
|
jupiter_pos: Res<game::JupiterPos>,
|
||||||
) {
|
) {
|
||||||
let dt = time.delta_seconds();
|
let dt = time.delta_seconds();
|
||||||
for (mut v, engine, maxv) in &mut query {
|
for (pos, mut v, engine, maxv, orbits_jupiter, matchwith) in &mut query {
|
||||||
let total = v.0.length();
|
let target_velocity = if let Some(matchwith) = matchwith {
|
||||||
if total <= maxv.0 + EPSILON {
|
if let Some(target_v) = id2v.0.get(&matchwith.0) {
|
||||||
if total > maxv.0 {
|
*target_v
|
||||||
v.0 = DVec3::splat(0.0);
|
} else {
|
||||||
|
warn!("Can't match velocity with nonexisting ID {}", matchwith.0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if orbits_jupiter.is_some() {
|
||||||
|
let relative_pos = pos.0 - jupiter_pos.0;
|
||||||
|
nature::orbital_velocity(relative_pos, nature::JUPITER_MASS)
|
||||||
|
} else {
|
||||||
|
DVec3::ZERO
|
||||||
|
};
|
||||||
|
let relative_velocity = v.0 - target_velocity;
|
||||||
|
let relative_speed = relative_velocity.length();
|
||||||
|
|
||||||
|
if relative_speed <= maxv.0 + EPSILON {
|
||||||
|
// it's already pretty close to the target
|
||||||
|
if relative_speed > maxv.0 {
|
||||||
|
// but not quite the target, so let's set it to the target
|
||||||
|
v.0 = target_velocity;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// slow it down a little bit
|
||||||
// TODO: respect engine parameters for different thrusts for different directions
|
// TODO: respect engine parameters for different thrusts for different directions
|
||||||
let avg_thrust =
|
let avg_thrust =
|
||||||
(engine.thrust_forward + engine.thrust_back + engine.thrust_sideways) / 3.0;
|
(engine.thrust_forward + engine.thrust_back + engine.thrust_sideways) / 3.0;
|
||||||
let acceleration = (avg_thrust * dt) as f64 * -v.0;
|
let acceleration = (avg_thrust * dt) as f64 * -relative_velocity;
|
||||||
v.0 += acceleration;
|
v.0 += acceleration;
|
||||||
if v.0.length() + EPSILON < acceleration.length() {
|
if v.0.length() + EPSILON < acceleration.length() {
|
||||||
v.0 = DVec3::splat(0.0);
|
v.0 = target_velocity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -610,8 +645,10 @@ fn handle_gforce(
|
||||||
let dt = time.delta_seconds();
|
let dt = time.delta_seconds();
|
||||||
let factor = 1.0 / dt / nature::EARTH_GRAVITY;
|
let factor = 1.0 / dt / nature::EARTH_GRAVITY;
|
||||||
for (v, mut hp, mut gforce) in &mut q_actor {
|
for (v, mut hp, mut gforce) in &mut q_actor {
|
||||||
gforce.gforce = factor * (v.0 - gforce.last_linear_velocity).length() as f32;
|
gforce.gforce = factor
|
||||||
|
* (v.0 - gforce.last_linear_velocity - gforce.gravitational_component).length() as f32;
|
||||||
gforce.last_linear_velocity = v.0;
|
gforce.last_linear_velocity = v.0;
|
||||||
|
gforce.gravitational_component = DVec3::ZERO;
|
||||||
if gforce.ignore_gforce_seconds > 0.0 {
|
if gforce.ignore_gforce_seconds > 0.0 {
|
||||||
gforce.ignore_gforce_seconds -= dt;
|
gforce.ignore_gforce_seconds -= dt;
|
||||||
continue;
|
continue;
|
||||||
|
@ -632,3 +669,28 @@ fn handle_gforce(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_gravity(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut q_pos: Query<
|
||||||
|
(
|
||||||
|
&Position,
|
||||||
|
&mut LinearVelocity,
|
||||||
|
Option<&mut ExperiencesGForce>,
|
||||||
|
),
|
||||||
|
With<OrbitsJupiter>,
|
||||||
|
>,
|
||||||
|
jupiter_pos: Res<game::JupiterPos>,
|
||||||
|
) {
|
||||||
|
let dt = time.delta_seconds() as f64;
|
||||||
|
|
||||||
|
// this assumes prograde orbits for every object
|
||||||
|
for (pos, mut v, gforce_maybe) in &mut q_pos {
|
||||||
|
let relative_pos = pos.0 - jupiter_pos.0;
|
||||||
|
let accel = dt * nature::gravitational_acceleration(relative_pos, nature::JUPITER_MASS);
|
||||||
|
if let Some(mut gforce) = gforce_maybe {
|
||||||
|
gforce.gravitational_component += accel;
|
||||||
|
}
|
||||||
|
v.0 += accel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -416,6 +416,7 @@ pub fn apply_input_to_player(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
|
jupiter_pos: Res<game::JupiterPos>,
|
||||||
windows: Query<&Window, With<PrimaryWindow>>,
|
windows: Query<&Window, With<PrimaryWindow>>,
|
||||||
mut mouse_events: EventReader<MouseMotion>,
|
mut mouse_events: EventReader<MouseMotion>,
|
||||||
key_input: Res<ButtonInput<KeyCode>>,
|
key_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
@ -426,6 +427,7 @@ pub fn apply_input_to_player(
|
||||||
Entity,
|
Entity,
|
||||||
&Transform,
|
&Transform,
|
||||||
&mut actor::Engine,
|
&mut actor::Engine,
|
||||||
|
&Position,
|
||||||
&mut LinearVelocity,
|
&mut LinearVelocity,
|
||||||
&mut ExternalTorque,
|
&mut ExternalTorque,
|
||||||
Option<&actor::PlayerDrivesThis>,
|
Option<&actor::PlayerDrivesThis>,
|
||||||
|
@ -451,15 +453,15 @@ pub fn apply_input_to_player(
|
||||||
win_res_y = 1050.0;
|
win_res_y = 1050.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let target_v: DVec3 = if let Ok(target) = q_target.get_single() {
|
if let Ok((player_entity, player_transform, mut engine, pos, mut v, mut torque, bike)) =
|
||||||
target.0
|
|
||||||
} else {
|
|
||||||
DVec3::splat(0.0)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok((player_entity, player_transform, mut engine, mut v, mut torque, bike)) =
|
|
||||||
q_playercam.get_single_mut()
|
q_playercam.get_single_mut()
|
||||||
{
|
{
|
||||||
|
let target_v: DVec3 = if let Ok(target) = q_target.get_single() {
|
||||||
|
target.0
|
||||||
|
} else {
|
||||||
|
let relative_pos = pos.0 - jupiter_pos.0;
|
||||||
|
nature::orbital_velocity(relative_pos, nature::JUPITER_MASS)
|
||||||
|
};
|
||||||
// Handle key input
|
// Handle key input
|
||||||
if focused {
|
if focused {
|
||||||
if key_input.pressed(settings.key_forward) || settings.cruise_control_active {
|
if key_input.pressed(settings.key_forward) || settings.cruise_control_active {
|
||||||
|
|
14
src/chat.rs
14
src/chat.rs
|
@ -827,6 +827,7 @@ pub fn handle_chat_scripts(
|
||||||
mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
|
mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
|
||||||
mut ew_achievement: EventWriter<game::AchievementEvent>,
|
mut ew_achievement: EventWriter<game::AchievementEvent>,
|
||||||
id2pos: Res<game::Id2Pos>,
|
id2pos: Res<game::Id2Pos>,
|
||||||
|
id2v: Res<game::Id2V>,
|
||||||
) {
|
) {
|
||||||
for script in er_chatscript.read() {
|
for script in er_chatscript.read() {
|
||||||
// Parse the script string
|
// Parse the script string
|
||||||
|
@ -892,15 +893,22 @@ pub fn handle_chat_scripts(
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some(station) = busstop {
|
if let Some(station) = busstop {
|
||||||
if let Some(target) = id2pos.0.get(&station.to_string()) {
|
if let Some(target_pos) = id2pos.0.get(&station.to_string()) {
|
||||||
pos.0 = *target + DVec3::new(0.0, -1000.0, 0.0);
|
pos.0 = *target_pos + DVec3::new(0.0, -1000.0, 0.0);
|
||||||
v.0 = DVec3::ZERO;
|
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
"Could not determine position of actor with ID: '{}'",
|
"Could not determine position of actor with ID: '{}'",
|
||||||
station
|
station
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if let Some(target_v) = id2v.0.get(&station.to_string()) {
|
||||||
|
v.0 = *target_v;
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"Could not determine velocity of actor with ID: '{}'",
|
||||||
|
station
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error!("Invalid destination for cryotrip chat script: '{}'", param1);
|
error!("Invalid destination for cryotrip chat script: '{}'", param1);
|
||||||
}
|
}
|
||||||
|
|
27
src/cmd.rs
27
src/cmd.rs
|
@ -86,6 +86,7 @@ struct ParserState {
|
||||||
wants_maxrotation: Option<f64>,
|
wants_maxrotation: Option<f64>,
|
||||||
wants_maxvelocity: Option<f64>,
|
wants_maxvelocity: Option<f64>,
|
||||||
wants_tolookat_id: Option<String>,
|
wants_tolookat_id: Option<String>,
|
||||||
|
wants_matchvelocity_id: Option<String>,
|
||||||
collider_is_mesh: bool,
|
collider_is_mesh: bool,
|
||||||
collider_is_one_mesh_of_scene: bool,
|
collider_is_one_mesh_of_scene: bool,
|
||||||
thrust_forward: f32,
|
thrust_forward: f32,
|
||||||
|
@ -143,6 +144,7 @@ impl Default for ParserState {
|
||||||
wants_maxrotation: None,
|
wants_maxrotation: None,
|
||||||
wants_maxvelocity: None,
|
wants_maxvelocity: None,
|
||||||
wants_tolookat_id: None,
|
wants_tolookat_id: None,
|
||||||
|
wants_matchvelocity_id: None,
|
||||||
collider_is_mesh: false,
|
collider_is_mesh: false,
|
||||||
collider_is_one_mesh_of_scene: false,
|
collider_is_one_mesh_of_scene: false,
|
||||||
thrust_forward: default_engine.thrust_forward,
|
thrust_forward: default_engine.thrust_forward,
|
||||||
|
@ -582,6 +584,10 @@ pub fn load_defs(mut ew_spawn: EventWriter<SpawnEvent>) {
|
||||||
// NOTE: Will not work if the actor has no engine
|
// NOTE: Will not work if the actor has no engine
|
||||||
state.wants_tolookat_id = Some(id.to_string());
|
state.wants_tolookat_id = Some(id.to_string());
|
||||||
}
|
}
|
||||||
|
["wants", "matchvelocitywith", id] => {
|
||||||
|
// NOTE: Will not work if the actor has no engine
|
||||||
|
state.wants_matchvelocity_id = Some(id.to_string());
|
||||||
|
}
|
||||||
["armodel", asset_name] => {
|
["armodel", asset_name] => {
|
||||||
state.ar_model = Some(asset_name.to_string());
|
state.ar_model = Some(asset_name.to_string());
|
||||||
}
|
}
|
||||||
|
@ -617,6 +623,12 @@ fn spawn_entities(
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
) {
|
) {
|
||||||
for state_wrapper in er_spawn.read() {
|
for state_wrapper in er_spawn.read() {
|
||||||
|
let jupiter_pos: DVec3 = if let Some(jupiter_pos) = id2pos.0.get(ID_JUPITER) {
|
||||||
|
*jupiter_pos
|
||||||
|
} else {
|
||||||
|
warn!("Could not determine Jupiter's position");
|
||||||
|
DVec3::ZERO
|
||||||
|
};
|
||||||
let state = &state_wrapper.0;
|
let state = &state_wrapper.0;
|
||||||
let mut rotation = state.rotation;
|
let mut rotation = state.rotation;
|
||||||
if state.class == DefClass::Actor {
|
if state.class == DefClass::Actor {
|
||||||
|
@ -668,6 +680,13 @@ fn spawn_entities(
|
||||||
1.0
|
1.0
|
||||||
} * state.model_scale,
|
} * state.model_scale,
|
||||||
);
|
);
|
||||||
|
let orbits_jupiter = state.id != ID_JUPITER;
|
||||||
|
let velocity = if orbits_jupiter {
|
||||||
|
let coords = absolute_pos - jupiter_pos;
|
||||||
|
state.velocity + nature::orbital_velocity(coords, nature::JUPITER_MASS)
|
||||||
|
} else {
|
||||||
|
state.velocity
|
||||||
|
};
|
||||||
|
|
||||||
// Spawn the actor
|
// Spawn the actor
|
||||||
let actor_entity;
|
let actor_entity;
|
||||||
|
@ -680,6 +699,9 @@ fn spawn_entities(
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
actor.insert(SleepingDisabled);
|
actor.insert(SleepingDisabled);
|
||||||
|
if orbits_jupiter {
|
||||||
|
actor.insert(actor::OrbitsJupiter);
|
||||||
|
}
|
||||||
actor.insert(world::DespawnOnPlayerDeath);
|
actor.insert(world::DespawnOnPlayerDeath);
|
||||||
actor.insert(actor::HitPoints::default());
|
actor.insert(actor::HitPoints::default());
|
||||||
actor.insert(Position::from(absolute_pos));
|
actor.insert(Position::from(absolute_pos));
|
||||||
|
@ -715,7 +737,7 @@ fn spawn_entities(
|
||||||
// Physics Parameters
|
// Physics Parameters
|
||||||
if state.has_physics {
|
if state.has_physics {
|
||||||
actor.insert(RigidBody::Dynamic);
|
actor.insert(RigidBody::Dynamic);
|
||||||
actor.insert(LinearVelocity(state.velocity));
|
actor.insert(LinearVelocity(velocity));
|
||||||
actor.insert(AngularVelocity(state.angular_momentum));
|
actor.insert(AngularVelocity(state.angular_momentum));
|
||||||
actor.insert(ColliderDensity(state.density));
|
actor.insert(ColliderDensity(state.density));
|
||||||
if state.collider_is_mesh {
|
if state.collider_is_mesh {
|
||||||
|
@ -799,6 +821,9 @@ fn spawn_entities(
|
||||||
if let Some(value) = &state.wants_tolookat_id {
|
if let Some(value) = &state.wants_tolookat_id {
|
||||||
actor.insert(actor::WantsToLookAt(value.clone()));
|
actor.insert(actor::WantsToLookAt(value.clone()));
|
||||||
}
|
}
|
||||||
|
if let Some(value) = &state.wants_matchvelocity_id {
|
||||||
|
actor.insert(actor::WantsMatchVelocityWith(value.clone()));
|
||||||
|
}
|
||||||
if let Some(color) = state.light_color {
|
if let Some(color) = state.light_color {
|
||||||
actor.insert((
|
actor.insert((
|
||||||
PointLight {
|
PointLight {
|
||||||
|
|
|
@ -122,11 +122,11 @@ actor 0 0 0
|
||||||
only_in_map_at_dist 1e7 amalthea
|
only_in_map_at_dist 1e7 amalthea
|
||||||
clickable no
|
clickable no
|
||||||
physics off
|
physics off
|
||||||
actor 0 127093 0 moonlet
|
actor 0 0 0 moonlet
|
||||||
name Thebe
|
name Thebe
|
||||||
relativeto jupiter
|
relativeto jupiter
|
||||||
id thebe
|
id thebe
|
||||||
orbit 221900e3 0.34
|
orbitaround jupiter 221900e3
|
||||||
scale 50e3
|
scale 50e3
|
||||||
moon yes
|
moon yes
|
||||||
angularmomentum 0 0.025 0
|
angularmomentum 0 0.025 0
|
||||||
|
@ -256,10 +256,11 @@ actor 0 0 0
|
||||||
physics off
|
physics off
|
||||||
|
|
||||||
|
|
||||||
actor 0 593051 0 suitv2
|
actor 0 59305 0 suitv2
|
||||||
template person
|
template person
|
||||||
relativeto jupiter
|
relativeto jupiter
|
||||||
orbit 221900e3 0.338
|
orbitaround jupiter 221900e3
|
||||||
|
orbit_phase_offset 0.002
|
||||||
player yes
|
player yes
|
||||||
id player
|
id player
|
||||||
wants maxvelocity none
|
wants maxvelocity none
|
||||||
|
@ -287,6 +288,7 @@ actor -55e3 44e3 0 suitv2
|
||||||
name "Yuni"
|
name "Yuni"
|
||||||
chatid Yuni
|
chatid Yuni
|
||||||
rotationx 180
|
rotationx 180
|
||||||
|
wants matchvelocitywith thebe
|
||||||
|
|
||||||
actor 5000 0 -3000 moonlet
|
actor 5000 0 -3000 moonlet
|
||||||
name Moonlet
|
name Moonlet
|
||||||
|
@ -308,12 +310,14 @@ actor 13200 300 -3000 hollow_asteroid
|
||||||
actor 0 0 0 suitv2
|
actor 0 0 0 suitv2
|
||||||
template person
|
template person
|
||||||
relativeto cultasteroid
|
relativeto cultasteroid
|
||||||
|
wants matchvelocitywith cultasteroid
|
||||||
name "Ash"
|
name "Ash"
|
||||||
chatid Ash
|
chatid Ash
|
||||||
pronoun they
|
pronoun they
|
||||||
actor -8 8 0 suitv2
|
actor -8 8 0 suitv2
|
||||||
template person
|
template person
|
||||||
relativeto cultasteroid
|
relativeto cultasteroid
|
||||||
|
wants matchvelocitywith cultasteroid
|
||||||
name "River"
|
name "River"
|
||||||
chatid River
|
chatid River
|
||||||
rotationy 54
|
rotationy 54
|
||||||
|
@ -442,6 +446,7 @@ actor -3300 10 0 pizzeria
|
||||||
relativeto pizzeria
|
relativeto pizzeria
|
||||||
armodel clippy_ar
|
armodel clippy_ar
|
||||||
wants lookat PLAYERCAMERA
|
wants lookat PLAYERCAMERA
|
||||||
|
wants matchvelocitywith pizzeria
|
||||||
rotationy -126
|
rotationy -126
|
||||||
chatid SubduedClippy
|
chatid SubduedClippy
|
||||||
|
|
||||||
|
@ -452,6 +457,7 @@ actor -3300 10 0 pizzeria
|
||||||
chatid PizzaChef
|
chatid PizzaChef
|
||||||
armodel suit_ar_chefhat
|
armodel suit_ar_chefhat
|
||||||
wants lookat PLAYERCAMERA
|
wants lookat PLAYERCAMERA
|
||||||
|
wants matchvelocitywith pizzeria
|
||||||
rotationy -90
|
rotationy -90
|
||||||
pronoun he
|
pronoun he
|
||||||
|
|
||||||
|
@ -464,6 +470,7 @@ actor 30 -12 -40 suitv2
|
||||||
armodel suit_ar_wings
|
armodel suit_ar_wings
|
||||||
angularmomentum 0.4 0.2 0.1
|
angularmomentum 0.4 0.2 0.1
|
||||||
wants maxrotation 0.5
|
wants maxrotation 0.5
|
||||||
|
wants matchvelocitywith pizzeria
|
||||||
rotationy 108
|
rotationy 108
|
||||||
rotationx 180
|
rotationx 180
|
||||||
pronoun it
|
pronoun it
|
||||||
|
@ -495,6 +502,7 @@ actor -300 0 40 suitv2
|
||||||
name "梓涵"
|
name "梓涵"
|
||||||
chatid Drifter
|
chatid Drifter
|
||||||
alive no
|
alive no
|
||||||
|
wants maxvelocity none
|
||||||
oxygen 0.08
|
oxygen 0.08
|
||||||
pronoun she
|
pronoun she
|
||||||
|
|
||||||
|
@ -505,12 +513,14 @@ actor 100 -18000 2000 clippy
|
||||||
name "StarTrans Clippy™ Serenity Station"
|
name "StarTrans Clippy™ Serenity Station"
|
||||||
armodel clippy_ar
|
armodel clippy_ar
|
||||||
wants lookat PLAYERCAMERA
|
wants lookat PLAYERCAMERA
|
||||||
|
wants matchvelocitywith orbbusstopserenity
|
||||||
rotationy -90
|
rotationy -90
|
||||||
chatid ClippyTransSerenity
|
chatid ClippyTransSerenity
|
||||||
|
|
||||||
actor 60 0 0 "orb_busstop"
|
actor 60 0 0 "orb_busstop"
|
||||||
name "StarTrans Bus Stop: Serenity Station"
|
name "StarTrans Bus Stop: Serenity Station"
|
||||||
relativeto busstopclippy
|
relativeto busstopclippy
|
||||||
|
id orbbusstopserenity
|
||||||
scale 5
|
scale 5
|
||||||
actor 80 0 0 "orb_busstop"
|
actor 80 0 0 "orb_busstop"
|
||||||
name "StarTrans Bus Stop: Serenity Station"
|
name "StarTrans Bus Stop: Serenity Station"
|
||||||
|
@ -637,6 +647,7 @@ actor 100 -18000 2000 clippy
|
||||||
actor 8 20 0 suitv2
|
actor 8 20 0 suitv2
|
||||||
template person
|
template person
|
||||||
relativeto "busstopclippy"
|
relativeto "busstopclippy"
|
||||||
|
wants matchvelocitywith orbbusstopserenity
|
||||||
name "Rudy"
|
name "Rudy"
|
||||||
chatid NPCinCryoStasis
|
chatid NPCinCryoStasis
|
||||||
pronoun he
|
pronoun he
|
||||||
|
@ -648,12 +659,14 @@ actor -184971e3 149410e3 -134273e3 clippy
|
||||||
name "StarTrans Clippy™ Farview Station"
|
name "StarTrans Clippy™ Farview Station"
|
||||||
armodel clippy_ar
|
armodel clippy_ar
|
||||||
wants lookat PLAYERCAMERA
|
wants lookat PLAYERCAMERA
|
||||||
|
wants matchvelocitywith orbbusstopfarview
|
||||||
rotationy -90
|
rotationy -90
|
||||||
chatid ClippyTransFarview
|
chatid ClippyTransFarview
|
||||||
|
|
||||||
actor 60 0 0 "orb_busstop"
|
actor 60 0 0 "orb_busstop"
|
||||||
name "StarTrans Bus Stop: Farview Station"
|
name "StarTrans Bus Stop: Farview Station"
|
||||||
relativeto busstopclippy2
|
relativeto busstopclippy2
|
||||||
|
id orbbusstopfarview
|
||||||
scale 5
|
scale 5
|
||||||
actor 80 0 0 "orb_busstop"
|
actor 80 0 0 "orb_busstop"
|
||||||
name "StarTrans Bus Stop: Farview Station"
|
name "StarTrans Bus Stop: Farview Station"
|
||||||
|
@ -785,6 +798,7 @@ actor 0 -44e3 0 clippy
|
||||||
name "StarTrans Clippy™ Metis Prime Station"
|
name "StarTrans Clippy™ Metis Prime Station"
|
||||||
armodel clippy_ar
|
armodel clippy_ar
|
||||||
wants lookat PLAYERCAMERA
|
wants lookat PLAYERCAMERA
|
||||||
|
wants matchvelocitywith orbbusstopmetis
|
||||||
orbitaround jupiter 128000e3
|
orbitaround jupiter 128000e3
|
||||||
orbit_phase_offset -0.002
|
orbit_phase_offset -0.002
|
||||||
rotationy -90
|
rotationy -90
|
||||||
|
@ -793,6 +807,7 @@ actor 0 -44e3 0 clippy
|
||||||
actor 60 0 0 "orb_busstop"
|
actor 60 0 0 "orb_busstop"
|
||||||
name "StarTrans Bus Stop: Metis Prime Station"
|
name "StarTrans Bus Stop: Metis Prime Station"
|
||||||
relativeto busstopclippy3
|
relativeto busstopclippy3
|
||||||
|
id orbbusstopmetis
|
||||||
scale 5
|
scale 5
|
||||||
actor 80 0 0 "orb_busstop"
|
actor 80 0 0 "orb_busstop"
|
||||||
name "StarTrans Bus Stop: Metis Prime Station"
|
name "StarTrans Bus Stop: Metis Prime Station"
|
||||||
|
|
46
src/game.rs
46
src/game.rs
|
@ -18,6 +18,10 @@ use bevy::window::{PrimaryWindow, Window, WindowMode};
|
||||||
use bevy_xpbd_3d::prelude::*;
|
use bevy_xpbd_3d::prelude::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub const CHEAT_WARP_1: &str = "pizzeria";
|
||||||
|
pub const CHEAT_WARP_2: &str = "busstopclippy2";
|
||||||
|
pub const CHEAT_WARP_3: &str = "busstopclippy3";
|
||||||
|
|
||||||
pub struct GamePlugin;
|
pub struct GamePlugin;
|
||||||
impl Plugin for GamePlugin {
|
impl Plugin for GamePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
|
@ -26,12 +30,15 @@ impl Plugin for GamePlugin {
|
||||||
app.add_systems(PostUpdate, handle_game_event);
|
app.add_systems(PostUpdate, handle_game_event);
|
||||||
app.add_systems(PreUpdate, handle_player_death);
|
app.add_systems(PreUpdate, handle_player_death);
|
||||||
app.add_systems(PostUpdate, update_id2pos);
|
app.add_systems(PostUpdate, update_id2pos);
|
||||||
|
app.add_systems(PostUpdate, update_id2v);
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
Update,
|
Update,
|
||||||
handle_achievement_event.run_if(on_event::<AchievementEvent>()),
|
handle_achievement_event.run_if(on_event::<AchievementEvent>()),
|
||||||
);
|
);
|
||||||
app.add_systems(Update, check_achievements);
|
app.add_systems(Update, check_achievements);
|
||||||
app.insert_resource(Id2Pos(HashMap::new()));
|
app.insert_resource(Id2Pos(HashMap::new()));
|
||||||
|
app.insert_resource(Id2V(HashMap::new()));
|
||||||
|
app.insert_resource(JupiterPos(DVec3::ZERO));
|
||||||
app.insert_resource(var::AchievementTracker::default());
|
app.insert_resource(var::AchievementTracker::default());
|
||||||
app.insert_resource(var::Settings::default());
|
app.insert_resource(var::Settings::default());
|
||||||
app.insert_resource(var::GameVars::default());
|
app.insert_resource(var::GameVars::default());
|
||||||
|
@ -50,6 +57,10 @@ pub struct PlayerDiesEvent(pub actor::DamageType);
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct Id2Pos(pub HashMap<String, DVec3>);
|
pub struct Id2Pos(pub HashMap<String, DVec3>);
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
|
pub struct Id2V(pub HashMap<String, DVec3>);
|
||||||
|
#[derive(Resource)]
|
||||||
|
pub struct JupiterPos(pub DVec3);
|
||||||
|
#[derive(Resource)]
|
||||||
pub struct AchievementCheckTimer(pub Timer);
|
pub struct AchievementCheckTimer(pub Timer);
|
||||||
|
|
||||||
#[derive(Event)]
|
#[derive(Event)]
|
||||||
|
@ -260,7 +271,9 @@ fn handle_cheats(
|
||||||
>,
|
>,
|
||||||
mut ew_playerdies: EventWriter<PlayerDiesEvent>,
|
mut ew_playerdies: EventWriter<PlayerDiesEvent>,
|
||||||
mut settings: ResMut<Settings>,
|
mut settings: ResMut<Settings>,
|
||||||
|
jupiter_pos: Res<JupiterPos>,
|
||||||
id2pos: Res<Id2Pos>,
|
id2pos: Res<Id2Pos>,
|
||||||
|
id2v: Res<Id2V>,
|
||||||
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
|
||||||
) {
|
) {
|
||||||
if q_player.is_empty() || q_life.is_empty() {
|
if q_player.is_empty() || q_life.is_empty() {
|
||||||
|
@ -285,7 +298,7 @@ fn handle_cheats(
|
||||||
|
|
||||||
if key_input.just_pressed(settings.key_cheat_stop) {
|
if key_input.just_pressed(settings.key_cheat_stop) {
|
||||||
gforce.ignore_gforce_seconds = 1.0;
|
gforce.ignore_gforce_seconds = 1.0;
|
||||||
v.0 = DVec3::ZERO;
|
v.0 = nature::orbital_velocity(pos.0 - jupiter_pos.0, nature::JUPITER_MASS);
|
||||||
}
|
}
|
||||||
if key_input.pressed(settings.key_cheat_speed)
|
if key_input.pressed(settings.key_cheat_speed)
|
||||||
|| key_input.pressed(settings.key_cheat_speed_backward)
|
|| key_input.pressed(settings.key_cheat_speed_backward)
|
||||||
|
@ -319,22 +332,31 @@ fn handle_cheats(
|
||||||
}
|
}
|
||||||
|
|
||||||
if key_input.just_pressed(settings.key_cheat_pizza) {
|
if key_input.just_pressed(settings.key_cheat_pizza) {
|
||||||
if let Some(target) = id2pos.0.get(&"pizzeria".to_string()) {
|
if let Some(target) = id2pos.0.get(&CHEAT_WARP_1.to_string()) {
|
||||||
pos.0 = *target + DVec3::new(-60.0, 0.0, 0.0);
|
pos.0 = *target + DVec3::new(-60.0, 0.0, 0.0);
|
||||||
gforce.ignore_gforce_seconds = 1.0;
|
gforce.ignore_gforce_seconds = 1.0;
|
||||||
}
|
}
|
||||||
|
if let Some(target) = id2v.0.get(&CHEAT_WARP_1.to_string()) {
|
||||||
|
v.0 = *target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if key_input.just_pressed(settings.key_cheat_farview1) {
|
if key_input.just_pressed(settings.key_cheat_farview1) {
|
||||||
if let Some(target) = id2pos.0.get(&"busstopclippy2".to_string()) {
|
if let Some(target) = id2pos.0.get(&CHEAT_WARP_2.to_string()) {
|
||||||
pos.0 = *target + DVec3::new(0.0, -1000.0, 0.0);
|
pos.0 = *target + DVec3::new(0.0, -1000.0, 0.0);
|
||||||
gforce.ignore_gforce_seconds = 1.0;
|
gforce.ignore_gforce_seconds = 1.0;
|
||||||
}
|
}
|
||||||
|
if let Some(target) = id2v.0.get(&CHEAT_WARP_2.to_string()) {
|
||||||
|
v.0 = *target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if key_input.just_pressed(settings.key_cheat_farview2) {
|
if key_input.just_pressed(settings.key_cheat_farview2) {
|
||||||
if let Some(target) = id2pos.0.get(&"busstopclippy3".to_string()) {
|
if let Some(target) = id2pos.0.get(&CHEAT_WARP_3.to_string()) {
|
||||||
pos.0 = *target + DVec3::new(0.0, -1000.0, 0.0);
|
pos.0 = *target + DVec3::new(0.0, -1000.0, 0.0);
|
||||||
gforce.ignore_gforce_seconds = 1.0;
|
gforce.ignore_gforce_seconds = 1.0;
|
||||||
}
|
}
|
||||||
|
if let Some(target) = id2v.0.get(&CHEAT_WARP_3.to_string()) {
|
||||||
|
v.0 = *target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if key_input.pressed(settings.key_cheat_adrenaline_zero) {
|
if key_input.pressed(settings.key_cheat_adrenaline_zero) {
|
||||||
lifeform.adrenaline = 0.0;
|
lifeform.adrenaline = 0.0;
|
||||||
|
@ -351,10 +373,24 @@ fn handle_cheats(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_id2pos(mut id2pos: ResMut<Id2Pos>, q_id: Query<(&Position, &actor::Identifier)>) {
|
fn update_id2pos(
|
||||||
|
mut id2pos: ResMut<Id2Pos>,
|
||||||
|
mut jupiterpos: ResMut<JupiterPos>,
|
||||||
|
q_id: Query<(&Position, &actor::Identifier)>,
|
||||||
|
) {
|
||||||
id2pos.0.clear();
|
id2pos.0.clear();
|
||||||
for (pos, id) in &q_id {
|
for (pos, id) in &q_id {
|
||||||
id2pos.0.insert(id.0.clone(), pos.0);
|
id2pos.0.insert(id.0.clone(), pos.0);
|
||||||
|
if id.0 == "jupiter" {
|
||||||
|
jupiterpos.0 = pos.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_id2v(mut id2v: ResMut<Id2V>, q_id: Query<(&LinearVelocity, &actor::Identifier)>) {
|
||||||
|
id2v.0.clear();
|
||||||
|
for (v, id) in &q_id {
|
||||||
|
id2v.0.insert(id.0.clone(), v.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -707,7 +707,8 @@ fn update_dashboard(
|
||||||
fn update_speedometer(
|
fn update_speedometer(
|
||||||
timer: ResMut<FPSUpdateTimer>,
|
timer: ResMut<FPSUpdateTimer>,
|
||||||
settings: Res<Settings>,
|
settings: Res<Settings>,
|
||||||
q_camera: Query<&LinearVelocity, With<actor::PlayerCamera>>,
|
jupiter_pos: Res<game::JupiterPos>,
|
||||||
|
q_camera: Query<(&LinearVelocity, &Position), With<actor::PlayerCamera>>,
|
||||||
q_player: Query<&actor::ExperiencesGForce, With<actor::Player>>,
|
q_player: Query<&actor::ExperiencesGForce, With<actor::Player>>,
|
||||||
q_target: Query<&LinearVelocity, With<IsTargeted>>,
|
q_target: Query<&LinearVelocity, With<IsTargeted>>,
|
||||||
mut q_speedometer: Query<&mut Style, (With<Speedometer>, Without<Speedometer2>)>,
|
mut q_speedometer: Query<&mut Style, (With<Speedometer>, Without<Speedometer2>)>,
|
||||||
|
@ -717,8 +718,9 @@ fn update_speedometer(
|
||||||
if !settings.hud_active || !timer.0.just_finished() {
|
if !settings.hud_active || !timer.0.just_finished() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Ok(cam_v) = q_camera.get_single() {
|
if let Ok((cam_v, pos)) = q_camera.get_single() {
|
||||||
let speed = cam_v.length();
|
let orbital_v = nature::orbital_velocity(pos.0 - jupiter_pos.0, nature::JUPITER_MASS);
|
||||||
|
let speed = (cam_v.0 - orbital_v).length();
|
||||||
|
|
||||||
let speedometer_split = 5_000.0;
|
let speedometer_split = 5_000.0;
|
||||||
if let Ok(mut speedometer) = q_speedometer.get_single_mut() {
|
if let Ok(mut speedometer) = q_speedometer.get_single_mut() {
|
||||||
|
|
|
@ -27,9 +27,11 @@ pub const G: f64 = 6.6743015e-11; // Gravitational constant in Nm²/kg²
|
||||||
pub const SOL_RADIUS: f64 = 696_300_000.0;
|
pub const SOL_RADIUS: f64 = 696_300_000.0;
|
||||||
pub const JUPITER_RADIUS: f64 = 71_492_000.0;
|
pub const JUPITER_RADIUS: f64 = 71_492_000.0;
|
||||||
pub const JUPITER_RING_RADIUS: f64 = 229_000_000.0;
|
pub const JUPITER_RING_RADIUS: f64 = 229_000_000.0;
|
||||||
|
pub const EARTH_RADIUS: f64 = 6_371_000.0;
|
||||||
|
|
||||||
pub const SOL_MASS: f64 = 1.9885e30;
|
pub const SOL_MASS: f64 = 1.9885e30;
|
||||||
pub const JUPITER_MASS: f64 = 1.8982e27;
|
pub const JUPITER_MASS: f64 = 1.8982e27;
|
||||||
|
pub const EARTH_MASS: f64 = 5.972168e24;
|
||||||
|
|
||||||
// Each star's values: (x, y, z, magnitude, color index, distance, name)
|
// Each star's values: (x, y, z, magnitude, color index, distance, name)
|
||||||
pub const STARS: &[(f32, f32, f32, f32, f32, f32, &str)] = &include!("data/stars.in");
|
pub const STARS: &[(f32, f32, f32, f32, f32, f32, &str)] = &include!("data/stars.in");
|
||||||
|
@ -163,10 +165,38 @@ pub fn inverse_lorentz_factor_custom_c(speed: f64, c: f64) -> f64 {
|
||||||
(1.0 - (speed.powf(2.0) / c.powf(2.0))).sqrt()
|
(1.0 - (speed.powf(2.0) / c.powf(2.0))).sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculates orbit duration in seconds, with given parameters, assuming circular orbit.
|
||||||
pub fn simple_orbital_period(mass: f64, distance: f64) -> f64 {
|
pub fn simple_orbital_period(mass: f64, distance: f64) -> f64 {
|
||||||
return 2.0 * PI * (distance.powf(3.0) / (G * mass)).sqrt();
|
return 2.0 * PI * (distance.powf(3.0) / (G * mass)).sqrt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculates the orbital velocity with given parameters, assuming prograde circular orbit.
|
||||||
|
pub fn orbital_velocity(coords: DVec3, mass: f64) -> DVec3 {
|
||||||
|
let r = coords.length();
|
||||||
|
let speed = (G * mass / r).sqrt();
|
||||||
|
|
||||||
|
// This generates a perpendicular orbital vector in the prograde direction
|
||||||
|
let perpendicular = DVec3::new(coords.z, 0.0, -coords.x).normalize();
|
||||||
|
|
||||||
|
return perpendicular * speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates the acceleration towards a mass in m/s
|
||||||
|
pub fn gravitational_acceleration(coords: DVec3, mass: f64) -> DVec3 {
|
||||||
|
let r_squared = coords.length_squared();
|
||||||
|
let acceleration_magnitude = G * mass / r_squared;
|
||||||
|
return -acceleration_magnitude * (coords / r_squared.sqrt());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gravitational_acceleration() {
|
||||||
|
let coords = DVec3::new(EARTH_RADIUS, 0.0, 0.0);
|
||||||
|
let mass = EARTH_MASS;
|
||||||
|
let g = gravitational_acceleration(coords, mass);
|
||||||
|
let g_rounded = (g * 10.0).round() / 10.0;
|
||||||
|
assert_eq!(g_rounded, DVec3::new(-9.8, 0.0, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn phase_dist_to_coords(phase_radians: f64, distance: f64) -> DVec3 {
|
pub fn phase_dist_to_coords(phase_radians: f64, distance: f64) -> DVec3 {
|
||||||
return DVec3::new(
|
return DVec3::new(
|
||||||
distance * phase_radians.cos(),
|
distance * phase_radians.cos(),
|
||||||
|
|
19
src/world.rs
19
src/world.rs
|
@ -19,6 +19,7 @@ use bevy_xpbd_3d::prelude::*;
|
||||||
use fastrand;
|
use fastrand;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
const ENABLE_ASTEROIDS: bool = false;
|
||||||
const ASTEROID_UPDATE_INTERVAL: f32 = 0.1; // seconds
|
const ASTEROID_UPDATE_INTERVAL: f32 = 0.1; // seconds
|
||||||
const ASTEROID_SIZE_FACTOR: f32 = 10.0;
|
const ASTEROID_SIZE_FACTOR: f32 = 10.0;
|
||||||
const RING_THICKNESS: f64 = 8.0e6;
|
const RING_THICKNESS: f64 = 8.0e6;
|
||||||
|
@ -36,19 +37,21 @@ pub struct WorldPlugin;
|
||||||
impl Plugin for WorldPlugin {
|
impl Plugin for WorldPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(Startup, setup);
|
app.add_systems(Startup, setup);
|
||||||
app.add_systems(PostUpdate, handle_despawn);
|
|
||||||
app.add_systems(Update, spawn_despawn_asteroids);
|
|
||||||
app.add_systems(Update, handle_respawn.run_if(on_event::<RespawnEvent>()));
|
app.add_systems(Update, handle_respawn.run_if(on_event::<RespawnEvent>()));
|
||||||
app.add_plugins(PhysicsPlugins::default());
|
app.add_plugins(PhysicsPlugins::default());
|
||||||
//app.add_plugins(PhysicsDebugPlugin::default());
|
//app.add_plugins(PhysicsDebugPlugin::default());
|
||||||
app.insert_resource(Gravity(DVec3::splat(0.0)));
|
app.insert_resource(Gravity(DVec3::splat(0.0)));
|
||||||
app.insert_resource(AsteroidUpdateTimer(Timer::from_seconds(
|
|
||||||
ASTEROID_UPDATE_INTERVAL,
|
|
||||||
TimerMode::Repeating,
|
|
||||||
)));
|
|
||||||
app.insert_resource(ActiveAsteroids(HashMap::new()));
|
app.insert_resource(ActiveAsteroids(HashMap::new()));
|
||||||
app.add_event::<DespawnAsteroidEvent>();
|
|
||||||
app.add_event::<RespawnEvent>();
|
app.add_event::<RespawnEvent>();
|
||||||
|
if ENABLE_ASTEROIDS {
|
||||||
|
app.insert_resource(AsteroidUpdateTimer(Timer::from_seconds(
|
||||||
|
ASTEROID_UPDATE_INTERVAL,
|
||||||
|
TimerMode::Repeating,
|
||||||
|
)));
|
||||||
|
app.add_systems(Update, spawn_despawn_asteroids);
|
||||||
|
app.add_systems(PostUpdate, handle_despawn_asteroids);
|
||||||
|
app.add_event::<DespawnAsteroidEvent>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +347,7 @@ fn spawn_despawn_asteroids(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_despawn(
|
fn handle_despawn_asteroids(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut er_despawn: EventReader<DespawnAsteroidEvent>,
|
mut er_despawn: EventReader<DespawnAsteroidEvent>,
|
||||||
mut db: ResMut<ActiveAsteroids>,
|
mut db: ResMut<ActiveAsteroids>,
|
||||||
|
|
Loading…
Reference in a new issue