Compare commits
7 commits
ac44f4ee4f
...
7e7b8e7432
Author | SHA1 | Date | |
---|---|---|---|
yuni | 7e7b8e7432 | ||
yuni | 4f71f833fb | ||
yuni | b01823c641 | ||
yuni | dcb6e6e5a9 | ||
yuni | 904f7927eb | ||
yuni | 06a0bf3984 | ||
yuni | 5dcfbaf591 |
|
@ -1,3 +1,7 @@
|
||||||
|
# v0.11.1
|
||||||
|
|
||||||
|
- Fixed radio stations
|
||||||
|
|
||||||
# v0.11.0
|
# v0.11.0
|
||||||
|
|
||||||
- Upgrade to Bevy 0.14.2, Rust 1.81
|
- Upgrade to Bevy 0.14.2, Rust 1.81
|
||||||
|
|
BIN
assets/textures/exhaust.png
Normal file
BIN
assets/textures/exhaust.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -46,6 +46,8 @@ We are not quite there yet, but this is what I'm aiming for:
|
||||||
- No anxiety-causing features
|
- No anxiety-causing features
|
||||||
- No DRM
|
- No DRM
|
||||||
- No paid features
|
- No paid features
|
||||||
|
- All source code and assets are ["free" as defined by the FSF](https://www.gnu.org/licenses/license-list.html)
|
||||||
|
- Obviously, space as a whole is not exactly wholesome. Space is a death trap. This should still be felt by the player, it's a space simulation after all.
|
||||||
- Non-addictiveness
|
- Non-addictiveness
|
||||||
- No features that manipulate the player into neglecting their life responsibilities in favor of the game
|
- No features that manipulate the player into neglecting their life responsibilities in favor of the game
|
||||||
- No artificially long game progression
|
- No artificially long game progression
|
||||||
|
|
16
src/actor.rs
16
src/actor.rs
|
@ -599,8 +599,9 @@ fn handle_wants_maxvelocity(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_wants_lookat(
|
fn handle_wants_lookat(
|
||||||
mut query: Query<(&Position, &mut Rotation, &Transform, &WantsToLookAt)>,
|
mut query: Query<(&Position, &mut Rotation, &Transform, &WantsToLookAt), Without<Camera>>,
|
||||||
q_playercam: Query<&Position, With<PlayerCamera>>,
|
q_playercam: Query<&Position, With<PlayerCamera>>,
|
||||||
|
q_cam: Query<&Transform, With<Camera>>,
|
||||||
id2pos: Res<game::Id2Pos>,
|
id2pos: Res<game::Id2Pos>,
|
||||||
) {
|
) {
|
||||||
let player_pos = if let Ok(player_pos) = q_playercam.get_single() {
|
let player_pos = if let Ok(player_pos) = q_playercam.get_single() {
|
||||||
|
@ -608,17 +609,22 @@ fn handle_wants_lookat(
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let cam_pos = if let Ok(cam_trans) = q_cam.get_single() {
|
||||||
|
cam_trans.translation.as_dvec3() + player_pos.0
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: use ExternalTorque rather than hard-resetting the rotation
|
// TODO: use ExternalTorque rather than hard-resetting the rotation
|
||||||
for (pos, mut rot, trans, target_id) in &mut query {
|
for (pos, mut rot, trans, target_id) in &mut query {
|
||||||
let target_pos = if target_id.0 == cmd::ID_SPECIAL_PLAYERCAM {
|
let target_pos: DVec3 = if target_id.0 == cmd::ID_SPECIAL_PLAYERCAM {
|
||||||
player_pos
|
cam_pos
|
||||||
} else if let Some(target_pos) = id2pos.0.get(&target_id.0) {
|
} else if let Some(target_pos) = id2pos.0.get(&target_id.0) {
|
||||||
target_pos
|
*target_pos
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
rot.0 = look_at_quat(**pos, *target_pos, trans.up().as_dvec3());
|
rot.0 = look_at_quat(**pos, target_pos, trans.up().as_dvec3());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -430,6 +430,7 @@ pub fn apply_input_to_player(
|
||||||
(&Position, &LinearVelocity),
|
(&Position, &LinearVelocity),
|
||||||
(
|
(
|
||||||
Without<hud::IsTargeted>,
|
Without<hud::IsTargeted>,
|
||||||
|
Without<visual::IsEffect>,
|
||||||
Without<actor::PlayerCamera>,
|
Without<actor::PlayerCamera>,
|
||||||
Without<actor::Player>,
|
Without<actor::Player>,
|
||||||
Without<actor::PlayerDrivesThis>,
|
Without<actor::PlayerDrivesThis>,
|
||||||
|
@ -447,6 +448,7 @@ pub fn apply_input_to_player(
|
||||||
),
|
),
|
||||||
(With<actor::PlayerCamera>, Without<Camera>),
|
(With<actor::PlayerCamera>, Without<Camera>),
|
||||||
>,
|
>,
|
||||||
|
mut ew_effect: EventWriter<visual::SpawnEffectEvent>,
|
||||||
) {
|
) {
|
||||||
if settings.map_active || !settings.in_control() {
|
if settings.map_active || !settings.in_control() {
|
||||||
return;
|
return;
|
||||||
|
@ -564,6 +566,16 @@ pub fn apply_input_to_player(
|
||||||
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);
|
||||||
play_thruster_sound = true;
|
play_thruster_sound = true;
|
||||||
|
|
||||||
|
// Visual effect
|
||||||
|
if acceleration_total.length_squared() > 1e-4 {
|
||||||
|
let thruster_direction = acceleration_total.normalize();
|
||||||
|
let thruster_v = v.0 - 10.0 * thruster_direction;
|
||||||
|
ew_effect.send(visual::SpawnEffectEvent {
|
||||||
|
duration: 2.0,
|
||||||
|
class: visual::Effects::ThrusterParticle(pos.clone(), LinearVelocity::from(thruster_v)),
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
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);
|
||||||
|
|
|
@ -110,6 +110,10 @@ pub fn in_shadow(
|
||||||
|
|
||||||
pub fn look_at_quat(from: DVec3, to: DVec3, up: DVec3) -> DQuat {
|
pub fn look_at_quat(from: DVec3, to: DVec3, up: DVec3) -> DQuat {
|
||||||
let direction = (to - from).normalize();
|
let direction = (to - from).normalize();
|
||||||
|
let direction_len = direction.length_squared();
|
||||||
|
if direction_len < 1e-4 || direction_len.is_nan() {
|
||||||
|
return DQuat::IDENTITY;
|
||||||
|
}
|
||||||
let right = up.cross(direction).normalize();
|
let right = up.cross(direction).normalize();
|
||||||
let corrected_up = direction.cross(right);
|
let corrected_up = direction.cross(right);
|
||||||
|
|
||||||
|
|
26
src/game.rs
26
src/game.rs
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bevy::color::palettes::css;
|
use bevy::color::palettes::css;
|
||||||
use bevy::pbr::ExtendedMaterial;
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::scene::SceneInstance;
|
use bevy::scene::SceneInstance;
|
||||||
use bevy::window::{PrimaryWindow, Window, WindowMode};
|
use bevy::window::{PrimaryWindow, Window, WindowMode};
|
||||||
|
@ -471,22 +470,23 @@ fn update_id2v(mut id2v: ResMut<Id2V>, q_id: Query<(&LinearVelocity, &actor::Ide
|
||||||
fn debug(
|
fn debug(
|
||||||
settings: Res<var::Settings>,
|
settings: Res<var::Settings>,
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mut commands: Commands,
|
// mut commands: Commands,
|
||||||
mut extended_materials: ResMut<
|
// mut extended_materials: ResMut<
|
||||||
Assets<ExtendedMaterial<StandardMaterial, load::AsteroidSurface>>,
|
// Assets<bevy::pbr::ExtendedMaterial<StandardMaterial, load::AsteroidSurface>>,
|
||||||
>,
|
// >,
|
||||||
mut achievement_tracker: ResMut<var::AchievementTracker>,
|
mut achievement_tracker: ResMut<var::AchievementTracker>,
|
||||||
vars: Res<var::GameVars>,
|
vars: Res<var::GameVars>,
|
||||||
materials: Query<(Entity, Option<&Name>, &Handle<Mesh>)>,
|
// materials: Query<(Entity, Option<&Name>, &Handle<Mesh>)>,
|
||||||
) {
|
) {
|
||||||
if settings.dev_mode && keyboard_input.just_pressed(KeyCode::KeyP) {
|
if settings.dev_mode && keyboard_input.just_pressed(KeyCode::KeyP) {
|
||||||
for (entity, _name, mesh) in &materials {
|
|
||||||
dbg!(mesh);
|
// for (entity, _name, mesh) in &materials {
|
||||||
let mut entity = commands.entity(entity);
|
// dbg!(mesh);
|
||||||
entity.remove::<Handle<StandardMaterial>>();
|
// let mut entity = commands.entity(entity);
|
||||||
let material = extended_materials.add(load::AsteroidSurface::material());
|
// entity.remove::<Handle<StandardMaterial>>();
|
||||||
entity.insert(material);
|
// let material = extended_materials.add(load::AsteroidSurface::material());
|
||||||
}
|
// entity.insert(material);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
if settings.dev_mode && keyboard_input.just_pressed(KeyCode::KeyN) {
|
if settings.dev_mode && keyboard_input.just_pressed(KeyCode::KeyN) {
|
||||||
achievement_tracker.achieve_all();
|
achievement_tracker.achieve_all();
|
||||||
|
|
|
@ -475,7 +475,7 @@ pub fn update_menu(
|
||||||
} else {
|
} else {
|
||||||
&settings.radio_modes[0]
|
&settings.radio_modes[0]
|
||||||
};
|
};
|
||||||
text.sections[i].value = format!("Radio: {station}\n");
|
text.sections[i].value = format!("Speakers: {station}\n");
|
||||||
}
|
}
|
||||||
MenuAction::ToggleAR => {
|
MenuAction::ToggleAR => {
|
||||||
let onoff = bool2string(settings.hud_active);
|
let onoff = bool2string(settings.hud_active);
|
||||||
|
|
|
@ -177,6 +177,7 @@ impl Default for Settings {
|
||||||
radio_modes: vec![
|
radio_modes: vec![
|
||||||
// see also: settings.is_radio_playing()
|
// see also: settings.is_radio_playing()
|
||||||
"Off".to_string(),
|
"Off".to_string(),
|
||||||
|
"Space Wave Radio".to_string(),
|
||||||
"Amplify outside recordings".to_string(),
|
"Amplify outside recordings".to_string(),
|
||||||
],
|
],
|
||||||
volume_sfx: 100,
|
volume_sfx: 100,
|
||||||
|
|
121
src/visual.rs
121
src/visual.rs
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use bevy_xpbd_3d::prelude::*;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub struct VisualPlugin;
|
pub struct VisualPlugin;
|
||||||
|
@ -26,6 +27,8 @@ impl Plugin for VisualPlugin {
|
||||||
app.add_systems(Update, spawn_effects);
|
app.add_systems(Update, spawn_effects);
|
||||||
app.add_systems(Update, update_fadein);
|
app.add_systems(Update, update_fadein);
|
||||||
app.add_systems(Update, update_fadeout);
|
app.add_systems(Update, update_fadeout);
|
||||||
|
app.add_systems(Update, update_fade_material);
|
||||||
|
app.add_systems(Update, update_grow);
|
||||||
app.add_systems(Update, play_animations);
|
app.add_systems(Update, play_animations);
|
||||||
// Blackout disabled for now
|
// Blackout disabled for now
|
||||||
//app.add_systems(Update, update_blackout);
|
//app.add_systems(Update, update_blackout);
|
||||||
|
@ -37,15 +40,32 @@ impl Plugin for VisualPlugin {
|
||||||
pub enum Effects {
|
pub enum Effects {
|
||||||
FadeIn(Color),
|
FadeIn(Color),
|
||||||
FadeOut(Color),
|
FadeOut(Color),
|
||||||
|
ThrusterParticle(Position, LinearVelocity),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blackout disabled for now
|
// Blackout disabled for now
|
||||||
//#[derive(Component)] pub struct BlackOutOverlay;
|
//#[derive(Component)] pub struct BlackOutOverlay;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct FadeIn;
|
pub struct IsEffect;
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct FadeOut;
|
pub struct FadeInSprite;
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct FadeOutSprite;
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct FadeMaterial {
|
||||||
|
pub start_time: f64,
|
||||||
|
pub duration: f64,
|
||||||
|
pub value_start: f32,
|
||||||
|
pub value_end: f32,
|
||||||
|
}
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Grow3DObject {
|
||||||
|
pub start_time: f64,
|
||||||
|
pub duration: f64,
|
||||||
|
pub scale_start: f32,
|
||||||
|
pub scale_end: f32,
|
||||||
|
}
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Effect {
|
pub struct Effect {
|
||||||
pub class: Effects,
|
pub class: Effects,
|
||||||
|
@ -109,6 +129,9 @@ pub fn setup(
|
||||||
pub fn spawn_effects(
|
pub fn spawn_effects(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut er_effect: EventReader<SpawnEffectEvent>,
|
mut er_effect: EventReader<SpawnEffectEvent>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
let now = time.elapsed_seconds_f64();
|
let now = time.elapsed_seconds_f64();
|
||||||
|
@ -116,12 +139,13 @@ pub fn spawn_effects(
|
||||||
match effect.class {
|
match effect.class {
|
||||||
Effects::FadeIn(color) => {
|
Effects::FadeIn(color) => {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
|
IsEffect,
|
||||||
Effect {
|
Effect {
|
||||||
class: effect.class.clone(),
|
class: effect.class.clone(),
|
||||||
duration: effect.duration,
|
duration: effect.duration,
|
||||||
start_time: now,
|
start_time: now,
|
||||||
},
|
},
|
||||||
FadeIn,
|
FadeInSprite,
|
||||||
NodeBundle {
|
NodeBundle {
|
||||||
style: style_fullscreen(),
|
style: style_fullscreen(),
|
||||||
background_color: color.into(),
|
background_color: color.into(),
|
||||||
|
@ -131,12 +155,13 @@ pub fn spawn_effects(
|
||||||
}
|
}
|
||||||
Effects::FadeOut(color) => {
|
Effects::FadeOut(color) => {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
|
IsEffect,
|
||||||
Effect {
|
Effect {
|
||||||
class: effect.class.clone(),
|
class: effect.class.clone(),
|
||||||
duration: effect.duration,
|
duration: effect.duration,
|
||||||
start_time: now,
|
start_time: now,
|
||||||
},
|
},
|
||||||
FadeOut,
|
FadeOutSprite,
|
||||||
NodeBundle {
|
NodeBundle {
|
||||||
style: style_fullscreen(),
|
style: style_fullscreen(),
|
||||||
background_color: color.with_alpha(0.0).into(),
|
background_color: color.with_alpha(0.0).into(),
|
||||||
|
@ -144,13 +169,49 @@ pub fn spawn_effects(
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
Effects::ThrusterParticle(pos, v) => {
|
||||||
|
let texture = asset_server.load("textures/exhaust.png");
|
||||||
|
commands.spawn((
|
||||||
|
IsEffect,
|
||||||
|
RigidBody::Kinematic,
|
||||||
|
bevy::pbr::NotShadowCaster,
|
||||||
|
pos,
|
||||||
|
v,
|
||||||
|
Grow3DObject {
|
||||||
|
start_time: now,
|
||||||
|
duration: effect.duration,
|
||||||
|
scale_start: 1.0,
|
||||||
|
scale_end: 20.0,
|
||||||
|
},
|
||||||
|
FadeMaterial {
|
||||||
|
start_time: now,
|
||||||
|
duration: effect.duration,
|
||||||
|
value_start: 0.1,
|
||||||
|
value_end: 0.0,
|
||||||
|
},
|
||||||
|
world::DespawnAt(now + effect.duration),
|
||||||
|
world::DespawnOnPlayerDeath,
|
||||||
|
actor::WantsToLookAt(cmd::ID_SPECIAL_PLAYERCAM.into()),
|
||||||
|
PbrBundle {
|
||||||
|
mesh: meshes.add(Mesh::from(Rectangle::new(0.2, 0.2))),
|
||||||
|
material: materials.add(StandardMaterial {
|
||||||
|
base_color_texture: Some(texture),
|
||||||
|
perceptual_roughness: 1.0,
|
||||||
|
metallic: 0.5,
|
||||||
|
alpha_mode: AlphaMode::Blend,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_fadein(
|
pub fn update_fadein(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With<FadeIn>>,
|
mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With<FadeInSprite>>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
for (entity, effect, mut bgcolor) in &mut q_effect {
|
for (entity, effect, mut bgcolor) in &mut q_effect {
|
||||||
|
@ -166,7 +227,7 @@ pub fn update_fadein(
|
||||||
|
|
||||||
pub fn update_fadeout(
|
pub fn update_fadeout(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With<FadeOut>>,
|
mut q_effect: Query<(Entity, &Effect, &mut BackgroundColor), With<FadeOutSprite>>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
) {
|
) {
|
||||||
for (entity, effect, mut bgcolor) in &mut q_effect {
|
for (entity, effect, mut bgcolor) in &mut q_effect {
|
||||||
|
@ -180,6 +241,54 @@ pub fn update_fadeout(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_fade_material(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut q_object: Query<(Entity, &Handle<StandardMaterial>, &FadeMaterial)>,
|
||||||
|
time: Res<Time>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
let now = time.elapsed_seconds_f64();
|
||||||
|
for (entity, material_handle, data) in q_object.iter_mut() {
|
||||||
|
let end_time = data.start_time + data.duration;
|
||||||
|
let material = materials.get_mut(material_handle).unwrap();
|
||||||
|
if now > end_time {
|
||||||
|
material.base_color.set_alpha(data.value_end);
|
||||||
|
commands.entity(entity).remove::<FadeMaterial>();
|
||||||
|
}
|
||||||
|
else if now < data.start_time {
|
||||||
|
material.base_color.set_alpha(data.value_start);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let progress = ((now - data.start_time) / data.duration) as f32;
|
||||||
|
let value = data.value_start + progress * (data.value_end - data.value_start);
|
||||||
|
material.base_color.set_alpha(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_grow(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut q_object: Query<(Entity, &mut Transform, &Grow3DObject)>,
|
||||||
|
time: Res<Time>,
|
||||||
|
) {
|
||||||
|
let now = time.elapsed_seconds_f64();
|
||||||
|
for (entity, mut trans, data) in q_object.iter_mut() {
|
||||||
|
let end_time = data.start_time + data.duration;
|
||||||
|
if now > end_time {
|
||||||
|
trans.scale = Vec3::splat(data.scale_end);
|
||||||
|
commands.entity(entity).remove::<Grow3DObject>();
|
||||||
|
}
|
||||||
|
else if now < data.start_time {
|
||||||
|
trans.scale = Vec3::splat(data.scale_start);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let progress = ((now - data.start_time) / data.duration) as f32;
|
||||||
|
let scale = data.scale_start + progress * (data.scale_end - data.scale_start);
|
||||||
|
trans.scale = Vec3::splat(scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn play_animations(
|
fn play_animations(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut players: Query<(Entity, &mut AnimationPlayer), Added<AnimationPlayer>>,
|
mut players: Query<(Entity, &mut AnimationPlayer), Added<AnimationPlayer>>,
|
||||||
|
|
16
src/world.rs
16
src/world.rs
|
@ -38,6 +38,7 @@ 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(Update, handle_respawn.run_if(on_event::<RespawnEvent>()));
|
app.add_systems(Update, handle_respawn.run_if(on_event::<RespawnEvent>()));
|
||||||
|
app.add_systems(Update, handle_despawn_at.run_if(any_with_component::<DespawnAt>));
|
||||||
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)));
|
||||||
|
@ -65,6 +66,8 @@ struct Asteroid;
|
||||||
pub struct Star;
|
pub struct Star;
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct DespawnOnPlayerDeath;
|
pub struct DespawnOnPlayerDeath;
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct DespawnAt(pub f64);
|
||||||
#[derive(Event)]
|
#[derive(Event)]
|
||||||
pub struct RespawnEvent;
|
pub struct RespawnEvent;
|
||||||
|
|
||||||
|
@ -360,6 +363,19 @@ fn handle_despawn_asteroids(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_despawn_at(
|
||||||
|
mut commands: Commands,
|
||||||
|
q_entity: Query<(Entity, &DespawnAt)>,
|
||||||
|
time: Res<Time>,
|
||||||
|
) {
|
||||||
|
let now = time.elapsed_seconds_f64();
|
||||||
|
for (entity, despawn_at) in &q_entity {
|
||||||
|
if despawn_at.0 < now {
|
||||||
|
commands.entity(entity).despawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_respawn(
|
pub fn handle_respawn(
|
||||||
ew_spawn: EventWriter<cmd::SpawnEvent>,
|
ew_spawn: EventWriter<cmd::SpawnEvent>,
|
||||||
mut achievement_tracker: ResMut<var::AchievementTracker>,
|
mut achievement_tracker: ResMut<var::AchievementTracker>,
|
||||||
|
|
Loading…
Reference in a new issue