diff --git a/examples/platformer/systems.rs b/examples/platformer/systems.rs index a072e801..32edf65d 100644 --- a/examples/platformer/systems.rs +++ b/examples/platformer/systems.rs @@ -84,14 +84,13 @@ pub fn spawn_wall_collision( ) { /// Represents a wide wall that is 1 tile tall /// Used to spawn wall collisions - #[derive(Copy, Clone, Eq, PartialEq, Debug, Default, Hash)] + #[derive(Clone, Eq, PartialEq, Debug, Default, Hash)] struct Plate { left: i32, right: i32, } /// A simple rectangle type representing a wall of any size - #[derive(Copy, Clone, Eq, PartialEq, Debug, Default, Hash)] struct Rect { left: i32, right: i32, @@ -115,7 +114,7 @@ pub fn spawn_wall_collision( if let Ok(grandparent) = parent_query.get(parent.get()) { level_to_wall_locations .entry(grandparent.get()) - .or_insert(HashSet::new()) + .or_default() .insert(grid_coords); } }); @@ -145,8 +144,7 @@ pub fn spawn_wall_collision( let mut row_plates: Vec = Vec::new(); let mut plate_start = None; - // + 1 to the width so the algorithm "terminates" plates that touch the right - // edge + // + 1 to the width so the algorithm "terminates" plates that touch the right edge for x in 0..width + 1 { match (plate_start, level_walls.contains(&GridCoords { x, y })) { (Some(s), false) => { @@ -165,40 +163,34 @@ pub fn spawn_wall_collision( } // combine "plates" into rectangles across multiple rows + let mut rect_builder: HashMap = HashMap::new(); + let mut prev_row: Vec = Vec::new(); let mut wall_rects: Vec = Vec::new(); - let mut previous_rects: HashMap = HashMap::new(); - // an extra empty row so the algorithm "terminates" the rects that touch the top - // edge + // an extra empty row so the algorithm "finishes" the rects that touch the top edge plate_stack.push(Vec::new()); - for (y, row) in plate_stack.iter().enumerate() { - let mut current_rects: HashMap = HashMap::new(); - for plate in row { - if let Some(previous_rect) = previous_rects.remove(plate) { - current_rects.insert( - *plate, - Rect { - top: previous_rect.top + 1, - ..previous_rect - }, - ); - } else { - current_rects.insert( - *plate, - Rect { - bottom: y as i32, - top: y as i32, - left: plate.left, - right: plate.right, - }, - ); + for (y, current_row) in plate_stack.into_iter().enumerate() { + for prev_plate in &prev_row { + if !current_row.contains(prev_plate) { + // remove the finished rect so that the same plate in the future starts a new rect + if let Some(rect) = rect_builder.remove(prev_plate) { + wall_rects.push(rect); + } } } - - // Any plates that weren't removed above have terminated - wall_rects.append(&mut previous_rects.values().copied().collect()); - previous_rects = current_rects; + for plate in ¤t_row { + rect_builder + .entry(plate.clone()) + .and_modify(|e| e.top += 1) + .or_insert(Rect { + bottom: y as i32, + top: y as i32, + left: plate.left, + right: plate.right, + }); + } + prev_row = current_row; } commands.entity(level_entity).with_children(|level| { diff --git a/src/utils.rs b/src/utils.rs index 6488b1e4..a67bacba 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -86,7 +86,7 @@ pub fn calculate_transform_from_entity_instance( let translation = ldtk_pixel_coords_to_translation_pivoted( entity_instance.px, - level_height as i32, + level_height, size, entity_instance.pivot, );