diff --git a/src/citizen.rs b/src/citizen.rs index d47d724..d2f6ab6 100644 --- a/src/citizen.rs +++ b/src/citizen.rs @@ -1,7 +1,4 @@ -use crate::{ - constants::{self, *}, - tilemap, -}; +use crate::constants::*; use bevy::prelude::*; use rand::prelude::*; @@ -72,27 +69,27 @@ pub fn spawn_citizens(mut commands: Commands, asset_server: Res) { } } -pub fn check_citizen_positions_for_chunks( - query: Query<&Transform, With>, - chunk_map: Res, - mut event_writer: EventWriter, -) { - for transform in query.iter() { - let position = transform.translation; +// pub fn check_citizen_positions_for_chunks( +// query: Query<&Transform, With>, +// chunk_map: Res, +// mut event_writer: EventWriter, +// ) { +// for transform in query.iter() { +// let position = transform.translation; - // Convert citizen position to chunk coordinates - let chunk_x = - (position.x / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32; - let chunk_y = - (position.y / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32; +// // Convert citizen position to chunk coordinates +// let chunk_x = +// (position.x / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32; +// let chunk_y = +// (position.y / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32; - let chunk_pos = IVec2::new(chunk_x, chunk_y); +// let chunk_pos = IVec2::new(chunk_x, chunk_y); - // // Load chunk if not already loaded - // if !chunk_map.loaded_chunks.contains_key(&chunk_pos) { - // event_writer.send(tilemap::LoadChunkEvent { - // chunk_position: chunk_pos, - // }); - // } - } -} +// // // Load chunk if not already loaded +// // if !chunk_map.loaded_chunks.contains_key(&chunk_pos) { +// // event_writer.send(tilemap::LoadChunkEvent { +// // chunk_position: chunk_pos, +// // }); +// // } +// } +// } diff --git a/src/game.rs b/src/game.rs index 39ddd97..604b02d 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,177 +1,4 @@ -use crate::constants::*; -use crate::item::ItemBundle; -use crate::tiles::FloorTilePrefab; -use crate::{citizen::Citizen, tiles::FixtureTilePrefab}; use bevy::prelude::*; -use noise::{NoiseFn, Perlin}; -use rand::prelude::*; #[derive(Resource)] pub struct ZIndex(pub f32); - -pub fn setup_level(mut commands: Commands, asset_server: Res) { - println!("setup_level"); - setup_tilemap(&mut commands, &asset_server); - - for x in -10..10 { - for y in -10..10 { - if random::() < 0.1 { - commands.spawn(Citizen::new( - &asset_server, - Vec3::new(x as f32 * TILE_SIZE, y as f32 * TILE_SIZE, 0.9), - )); - } - } - } -} - -fn setup_tilemap(commands: &mut Commands, asset_server: &Res) { - let noise = Perlin::new(0); - let mut floor_positions = Vec::new(); - - // First pass: Generate and store floor tiles - for y in -50..50 { - for x in -50..50 { - let noise_value_a = noise.get([x as f64 * 0.01, y as f64 * 0.01]) * 1.25; - let noise_value_b = noise.get([x as f64 * 0.05, y as f64 * 0.05]) * 0.25; - let combined_noise_value = noise_value_a + noise_value_b; - - let noise_position = Vec3::new( - (x as f32 * TILE_SIZE).round(), - (y as f32 * TILE_SIZE).round(), - (combined_noise_value * 4.).round() as f32 * TILE_SIZE, - ); - - for z in -150..50 { - let position = Vec3::new( - (x as f32 * TILE_SIZE).round(), - (y as f32 * TILE_SIZE).round(), - (z as f32 * TILE_SIZE).round(), - ); - - let items: Vec = vec![]; - let mut floor_type = None; - - if noise_position.z > position.z { - if z < -15 { - let noise_value = - noise.get([x as f64 * 0.05, y as f64 * 0.05, z as f64 * 0.05]); - if noise_value < -0.5 { - commands - .spawn(FloorTilePrefab::air(position, asset_server)) - .with_children(|parent| { - for item in items { - parent.spawn(item); - } - }); - floor_type = Some("air"); - } else if noise_value < 0.8 { - commands - .spawn(FloorTilePrefab::rock(position, asset_server)) - .with_children(|parent| { - for item in items { - parent.spawn(item); - } - }); - floor_type = Some("rock"); - } else { - commands - .spawn(FloorTilePrefab::dirt(position, asset_server)) - .with_children(|parent| { - for item in items { - parent.spawn(item); - } - }); - floor_type = Some("dirt"); - } - } else { - commands - .spawn(FloorTilePrefab::dirt(position, asset_server)) - .with_children(|parent| { - for item in items { - parent.spawn(item); - } - }); - floor_type = Some("dirt"); - } - } else if noise_position.z < position.z { - commands - .spawn(FloorTilePrefab::air(position, asset_server)) - .with_children(|parent| { - for item in items { - parent.spawn(item); - } - }); - floor_type = Some("air"); - } else { - commands - .spawn(FloorTilePrefab::dirt(position, asset_server)) - .with_children(|parent| { - for item in items { - parent.spawn(item); - } - }); - floor_type = Some("dirt"); - } - - // Store floor type and position - if let Some(floor_type) = floor_type { - floor_positions.push((position, floor_type)); - } - } - } - } - - // Generate bedrock floor - for x in -50..50 { - for y in -50..50 { - let position = Vec3::new(x as f32 * TILE_SIZE, y as f32 * TILE_SIZE, -150.); - commands.spawn(FloorTilePrefab::bedrock(position, asset_server)); - floor_positions.push((position, "bedrock")); - } - } - - // Sort floor positions by z coordinate (highest to lowest) to process from top to bottom - floor_positions.sort_by(|a, b| b.0.z.partial_cmp(&a.0.z).unwrap()); - - // Create a map to easily look up floor types at specific positions - let floor_map: std::collections::HashMap<(i32, i32, i32), &str> = floor_positions - .iter() - .map(|(pos, floor_type)| ((pos.x as i32, pos.y as i32, pos.z as i32), *floor_type)) - .collect(); - - // Second pass: Generate fixtures based on floor tiles above - for (position, _) in floor_positions.iter() { - let x = position.x as i32; - let y = position.y as i32; - let z = position.z as i32; - - // Look up the floor type one z-level above - if let Some(above_floor_type) = floor_map.get(&(x, y, z + TILE_SIZE as i32)) { - // Skip if the floor above is air or if we're at the surface - if *above_floor_type == "air" { - continue; - } - - // Calculate fixture position (one tile above current floor) - let fixture_position = Vec3::new(position.x, position.y, position.z + 1.); - - // Spawn appropriate fixture based on floor type above - match *above_floor_type { - "dirt" => { - commands.spawn(FixtureTilePrefab::dirt_wall(fixture_position, asset_server)); - } - "rock" => { - commands.spawn(FixtureTilePrefab::rock_wall(fixture_position, asset_server)); - } - "bedrock" => { - commands.spawn(FixtureTilePrefab::bedrock_wall( - fixture_position, - asset_server, - )); - } - _ => {} - } - } - } -} diff --git a/src/item.rs b/src/item.rs index c66b8b5..8958a1d 100644 --- a/src/item.rs +++ b/src/item.rs @@ -1,12 +1,12 @@ use bevy::prelude::*; #[derive(Component)] -#[require(Sprite,Transform,Visibility )] +#[require(Sprite, Transform, Visibility)] pub struct Item { wear: u8, quality: u8, weight: u8, - stain_time: u16 + stain_time: u16, } impl Default for Item { @@ -33,12 +33,12 @@ pub struct ItemBundle { pub item: Item, pub transform: Transform, pub sprite: Sprite, - pub visibility: Visibility + pub visibility: Visibility, } #[derive(Component)] pub struct Nameable { - pub name: String + pub name: String, } #[derive(Component)] diff --git a/src/main.rs b/src/main.rs index 703c7fb..0331d61 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,10 +29,9 @@ fn main() { .add_systems( Startup, ( - setup_initial_chunks, camera::spawn_panning_camera, cursor::setup_cursor, - citizen::spawn_citizens, // New citizen spawning system + citizen::spawn_citizens, ), ) .add_systems( @@ -41,8 +40,7 @@ fn main() { camera::camera_movement, citizen::citizen_movement, cursor::move_cursor, - check_camera_position_for_chunks, - citizen::check_citizen_positions_for_chunks, // New citizen-based chunk loading system + // citizen::check_citizen_positions_for_chunks, ), ) .init_resource::() @@ -56,45 +54,3 @@ fn main() { ) .run(); } - -fn setup_initial_chunks(mut event_writer: EventWriter) { - println!("setup_initial_chunks"); - // // Spawn a 3x3 grid of chunks around the origin - // for x in -5..=5 { - // for y in -5..=5 { - // event_writer.send(tilemap::LoadChunkEvent { - // chunk_position: IVec2::new(x, y), - // }); - // } - // } -} - -// New system to check camera position and load nearby chunks -fn check_camera_position_for_chunks( - camera_query: Query<&Transform, With>, - chunk_map: Res, - mut event_writer: EventWriter, -) { - let camera_transform = camera_query.single(); - let camera_pos = camera_transform.translation; - - // Convert camera position to chunk coordinates - let chunk_x = - (camera_pos.x / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32; - let chunk_y = - (camera_pos.y / (tilemap::CHUNK_SIZE as f32 * constants::TILE_SIZE)).floor() as i32; - - // Check a 3x3 area around the camera's current chunk - for x in (chunk_x - 2)..=(chunk_x + 2) { - for y in (chunk_y - 2)..=(chunk_y + 2) { - let chunk_pos = IVec2::new(x, y); - - // Only spawn new chunks if they haven't been loaded yet - if !chunk_map.loaded_chunks.contains_key(&chunk_pos) { - event_writer.send(tilemap::LoadChunkEvent { - chunk_position: chunk_pos, - }); - } - } - } -} diff --git a/src/tile.rs b/src/tile.rs index b02723a..b1d6a40 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,6 +1,4 @@ -use crate::constants::TILE_SIZE; use crate::game; -use crate::tilemap::ChunkMap; use bevy::ecs::system::ParamSet; use bevy::prelude::*; use std::collections::HashMap; @@ -52,7 +50,6 @@ impl Default for FixtureTile { #[derive(Resource, Default)] pub struct CameraMoved(pub bool); -// Modify camera_z_movement pub fn camera_z_movement( keyboard_input: Res>, mut z_index: ResMut, diff --git a/src/tilemap.rs b/src/tilemap.rs index c9f7518..663ddfb 100644 --- a/src/tilemap.rs +++ b/src/tilemap.rs @@ -1,5 +1,5 @@ use crate::constants::TILE_SIZE; -use crate::tile::{self, FixtureTile, FloorTile, NeedsOccluded, TileMap}; +use crate::tile::{FixtureTile, FloorTile, NeedsOccluded, TileMap}; use crate::tiles::{FixtureTilePrefab, FloorTilePrefab}; use bevy::prelude::*; use noise::{NoiseFn, Perlin}; @@ -30,7 +30,7 @@ fn setup_chunk_system(mut commands: Commands) { commands.insert_resource(ChunkMap::default()); } -// System to handle individual tile occlusion updates +// System to handle tile occlusion updates pub fn handle_tile_occlusion_updates( mut commands: Commands, tilemap: Res, @@ -144,6 +144,22 @@ pub fn calculate_visibility(pos: IVec3, tilemap: &TileMap) -> [u32; 8] { visible_range } +pub fn generate_surface_noise(x: i32, y: i32) -> f32 { + let noise = Perlin::new(0); + let mut noise_value = 0.0; + let mut amplitude = 1.0; + let mut frequency = 0.008; // Reduced initial frequency for smoother base terrain + + // Reduced number of octaves for less rough detail + for _ in 0..6 { + noise_value += noise.get([x as f64 * frequency, y as f64 * frequency]) * amplitude; + amplitude *= 0.6; // Gentler amplitude falloff + frequency *= 1.8; // Gentler frequency increase + } + + (noise_value * 2.5) as f32 // Reduced height multiplier for less extreme elevation +} + fn handle_chunk_loading( mut commands: Commands, asset_server: Res, @@ -173,16 +189,10 @@ fn handle_chunk_loading( let world_x = start_x + local_x; let world_y = start_y + local_y; - let noise_value_a = - noise.get([world_x as f64 * 0.01, world_y as f64 * 0.01]) * 1.25; - let noise_value_b = - noise.get([world_x as f64 * 0.05, world_y as f64 * 0.05]) * 0.25; - let combined_noise_value = noise_value_a + noise_value_b; - let noise_position = Vec3::new( (world_x as f32 * TILE_SIZE).round(), (world_y as f32 * TILE_SIZE).round(), - (combined_noise_value * 4.).round() as f32 * TILE_SIZE, + (generate_surface_noise(world_x, world_y) * TILE_SIZE).round(), ); // Spawn tiles and add them to tilemap @@ -194,41 +204,43 @@ fn handle_chunk_loading( ); let pos_ivec = position.as_ivec3(); - if noise_position.z > position.z { - if z < -8 { - let noise_value = noise.get([ - world_x as f64 * 0.05, - world_y as f64 * 0.05, - z as f64 * 0.05, - ]); - if noise_value < -0.5 { - FloorTilePrefab::air(position, &asset_server).spawn(&mut commands); - tilemap.floors.insert(pos_ivec, (0, false, true, 1, [0; 8])); // Air tile - floor_positions.push((position, "air")); - } else if noise_value < 0.8 { - FloorTilePrefab::rock(position, &asset_server).spawn(&mut commands); - tilemap - .floors - .insert(pos_ivec, (2, true, false, 255, [0; 8])); // Rock tile - floor_positions.push((position, "rock")); - } else { - FloorTilePrefab::dirt(position, &asset_server).spawn(&mut commands); - tilemap.floors.insert(pos_ivec, (1, true, true, 1, [0; 8])); // Dirt tile - floor_positions.push((position, "dirt")); - } + if z < -8 { + let noise_value = noise.get([ + world_x as f64 * 0.05, + world_y as f64 * 0.05, + z as f64 * 0.05, + ]); + if noise_value < -0.5 { + FloorTilePrefab::air(position, &asset_server).spawn(&mut commands); + tilemap.floors.insert(pos_ivec, (0, false, true, 1, [0; 8])); // Air tile + floor_positions.push((position, "air")); + } else if noise_value < 0.8 { + FloorTilePrefab::rock(position, &asset_server).spawn(&mut commands); + tilemap + .floors + .insert(pos_ivec, (2, true, false, 255, [0; 8])); // Rock tile + floor_positions.push((position, "rock")); } else { FloorTilePrefab::dirt(position, &asset_server).spawn(&mut commands); tilemap.floors.insert(pos_ivec, (1, true, true, 1, [0; 8])); // Dirt tile floor_positions.push((position, "dirt")); } - } else if noise_position.z < position.z { + } else if noise_position.z > position.z { + if (generate_surface_noise(world_x, world_y) * TILE_SIZE).round() + <= position.z + TILE_SIZE + { + FloorTilePrefab::grass(position, &asset_server).spawn(&mut commands); + tilemap.floors.insert(pos_ivec, (1, true, true, 1, [0; 8])); // Dirt tile (grass) + floor_positions.push((position, "dirt")); + } else { + FloorTilePrefab::dirt(position, &asset_server).spawn(&mut commands); + tilemap.floors.insert(pos_ivec, (1, true, true, 1, [0; 8])); // Dirt tile + floor_positions.push((position, "dirt")); + } + } else { FloorTilePrefab::air(position, &asset_server).spawn(&mut commands); tilemap.floors.insert(pos_ivec, (0, false, true, 1, [0; 8])); // Air tile floor_positions.push((position, "air")); - } else { - FloorTilePrefab::grass(position, &asset_server).spawn(&mut commands); - tilemap.floors.insert(pos_ivec, (1, true, true, 1, [0; 8])); // Grass tile - floor_positions.push((position, "dirt")); } } } @@ -258,13 +270,24 @@ fn handle_chunk_loading( } } +fn setup_initial_chunks(mut event_writer: EventWriter) { + println!("setup_initial_chunks"); + for x in -5..=5 { + for y in -5..=5 { + event_writer.send(LoadChunkEvent { + chunk_position: IVec2::new(x, y), + }); + } + } +} + pub struct TilemapPlugin; impl Plugin for TilemapPlugin { fn build(&self, app: &mut App) { app.init_resource::() .add_event::() - .add_systems(Startup, setup_chunk_system) + .add_systems(Startup, (setup_chunk_system, setup_initial_chunks)) .add_systems( FixedUpdate, (handle_chunk_loading, handle_tile_occlusion_updates).chain(),