From ed88d5bdcead6bb82e2a8d46f03b68efb6b21921 Mon Sep 17 00:00:00 2001 From: StephenAdamson Date: Tue, 7 Jan 2025 21:35:44 +0000 Subject: [PATCH] partial chunking --- assets/dorf.png | Bin 0 -> 4701 bytes assets/empty.png | Bin 0 -> 577 bytes assets/natural walls/rock/corner_full.png | Bin 0 -> 745 bytes src/citizen.rs | 82 ++++++--- src/constants.rs | 2 +- src/main.rs | 52 +++++- src/tile.rs | 97 ----------- src/tilemap.rs | 192 ++++++++++++++++++++++ 8 files changed, 305 insertions(+), 120 deletions(-) create mode 100644 assets/dorf.png create mode 100644 assets/empty.png create mode 100644 assets/natural walls/rock/corner_full.png create mode 100644 src/tilemap.rs diff --git a/assets/dorf.png b/assets/dorf.png new file mode 100644 index 0000000000000000000000000000000000000000..bd3070e2c20c38bc46cb7c3fb069228333a8c511 GIT binary patch literal 4701 zcmeHKdsGu=77y4JL=csSPjn1rL1gk60!c;!LV^-85`k8*STo5?!YoN9BtsHFM4{NC zB8UaGR7Dh26fHis>TZ3k>{1nV*|oJ*p+0xf7QshXdaT-S0`fT9bM|=7_CJzLX6AnP z{=R#E_ulV(U$JuGJP)_YZY&ndLmnqf1b1)davcf&ON#wGz^yYUIfYKdY>>%JX-Pc+ z(b*;fBJ8A=#j;;3S#;gwEad*PZq0g?{z-_xhuivSRT5F5^)Wv=NXBUD>wk|v4U;2KPXL0k3ovq@% zGvcpCXIx6Kt$4gT?bMXx&czx8ez{6G-Wq#gxi$9NKOC1Bw%nigE;R?njS_zJG8t*tH-E zdRVZrX6?uJWr^wI?i4jY7j2n zx91(Wz&Vx45r=fQlxgWCxbBQQ=;;TElMAw=7c*4lh z*XFPO{>b0TPLD5-i~e988ocK(F&|hU;dgjkVF~U%97|e)$cfTJp==JJN6Yt4vdl9ebGm zc$(?>h;S71^pD-;QOLe}5g>e1Ak)Z7Td7%jLt?Ql%kMB)vZ?vFx z3EP2-f@em|WkU`XIzz%vQ79oPWhNj2N5J91v3Ammup`}|2s5rl6J>MzAi$f1olesx zl*_f*Y#duChcfH9e6d)}G$f8X9))5A!!cY8tNB_n zEWk7bEJ8wYSdDA>A_0LAxK=a>N^Z2!m{CJ8Pyn1m0vt@N<{^Yw1Bz6b_)od@wCv036ZcVZa+g1gq5uALePb1cHQv z8-h8Ya1A<_G8-_EPSSws2(HPfa||$qqtQyagpF``0}`bkqqV>Q^Z;qZDVt?rD48@6 zNi@dr$rpx(BSH~BlqUdA@InWa-X+WyP>T#IpT`O9jfY7L3c>-@Voaq10EY#L29=r# zjHb-V6s4E28K)q|vVT|s8Vbi~Ooq_}0OcWJD36cwgvop{iiprK-YgyuK0zfueWaX799{J~f_Ujs783y0O=m;e@n648e9g-Do4I27GNX=xi~CZctK zN5B;*PzP5~P+zKM4%N4%6HFceWiSs^#sFn(ZeOrmX2p0NZ3Oqf_=s>Q3|eA;FcV z+rVLpFoGSB4IGtP_9jx`m^D%zKTpQ0VZP&5Mo58VlqoLN!eVj!najyu8)XGT7h0}} zb-C~4;x!d9bljW(M3d;)6k19dm_0emu~8&&$VSrX5VKKSylMk*`Uj-J#)E_OfcBmR3DE(w~$KB?eK|$W1-@bXXI)2j$y5;Wepse8JaWX-{9_7>@ z?vCxO4v;E-waSU7i&l5jeXd5p{=Vuu&{9I!OLaY+gmCoMtpQ<$9!$& z62qPA!fn-QUBO#Y*=%Rk{`!y&*V{O|r++bvyz=l;_4)Be?z8Ii<(&(5D50xmKi>H3 z3wJOiD79W&4XiEPm|s zQdz6(DwPlTt(jZ-AaG>f+pYz<6`EU-&MQ0b$&cjhiz;uaNZDt*QL}m07BMVsb$##N z;-JaVt*&c-%EcF6sGN<4R9!@j75>r{(#u!d*S+K7!*xrW$f9Q-Rp4KiKGR*)POox( z??335jh>zdr}=TKp49~X%hSkAjV xXIfK8#O8hLnqr#%Is4Kr>I<^vXet$$zw||ubmNY%J^`6#$zvDF4#cPmegUtd#*zR4 literal 0 HcmV?d00001 diff --git a/assets/empty.png b/assets/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..bf3830a82305b98dbc9596eabd3893d5f70eb32f GIT binary patch literal 577 zcmV-H0>1r;P)EX>4Tx04R}tkv&MmP!xqvQ>7vmK|6>zWT*~e7Zq_VtylyLrLEAagUL((ph-iL z;^HW{799LptU9+0Yt2!cN#?t+t|ibkxj>mL&RdKi{&n6WkV&NB@Qd9M)^X{ zWrgz=XSG^q?R)YU1`FCshU>J(kiZg>NI`^*Ix48bLWFjW6ccGWk9qh<9e;{kGPx>X z_CX>@2HM@dakSAh-}0000ONklEX>4Tx04R}tkv&MmP!xqvQ>8^J3KkJ@$WWc^q9Tr^ibb$c+6t{Yn7s54nlvOS zE{=k0!NH%!s)LKOt`4q(Aov5~E;uQ=NQw6)g%&Yhc)XAE?m4`7A0RZVOf`FAfT~$W zIuRFh`BgFS3LgXvBZxtXnR+s_n1yG3-BUN!U6f~e_x)M@O2K4+Pb7{p-LQx^h-Wt~ zo%23%n3W}k_?&pspbHW|a$R=$jdRIifoFz|Y zOq3{l-Q(TC?z#Qj)1KcCI;?V#SATsN00006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=>Y;35eCTTST+Cv02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{006;BL_t(I%axPS5rZ%cLm%xT-UMyJC@!NgN;b&|Y(Re? zHDI{nJ71hcksJkZ_a!EWJCK7i*MKwvxW@8OM<93P8rQIvs?30vWJdm z*Zof|&Ubs+_kBke)!qH)LG}t)FB65{l0K4{rfK)%)LN;vwi>|9nCF?U>o7BhVSuLw b9=rGgNjfS@k`D~T00000NkvXXu0mjfr0YOG literal 0 HcmV?d00001 diff --git a/src/citizen.rs b/src/citizen.rs index b9aac5f..5ea70fc 100644 --- a/src/citizen.rs +++ b/src/citizen.rs @@ -1,4 +1,7 @@ -use crate::constants::*; +use crate::{ + constants::{self, *}, + tilemap, +}; use bevy::prelude::*; use rand::prelude::*; @@ -10,7 +13,7 @@ pub struct Ambulatory { #[derive(Bundle)] pub struct Citizen { - walker: Ambulatory, + walkness: Ambulatory, sprite: Sprite, transform: Transform, } @@ -18,9 +21,9 @@ pub struct Citizen { impl Citizen { pub fn new(asset_server: &Res, position: Vec3) -> Self { Citizen { - walker: Ambulatory { speed: TILE_SIZE }, + walkness: Ambulatory { speed: TILE_SIZE }, sprite: Sprite { - image: asset_server.load("character.png"), + image: asset_server.load("dorf.png"), ..Default::default() }, transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)), @@ -30,29 +33,66 @@ impl Citizen { pub fn citizen_movement(mut query: Query<(&Ambulatory, &mut Transform), With>) { for (citizen, mut transform) in query.iter_mut() { - if random::() < 0.66666 { + // Skip processing if the random check fails + if rand::random::() >= 0.66666 { continue; } - let mut direction = Vec2::ZERO; - direction.y += rand::random::(); - direction.y -= rand::random::(); - direction.x -= rand::random::(); - direction.x += rand::random::(); + // Generate random directions + let direction_x = (rand::random::() - rand::random::()).round(); + let direction_y = (rand::random::() - rand::random::()).round(); - if direction.length() > 0.0 { - direction.x = direction.x.round(); - direction.y = direction.y.round(); + // Skip if there's no movement + if direction_x == 0.0 && direction_y == 0.0 { + continue; + } - let movement = direction * citizen.speed; - transform.translation.x += movement.x; - transform.translation.y += movement.y; + // Calculate movement only once + let speed = citizen.speed; + transform.translation.x += direction_x * speed; + transform.translation.y += direction_y * speed; - if direction.x > 0.0 { - transform.scale.x = PIXEL_RATIO; - } else if direction.x < 0.0 { - transform.scale.x = -PIXEL_RATIO; - } + // Adjust scale for x direction + if direction_x != 0.0 { + transform.scale.x = PIXEL_RATIO * direction_x.signum(); + } + } +} + +pub fn spawn_citizens(mut commands: Commands, asset_server: Res) { + let mut rng = rand::thread_rng(); + + // Spawn a handful of citizens + for _ in 0..10 { + let x = rng.gen_range(-10.0..10.0); + let y = rng.gen_range(-10.0..10.0); + let position = Vec3::new(x, y, 0.0) * PIXEL_RATIO; + + commands.spawn(Citizen::new(&asset_server, position)); + } +} + +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; + + 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, + }); } } } diff --git a/src/constants.rs b/src/constants.rs index cba30c1..51c6b13 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,2 +1,2 @@ -pub const PIXEL_RATIO: f32 = 3.; +pub const PIXEL_RATIO: f32 = 1.; pub const TILE_SIZE: f32 = 16.0 * PIXEL_RATIO; diff --git a/src/main.rs b/src/main.rs index 9ec4ce6..8ca0eb7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,7 @@ +use std::process::exit; + use bevy::prelude::*; +use camera::PanningCamera; mod camera; mod citizen; @@ -7,6 +10,7 @@ mod cursor; mod game; mod item; mod tile; +mod tilemap; mod tiles; fn main() { @@ -24,12 +28,14 @@ fn main() { .set(ImagePlugin::default_nearest()), ) .insert_resource(ClearColor(Color::srgb(0.0, 0.0, 0.0))) + .add_plugins(tilemap::TilemapPlugin) .add_systems( Startup, ( - game::setup_level, + setup_initial_chunks, camera::spawn_panning_camera, cursor::setup_cursor, + citizen::spawn_citizens, // New citizen spawning system ), ) .add_systems( @@ -47,6 +53,8 @@ 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 ), ) .init_resource::() @@ -60,3 +68,45 @@ fn main() { ) .run(); } + +fn setup_initial_chunks(mut event_writer: EventWriter) { + // Spawn a 3x3 grid of chunks around the origin + for x in -1..=1 { + for y in -1..=1 { + println!("setup_initial_chunks: x = {}, y = {}", x, y); + 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 - 1)..=(chunk_x + 1) { + for y in (chunk_y - 1)..=(chunk_y + 1) { + 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 f6523f7..efa1ecc 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,11 +1,8 @@ use crate::constants::TILE_SIZE; use crate::game; -use crate::item::Item; use bevy::ecs::system::ParamSet; -use bevy::math::ivec3; use bevy::prelude::*; use std::collections::HashMap; -use std::process::exit; #[derive(Component, Clone)] #[require(Sprite)] @@ -46,9 +43,6 @@ impl Default for FixtureTile { } } -#[derive(Component, Clone)] -pub struct ConnectedTexture {} - #[derive(Resource, Default)] pub struct CameraMoved(pub bool); @@ -211,24 +205,6 @@ pub fn tile_sprite_generate_occlusion_map( let pos = transform.translation.as_ivec3() - IVec3::new(0, 0, 1); fixture.visible_range = calculate_visibility(pos, &tilemap); }); - - use std::time::Instant; - let total: Instant = Instant::now(); - - for i in 0..1000000 { - let now: Instant = Instant::now(); - for x in -1..=1 { - for y in -1..=1 { - for z in 0..=1 { - tilemap.floors.get(&IVec3::new(x, y, z)); - } - } - } - let elapsed = now.elapsed(); - } - let elapsed = total.elapsed(); - print!("{:.4?}, ", elapsed / 1000000); - exit(0); } pub fn update_tile_visibility( @@ -270,79 +246,6 @@ pub fn update_tile_visibility( }); } -fn calculate_connected_texture(floor_tiles: &HashMap<(i32, i32, i32), (bool, u32)>) -> Vec { - let mut textures = vec![]; - - for ((x, y, z), (is_floor, tile_id)) in floor_tiles.iter() { - let mut is_wall = false; - - for x_offset in -1..=1 { - for y_offset in -1..=1 { - for z_offset in 0..=1 { - if x_offset == 0 && y_offset == 0 && z_offset == 0 { - continue; - } - - let neighbor_pos = (x + x_offset, y + y_offset, z + z_offset); - - if let Some((_, neighbor_id)) = floor_tiles.get(&neighbor_pos) { - if *neighbor_id > 0 { - // assuming wall IDs are greater than 0 - is_wall = true; - break; - } - } - } - } - } - - match (is_floor, is_wall) { - (true, false) => textures.push("floor".to_string()), // or some other floor texture - (false, true) => textures.push("wall".to_string()), // or some other wall texture - _ => panic!("Unexpected tile state"), - } - } - - textures -} - -pub fn tile_item_sprite_update( - time: Res