use bevy::prelude::*; use crate::{camera::MainCamera, player::Player}; pub const CHUNK_HEIGHT: f32 = 200.0; // Height a cunk const MARGIN_BELLOW: f32 = 500.0; // Height bellow the camera view it'll be gen const MARGIN_ABOVE: f32 = 500.0; // Height above the camera view it'll be gen #[derive(Component)] pub struct Chunk { pub id: i64, } #[derive(Resource)] pub struct RunSeed(pub u64); fn stream_world( player: Single<&Transform, With>, entities: Query<(Entity, &Chunk)>, mut commands: Commands, camera: Single<&Camera, With>, run_seed: Res, ) { let (min_id, max_id) = visible_chunk_range( player.translation.y, camera .logical_viewport_size() .unwrap_or(Vec2::new(1920.0, 1080.0)) .y, ); let existing_ids: Vec = entities.iter().map(|(_, chunk)| chunk.id).collect(); for (entity, chunk) in entities { // Out of bounds implies despawn if chunk.id < min_id || chunk.id > max_id { commands.entity(entity).despawn(); } } for id in min_id..=max_id { if !existing_ids.contains(&id) { spawn_chunk(&mut commands, id, run_seed.0); } } } // Bounds of chunk's ids to be generated fn visible_chunk_range(player_y: f32, camera_y: f32) -> (i64, i64) { ( ((player_y - camera_y / 2.0 - MARGIN_BELLOW) / CHUNK_HEIGHT).floor() as i64, ((player_y + camera_y / 2.0 + MARGIN_ABOVE) / CHUNK_HEIGHT).floor() as i64, ) } fn spawn_chunk(commands: &mut Commands, id: i64, run_seed: u64) { crate::background::spawn_background_chunk(commands, id); // TODO: obstacles } pub struct WorldPlugin; impl Plugin for WorldPlugin { fn build(&self, app: &mut App) { app.insert_resource(RunSeed(rand::random::())) .add_systems(Update, stream_world); } }