From 014e786053bb041a25ab4cfc9d141ac1e4f13ad6 Mon Sep 17 00:00:00 2001 From: Isaac Turci <78173025+Zac8668@users.noreply.github.com> Date: Thu, 4 Jan 2024 11:08:51 -0300 Subject: [PATCH 1/2] Better actors --- src/actors.rs | 112 ++++++++++++++++++++----------------------- src/atom.rs | 27 ++++------- src/chunk.rs | 2 +- src/chunk_manager.rs | 66 ------------------------- src/debug.rs | 6 +-- src/manager_api.rs | 45 +++++++---------- src/player.rs | 7 ++- 7 files changed, 85 insertions(+), 180 deletions(-) diff --git a/src/actors.rs b/src/actors.rs index 10a2855..c9d2190 100644 --- a/src/actors.rs +++ b/src/actors.rs @@ -8,11 +8,34 @@ pub struct Actor { pub vel: Vec2, } -pub fn add_actor(chunk_manager: &mut ChunkManager, actor: &Actor) { - for x_off in 0..actor.width as i32 { - for y_off in 0..actor.height as i32 { - let pos = global_to_chunk(actor.pos + ivec2(x_off, y_off)); - chunk_manager.colliders.add_one(pos); +//Called before simulations +pub fn add_actors(mut chunk_manager: ResMut, actors: Query<&Actor>) { + for actor in actors.iter() { + for x_off in 0..actor.width as i32 { + for y_off in 0..actor.height as i32 { + let pos = global_to_chunk(actor.pos + ivec2(x_off, y_off)); + if let Some(atom) = chunk_manager.get_mut_atom(pos) { + if atom.state == State::Void { + *atom = Atom::object(); + } + } + } + } + } +} + +//Called after simulation, before actor update +pub fn remove_actors(mut chunk_manager: ResMut, actors: Query<&Actor>) { + for actor in actors.iter() { + for x_off in 0..actor.width as i32 { + for y_off in 0..actor.height as i32 { + let pos = global_to_chunk(actor.pos + ivec2(x_off, y_off)); + if let Some(atom) = chunk_manager.get_mut_atom(pos) { + if atom.state == State::Object { + *atom = Atom::default(); + } + } + } } } } @@ -45,7 +68,7 @@ pub fn update_actors(mut chunk_manager: ResMut, mut actors: Query< }; if move_hor { - let moved_x = move_x(&mut chunk_manager, &mut actor, v.x - prev.x); + let moved_x = move_x(&mut chunk_manager, &mut actor, (v.x - prev.x).signum()); if on_ground(&chunk_manager, &actor) { let starting_y = actor.pos.y; match moved_x { @@ -57,7 +80,11 @@ pub fn update_actors(mut chunk_manager: ResMut, mut actors: Query< //Abort if we couldn't move up, or if we moved up but couldn't move sideways on the last step if !moved_y || i == UP_WALK_HEIGHT - && !move_x(&mut chunk_manager, &mut actor, v.x - prev.x) + && !move_x( + &mut chunk_manager, + &mut actor, + (v.x - prev.x).signum(), + ) { abort_stair(&mut chunk_manager, &mut actor, starting_y, 1); break; @@ -78,7 +105,7 @@ pub fn update_actors(mut chunk_manager: ResMut, mut actors: Query< } } } else { - move_y(&mut chunk_manager, &mut actor, v.y - prev.y); + move_y(&mut chunk_manager, &mut actor, (v.y - prev.y).signum()); } prev = v; @@ -120,31 +147,6 @@ pub fn move_x(chunk_manager: &mut ChunkManager, actor: &mut Actor, dir: i32) -> } } - //Move - for y_off in 0..actor.height as i32 { - let pos1 = actor.pos - + if dir > 0 { - // Moving right - ivec2(actor.width as i32, y_off) - } else { - // Moving left - ivec2(-1, y_off) - }; - - let pos2 = actor.pos - + if dir > 0 { - // Moving right - ivec2(0, y_off) - } else { - // Moving left - ivec2(actor.width as i32 - 1, y_off) - }; - - let chunk_pos1 = global_to_chunk(pos1); - let chunk_pos2 = global_to_chunk(pos2); - chunk_manager.colliders.add_one(chunk_pos1); - chunk_manager.colliders.remove_one(chunk_pos2); - } actor.pos.x += dir; true @@ -178,32 +180,6 @@ pub fn move_y(chunk_manager: &mut ChunkManager, actor: &mut Actor, dir: i32) -> } } - //Move - for x_off in 0..actor.width as i32 { - let pos1 = actor.pos - + if dir > 0 { - // Moving down - ivec2(x_off, actor.height as i32) - } else { - // Moving up - ivec2(x_off, -1) - }; - - let pos2 = actor.pos - + if dir > 0 { - // Moving down - ivec2(x_off, 0) - } else { - // Moving up - ivec2(x_off, actor.height as i32 - 1) - }; - - let chunk_pos1 = global_to_chunk(pos1); - let chunk_pos2 = global_to_chunk(pos2); - chunk_manager.colliders.add_one(chunk_pos1); - chunk_manager.colliders.remove_one(chunk_pos2); - } - actor.pos.y += dir; true @@ -212,6 +188,22 @@ pub fn move_y(chunk_manager: &mut ChunkManager, actor: &mut Actor, dir: i32) -> pub struct ActorsPlugin; impl Plugin for ActorsPlugin { fn build(&self, app: &mut App) { - app.add_systems(Update, update_actors.before(chunk_manager_update)); + app.add_systems( + Update, + ( + add_actors + .before(chunk_manager_update) + .before(remove_actors) + .before(update_actors), + remove_actors + .after(chunk_manager_update) + .after(add_actors) + .before(update_actors), + update_actors + .after(remove_actors) + .after(add_actors) + .after(chunk_manager_update), + ), + ); } } diff --git a/src/atom.rs b/src/atom.rs index f0ed8a4..f764fe1 100644 --- a/src/atom.rs +++ b/src/atom.rs @@ -22,14 +22,11 @@ pub struct Atom { } impl Atom { - pub fn new() -> Self { + pub fn object() -> Self { Atom { - color: [55, 55, 55, 255], - state: State::Void, - updated_at: 0, - fall_speed: 0, - velocity: (0, 0), - f_idle: 0, + state: State::Object, + color: [255, 255, 255, 255], + ..Default::default() } } } @@ -41,6 +38,7 @@ pub enum State { Powder, Liquid, Gas, + Object, #[default] Void, } @@ -61,8 +59,7 @@ pub fn update_powder(chunks: &mut UpdateChunksType, pos: IVec2, dt: u8) -> HashS } for _ in 0..fall_speed { - let state = get_state(chunks, cur_pos); - let neigh = down_neigh(chunks, cur_pos, &[(State::Liquid, 0.2)], state, dt); + let neigh = down_neigh(chunks, cur_pos, &[(State::Liquid, 0.2)], dt); let mut swapped = false; for neigh in neigh { if neigh.0 { @@ -110,8 +107,7 @@ pub fn update_liquid(chunks: &mut UpdateChunksType, pos: IVec2, dt: u8) -> HashS let mut swapped = false; for _ in 0..fall_speed { - let state = get_state(chunks, cur_pos); - let neigh = down_neigh(chunks, cur_pos, &[], state, dt); + let neigh = down_neigh(chunks, cur_pos, &[], dt); for neigh in neigh { if neigh.0 { swap(chunks, cur_pos, cur_pos + neigh.1, dt); @@ -127,8 +123,7 @@ pub fn update_liquid(chunks: &mut UpdateChunksType, pos: IVec2, dt: u8) -> HashS if !swapped { set_fspeed(chunks, cur_pos, 0); - let state = get_state(chunks, cur_pos); - let neigh = side_neigh(chunks, cur_pos, &[], state, dt); + let neigh = side_neigh(chunks, cur_pos, &[], dt); let side = if neigh[0].0 { Some(neigh[0].1.x) } else if neigh[1].0 { @@ -139,8 +134,7 @@ pub fn update_liquid(chunks: &mut UpdateChunksType, pos: IVec2, dt: u8) -> HashS if let Some(side) = side { for _ in 0..5 { - let state = get_state(chunks, cur_pos); - if !swapable(chunks, cur_pos + IVec2::new(side, 0), &[], dt, state) { + if !swapable(chunks, cur_pos + IVec2::new(side, 0), &[], dt) { break; } @@ -170,8 +164,7 @@ pub fn update_particle(chunks: &mut UpdateChunksType, pos: IVec2, dt: u8) -> Has // Move for pos in Line::new(cur_pos, vel) { awakened.insert(cur_pos); - let state = get_state(chunks, cur_pos); - if swapable(chunks, pos, &[], dt, state) { + if swapable(chunks, pos, &[], dt) { swap(chunks, cur_pos, pos, dt); cur_pos = pos; awakened.insert(cur_pos); diff --git a/src/chunk.rs b/src/chunk.rs index 0c00c58..4690e46 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -25,7 +25,7 @@ impl Default for Chunk { impl Chunk { pub fn new(texture: Handle, index: IVec2) -> Chunk { - let mut atoms = [Atom::new(); CHUNK_LEN]; + let mut atoms = [Atom::default(); CHUNK_LEN]; match index.y.cmp(&2) { Ordering::Less => {} diff --git a/src/chunk_manager.rs b/src/chunk_manager.rs index a33ecce..65df0d8 100644 --- a/src/chunk_manager.rs +++ b/src/chunk_manager.rs @@ -12,7 +12,6 @@ use crate::prelude::*; #[derive(Default, Resource)] pub struct ChunkManager { pub chunks: HashMap, - pub colliders: ChunkColliders, pub pos: IVec2, pub dt: u8, } @@ -149,68 +148,6 @@ impl std::ops::IndexMut for ChunkManager { } } -#[derive(Default, Clone)] -pub struct ChunkColliders { - data: HashMap>, -} - -impl ChunkColliders { - pub fn get_collider(&self, pos: &ChunkPos) -> Option<&u8> { - if let Some(chunk) = self.data.get(&pos.chunk) { - chunk.get(&pos.atom) - } else { - None - } - } - - pub fn get_mut_collider(&mut self, pos: ChunkPos) -> Option<&mut u8> { - if let Some(chunk) = self.data.get_mut(&pos.chunk) { - chunk.get_mut(&pos.atom) - } else { - None - } - } - - pub fn add_one(&mut self, pos: ChunkPos) { - if let Some(chunk) = self.data.get_mut(&pos.chunk) { - if let Some(collider) = chunk.get_mut(&pos.atom) { - *collider += 1 - } else { - chunk.insert(pos.atom, 1); - } - } else { - let mut chunk_hash = HashMap::new(); - chunk_hash.insert(pos.atom, 1); - self.data.insert(pos.chunk, chunk_hash); - } - } - - pub fn remove_one(&mut self, pos: ChunkPos) { - if self[pos] == 1 { - self.data.get_mut(&pos.chunk).unwrap().remove(&pos.atom); - if self.data.get_mut(&pos.chunk).unwrap().is_empty() { - self.data.remove(&pos.chunk); - } - } else { - self[pos] -= 1; - } - } -} - -impl std::ops::Index for ChunkColliders { - type Output = u8; - #[track_caller] - fn index(&self, pos: ChunkPos) -> &Self::Output { - self.get_collider(&pos).expect("Invalid index position.") - } -} -impl std::ops::IndexMut for ChunkColliders { - #[track_caller] - fn index_mut(&mut self, pos: ChunkPos) -> &mut Self::Output { - self.get_mut_collider(pos).expect("Invalid index position.") - } -} - #[derive(Component)] pub struct DirtyRects { /// The current chunk update dirty rects @@ -278,8 +215,6 @@ pub fn chunk_manager_update( mut chunk_manager: ResMut, mut dirty_rects: Query<&mut DirtyRects>, ) { - let colliders = &chunk_manager.colliders.clone(); - chunk_manager.dt = chunk_manager.dt.wrapping_add(1); let dt = chunk_manager.dt; @@ -434,7 +369,6 @@ pub fn chunk_manager_update( group: chunk_group, dirty_update_rect_send, dirty_render_rect_send, - colliders, }, dt, rect, diff --git a/src/debug.rs b/src/debug.rs index 70b7c89..bb06a92 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -62,10 +62,8 @@ fn brush( let pos = v / ATOM_SIZE as i32; let pos = global_to_chunk(pos); - //Checks if there is a atom at the pos and if the pos is collidable, therefore not drawable - if chunk_manager.get_atom(&pos).is_none() - || chunk_manager.colliders.get_collider(&pos).is_some() - { + //Checks if there is a atom at the pos + if chunk_manager.get_atom(&pos).is_none() { continue; } diff --git a/src/manager_api.rs b/src/manager_api.rs index 0569e4f..112a644 100644 --- a/src/manager_api.rs +++ b/src/manager_api.rs @@ -9,7 +9,6 @@ use crate::prelude::*; pub struct UpdateChunksType<'a> { pub group: ChunkGroup<'a>, - pub colliders: &'a ChunkColliders, pub dirty_update_rect_send: &'a Sender, pub dirty_render_rect_send: &'a Sender, } @@ -51,13 +50,21 @@ pub fn global_to_chunk(mut pos: IVec2) -> ChunkPos { pos.y -= CHUNK_LENGHT as i32; } - let (chunk_x, chunk_y) = (pos.x / CHUNK_LENGHT as i32, pos.y / CHUNK_LENGHT as i32); + let (mut chunk_x, mut chunk_y) = (pos.x / CHUNK_LENGHT as i32, pos.y / CHUNK_LENGHT as i32); + //Hacky stuff for neg coords, but it works let (x_off, y_off) = ( - (CHUNK_LENGHT as i32 - 1) - (pos.x % CHUNK_LENGHT as i32).abs(), - (CHUNK_LENGHT as i32 - 1) - (pos.y % CHUNK_LENGHT as i32).abs(), + (pos.x % CHUNK_LENGHT as i32 + CHUNK_LENGHT as i32) % CHUNK_LENGHT as i32, + (pos.y % CHUNK_LENGHT as i32 + CHUNK_LENGHT as i32) % CHUNK_LENGHT as i32, ); + if pos.x < 0 && x_off == 0 { + chunk_x += 1 + } + if pos.y < 0 && y_off == 0 { + chunk_y += 1 + } + let (x, y) = ( if pos.x >= 0 { pos.x as u32 % CHUNK_LENGHT as u32 @@ -85,28 +92,12 @@ pub fn chunk_to_global(pos: ChunkPos) -> IVec2 { /// See if position is swapable, that means it sees if the position is a void /// or if it's a swapable state and has been not updated -pub fn swapable( - chunks: &UpdateChunksType, - pos: IVec2, - states: &[(State, f32)], - dt: u8, - state: State, -) -> bool { - let local_pos = global_to_local(pos); - let collidable = chunks - .colliders - .get_collider(&ChunkPos::new( - local_pos.0.as_uvec2(), - chunks.group.center_pos, - )) - .is_some(); - +pub fn swapable(chunks: &UpdateChunksType, pos: IVec2, states: &[(State, f32)], dt: u8) -> bool { if let Some(atom) = chunks.group.get_global(pos) { - (atom.state == State::Void + atom.state == State::Void || (states.iter().any(|&(state, prob)| { state == atom.state && rand::thread_rng().gen_range(0.0..1.0) < prob - }) && atom.updated_at != dt)) - && (!collidable || state == State::Liquid) + }) && atom.updated_at != dt) } else { false } @@ -117,13 +108,12 @@ pub fn down_neigh( chunks: &UpdateChunksType, pos: IVec2, states: &[(State, f32)], - state: State, dt: u8, ) -> [(bool, IVec2); 3] { let mut neigh = [(false, IVec2::ZERO); 3]; for (neigh, x) in neigh.iter_mut().zip([0, -1, 1]) { - neigh.0 = swapable(chunks, pos + IVec2::new(x, 1), states, dt, state); + neigh.0 = swapable(chunks, pos + IVec2::new(x, 1), states, dt); neigh.1 = IVec2::new(x, 1); } @@ -139,13 +129,12 @@ pub fn side_neigh( chunks: &UpdateChunksType, pos: IVec2, states: &[(State, f32)], - state: State, dt: u8, ) -> [(bool, IVec2); 2] { let mut neigh = [(false, IVec2::ZERO); 2]; for (neigh, x) in neigh.iter_mut().zip([-1, 1]) { - neigh.0 = swapable(chunks, pos + IVec2::new(x, 0), states, dt, state); + neigh.0 = swapable(chunks, pos + IVec2::new(x, 0), states, dt); neigh.1 = IVec2::new(x, 0); } @@ -182,7 +171,7 @@ pub fn get_fspeed(chunks: &UpdateChunksType, pos: IVec2) -> u8 { } /// Gets state from a global pos -pub fn get_state(chunks: &UpdateChunksType, pos: IVec2) -> State { +pub fn _get_state(chunks: &UpdateChunksType, pos: IVec2) -> State { chunks.group[pos].state } diff --git a/src/player.rs b/src/player.rs index 624413f..f549243 100644 --- a/src/player.rs +++ b/src/player.rs @@ -27,7 +27,6 @@ pub fn player_setup( mut commands: Commands, asset_server: Res, mut texture_atlases: ResMut>, - mut chunk_manager: ResMut, ) { let player_actor = Actor { height: 17, @@ -35,7 +34,6 @@ pub fn player_setup( pos: ivec2(0, 0), vel: vec2(0., 0.), }; - add_actor(&mut chunk_manager, &player_actor); let player_handle = asset_server.load("player/player_sheet.png"); let player_atlas = @@ -181,6 +179,7 @@ pub fn update_player( let mut pos_to_update = vec![]; if mouse.pressed(MouseButton::Right) { + println!("lol"); let new_tool_front = tool_front + tool_slope * 6.; for i in 0..3 { for vec in Line::new( @@ -212,9 +211,9 @@ pub fn update_player( for vec in Line::new(tool_front.as_ivec2(), bound_vec - tool_front.as_ivec2()) { let chunk_pos = global_to_chunk(vec); if let Some(atom) = chunk_manager.get_mut_atom(chunk_pos) { - if atom.state != State::Void { + if atom.state != State::Void && atom.state != State::Object { tool.atoms.push(*atom); - *atom = Atom::new(); + *atom = Atom::default(); pos_to_update.push(chunk_pos); break; } From e5395daa05be985131405c8c18c465486004580e Mon Sep 17 00:00:00 2001 From: Isaac Turci <78173025+Zac8668@users.noreply.github.com> Date: Thu, 4 Jan 2024 11:10:11 -0300 Subject: [PATCH 2/2] Removed debug --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index b1dfca4..7978b09 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,7 @@ fn main() { //local plugins .add_plugins(( ChunkManagerPlugin, - DebugPlugin, + //DebugPlugin, ActorsPlugin, PlayerPlugin, animation::AnimationPlugin,