WIP despawning asteroids... for some reason, scenes can't despawn

This commit is contained in:
yuni 2024-04-01 20:52:57 +02:00
parent a78d4b0387
commit bbad89e1fb

View file

@ -1,4 +1,4 @@
use crate::{actor, nature, settings}; use crate::{actor, nature, settings, hud};
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::render_resource::{AsBindGroup, ShaderRef}; use bevy::render::render_resource::{AsBindGroup, ShaderRef};
use bevy::math::DVec3; use bevy::math::DVec3;
@ -6,11 +6,12 @@ use bevy_xpbd_3d::prelude::*;
use bevy_xpbd_3d::plugins::sync::SyncConfig; use bevy_xpbd_3d::plugins::sync::SyncConfig;
use std::f32::consts::PI; use std::f32::consts::PI;
const ASTEROID_UPDATE_INTERVAL: f32 = 1.0; // seconds const ASTEROID_UPDATE_INTERVAL: f32 = 0.1; // seconds
const ASTEROID_SIZE: f32 = 100.0; const ASTEROID_SIZE: f32 = 100.0;
const STARS_MAX_MAGNITUDE: f32 = 5.5; const STARS_MAX_MAGNITUDE: f32 = 5.5;
const CENTER_WORLD_ON_PLAYER: bool = true; const CENTER_WORLD_ON_PLAYER: bool = true;
const ASTEROIDS_ARE_SPHERES: bool = true;
const ASSET_ASTEROID1: &str = "models/asteroid.glb#Scene0"; const ASSET_ASTEROID1: &str = "models/asteroid.glb#Scene0";
const ASSET_ASTEROID2: &str = "models/asteroid2.glb#Scene0"; const ASSET_ASTEROID2: &str = "models/asteroid2.glb#Scene0";
@ -59,13 +60,15 @@ impl Plugin for WorldPlugin {
#[derive(Resource)] struct AsteroidUpdateTimer(Timer); #[derive(Resource)] struct AsteroidUpdateTimer(Timer);
#[derive(Resource)] struct AsteroidDatabase(Vec<AsteroidData>); #[derive(Resource)] struct AsteroidDatabase(Vec<AsteroidData>);
#[derive(Component)] struct Asteroid;
struct AsteroidData { struct AsteroidData {
entity: Option<Entity>,
is_spawned: bool, is_spawned: bool,
spawned_once: bool,
class: u8, class: u8,
size: f32, size: f32,
x: f64, pos: DVec3,
y: f64,
z: f64,
} }
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)] #[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
@ -94,7 +97,6 @@ pub fn setup(
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
mut materials_custom: ResMut<Assets<RingMaterial>>, mut materials_custom: ResMut<Assets<RingMaterial>>,
asset_server: Res<AssetServer>,
) { ) {
// Generate starmap // Generate starmap
let sphere_handle = meshes.add(Sphere::new(1.0)); let sphere_handle = meshes.add(Sphere::new(1.0));
@ -177,10 +179,14 @@ fn generate_asteroids(
let wobble: f64 = dist/2.0; let wobble: f64 = dist/2.0;
let (i, j, k) = (i as f64, j as f64, k as f64); let (i, j, k) = (i as f64, j as f64, k as f64);
db.0.push(AsteroidData { db.0.push(AsteroidData {
entity: None,
is_spawned: false, is_spawned: false,
x: player_x + offset + dist * i + wobble * (j+k/pi).sin() * (k+j/pi).cos(), spawned_once: false,
y: player_y + offset + dist * j + wobble * (k+i/pi).sin() * (i+k/pi).cos(), pos: DVec3::new(
z: player_z + offset + dist * k + wobble * (i+j/pi).sin() * (j+i/pi).cos(), player_x + offset + dist * i + wobble * (j+k/pi).sin() * (k+j/pi).cos(),
player_y + offset + dist * j + wobble * (k+i/pi).sin() * (i+k/pi).cos(),
player_z + offset + dist * k + wobble * (i+j/pi).sin() * (j+i/pi).cos(),
),
size: ASTEROID_SIZE, size: ASTEROID_SIZE,
class: (((i+j+k) as i32) % 2) as u8, class: (((i+j+k) as i32) % 2) as u8,
}); });
@ -194,45 +200,102 @@ fn spawn_despawn_asteroids(
mut timer: ResMut<AsteroidUpdateTimer>, mut timer: ResMut<AsteroidUpdateTimer>,
mut db: ResMut<AsteroidDatabase>, mut db: ResMut<AsteroidDatabase>,
mut commands: Commands, mut commands: Commands,
q_player: Query<&Position, With<actor::PlayerCamera>>,
mut meshes: ResMut<Assets<Mesh>>,
mut q_asteroid: Query<(Entity, &mut Visibility), With<Asteroid>>,
mut materials: ResMut<Assets<StandardMaterial>>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut log: ResMut<hud::Log>,
) { ) {
if !timer.0.tick(time.delta()).just_finished() { if !timer.0.tick(time.delta()).just_finished() || q_player.is_empty() {
return; return;
} }
let player = q_player.get_single().unwrap();
let mut spawned = 0;
let mut despawned = 0;
for asteroid in &mut db.0 { for asteroid in &mut db.0 {
if asteroid.is_spawned { let dist = player.distance(asteroid.pos);
let should_spawn = dist < 10000.0;
if should_spawn == asteroid.is_spawned {
continue; // Nothing to do
}
if !should_spawn {
// Despawn
if let Some(entity) = asteroid.entity {
for (ent, mut vis) in &mut q_asteroid {
if ent == entity {
*vis = Visibility::Hidden;
asteroid.entity = None;
asteroid.is_spawned = false;
despawned += 1;
commands.entity(entity).despawn();
break;
}
}
}
continue; continue;
} }
asteroid.is_spawned = true;
let asset = match asteroid.class { // Spawn
0 => ASSET_ASTEROID1, let mut entity_commands = commands.spawn((
_ => ASSET_ASTEROID2,
};
commands.spawn((
actor::Actor::default(), actor::Actor::default(),
RigidBody::Dynamic, RigidBody::Dynamic,
AngularVelocity(DVec3::new(0.1, 0.1, 0.03)), AngularVelocity(DVec3::new(0.1, 0.1, 0.03)),
LinearVelocity(DVec3::new(0.0, 0.0, 0.35)), LinearVelocity(DVec3::new(0.0, 0.0, 0.35)),
Collider::sphere(1.0), Collider::sphere(1.0),
SceneBundle { Rotation::from(Quat::from_rotation_y(-PI / 3.)),
Position::new(asteroid.pos),
Asteroid,
));
if ASTEROIDS_ARE_SPHERES {
let sphere_handle = meshes.add(Sphere::default().mesh().uv(128, 128));
let sphere_material_handle = materials.add(StandardMaterial {
base_color: Color::rgb(0.4, 0.4, 0.4),
perceptual_roughness: 1.0,
metallic: 0.0,
..default()
});
entity_commands.insert(PbrBundle {
mesh: sphere_handle,
material: sphere_material_handle,
transform: Transform { transform: Transform {
scale: Vec3::splat(asteroid.size), scale: Vec3::splat(asteroid.size),
..default() ..default()
}, },
scene: asset_server.load(asset),
..default() ..default()
}, });
Rotation::from(Quat::from_rotation_y(-PI / 3.)), }
Position::from_xyz(asteroid.x, asteroid.y, asteroid.z), else {
)); let asset = match asteroid.class {
0 => ASSET_ASTEROID1,
_ => ASSET_ASTEROID2,
};
entity_commands.insert(SceneBundle {
scene: asset_server.load(asset),
transform: Transform {
scale: Vec3::splat(asteroid.size),
..default()
},
..default()
});
}
asteroid.entity = Some(entity_commands.id());
spawned += 1;
asteroid.spawned_once = true;
asteroid.is_spawned = true;
}
if spawned != 0 || despawned != 0 {
log.notice(format!("spawned: {spawned}, despawned: {despawned}"));
} }
} }
fn handle_cheats( fn handle_cheats(
mut commands: Commands,
key_input: Res<ButtonInput<KeyCode>>, key_input: Res<ButtonInput<KeyCode>>,
mut q_player: Query<(&Transform, &mut Position, &mut LinearVelocity), With<actor::PlayerCamera>>, mut q_player: Query<(&Transform, &mut Position, &mut LinearVelocity), With<actor::PlayerCamera>>,
mut q_life: Query<(&mut actor::LifeForm, ), With<actor::Player>>, mut q_life: Query<(&mut actor::LifeForm, ), With<actor::Player>>,
q_entities: Query<Entity, (With<actor::Actor>, Without<actor::Player>)>,
settings: ResMut<settings::Settings>, settings: ResMut<settings::Settings>,
) { ) {
if !settings.dev_mode || q_player.is_empty() || q_life.is_empty() { if !settings.dev_mode || q_player.is_empty() || q_life.is_empty() {
@ -259,6 +322,10 @@ fn handle_cheats(
v.0 += DVec3::from(trans.rotation * Vec3::new(0.0, 0.0, -1000.0)); v.0 += DVec3::from(trans.rotation * Vec3::new(0.0, 0.0, -1000.0));
} }
if key_input.pressed(settings.key_cheat_adrenaline_zero) { if key_input.pressed(settings.key_cheat_adrenaline_zero) {
// NOTE: temporarily added despawn all in here
for entity in &q_entities {
commands.entity(entity).despawn();
}
lifeform.adrenaline = 0.0; lifeform.adrenaline = 0.0;
} }
if key_input.pressed(settings.key_cheat_adrenaline_mid) { if key_input.pressed(settings.key_cheat_adrenaline_mid) {