Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Better actors code #30

Merged
merged 2 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 52 additions & 60 deletions src/actors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ChunkManager>, 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<ChunkManager>, 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();
}
}
}
}
}
}
Expand Down Expand Up @@ -45,7 +68,7 @@ pub fn update_actors(mut chunk_manager: ResMut<ChunkManager>, 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 {
Expand All @@ -57,7 +80,11 @@ pub fn update_actors(mut chunk_manager: ResMut<ChunkManager>, 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;
Expand All @@ -78,7 +105,7 @@ pub fn update_actors(mut chunk_manager: ResMut<ChunkManager>, 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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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),
),
);
}
}
27 changes: 10 additions & 17 deletions src/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
}
Expand All @@ -41,6 +38,7 @@ pub enum State {
Powder,
Liquid,
Gas,
Object,
#[default]
Void,
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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 {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Default for Chunk {

impl Chunk {
pub fn new(texture: Handle<Image>, index: IVec2) -> Chunk {
let mut atoms = [Atom::new(); CHUNK_LEN];
let mut atoms = [Atom::default(); CHUNK_LEN];

match index.y.cmp(&2) {
Ordering::Less => {}
Expand Down
66 changes: 0 additions & 66 deletions src/chunk_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::prelude::*;
#[derive(Default, Resource)]
pub struct ChunkManager {
pub chunks: HashMap<IVec2, Chunk>,
pub colliders: ChunkColliders,
pub pos: IVec2,
pub dt: u8,
}
Expand Down Expand Up @@ -149,68 +148,6 @@ impl std::ops::IndexMut<ChunkPos> for ChunkManager {
}
}

#[derive(Default, Clone)]
pub struct ChunkColliders {
data: HashMap<IVec2, HashMap<UVec2, u8>>,
}

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<ChunkPos> 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<ChunkPos> 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
Expand Down Expand Up @@ -278,8 +215,6 @@ pub fn chunk_manager_update(
mut chunk_manager: ResMut<ChunkManager>,
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;

Expand Down Expand Up @@ -434,7 +369,6 @@ pub fn chunk_manager_update(
group: chunk_group,
dirty_update_rect_send,
dirty_render_rect_send,
colliders,
},
dt,
rect,
Expand Down
6 changes: 2 additions & 4 deletions src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn main() {
//local plugins
.add_plugins((
ChunkManagerPlugin,
DebugPlugin,
//DebugPlugin,
ActorsPlugin,
PlayerPlugin,
animation::AnimationPlugin,
Expand Down
Loading