From 257e228a7af801cecee4f8959133c64c6b50db83 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Wed, 15 Jun 2022 10:28:21 -0500 Subject: [PATCH] Use single collider per tile, and fix other off-by-1 errors. --- src/map.rs | 147 ++++++++--------------------------------------------- 1 file changed, 21 insertions(+), 126 deletions(-) diff --git a/src/map.rs b/src/map.rs index e6ff86d..bc7d4aa 100644 --- a/src/map.rs +++ b/src/map.rs @@ -39,16 +39,6 @@ pub struct MapObstruction; #[reflect(Component)] pub struct Portal; -#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect)] -#[reflect(Component)] -pub struct SpawnColliderPerTile(pub bool); - -impl From for SpawnColliderPerTile { - fn from(v: bool) -> Self { - Self(v) - } -} - #[derive(Component, Clone, Debug, Deref, DerefMut, Reflect)] #[reflect(Component)] pub struct SpawnColliders(pub bool); @@ -132,7 +122,6 @@ impl Default for PortalBundle { pub struct MapBundle { pub map: Map, pub spawn_colliders: SpawnColliders, - pub spawn_collider_per_tile: SpawnColliderPerTile, pub spawn_portals: SpawnPortals, pub transform: Transform, pub global_transform: GlobalTransform, @@ -224,119 +213,29 @@ impl MapFilter for GridBuilder { fn spawn_colliders( mut commands: Commands, - maps: Query<(Entity, &Map, &SpawnColliders, &SpawnColliderPerTile), Changed>, + maps: Query<(Entity, &Map, &SpawnColliders), Changed>, ) { - for (map_entity, map, spawn_colliders, spawn_collider_per_tile) in maps.iter() { + for (map_entity, map, spawn_colliders) in maps.iter() { if **spawn_colliders { commands .entity(map_entity) .remove::() - .remove::() .insert(RigidBody::Fixed); - if **spawn_collider_per_tile { - for y in 0..map.height { - for x in 0..map.width { - let tile = map.at(x, y); - if tile.blocks_motion() { - let id = commands - .spawn() - .insert(Collider::cuboid(0.5, 0.5)) - .insert(Transform::from_xyz(x as f32 + 0.5, y as f32 + 0.5, 0.)) - .insert(GlobalTransform::default()) - .insert(MapObstruction) - .id(); - if tile.blocks_visibility() { - commands.entity(id).insert(Visible::opaque()); - } - commands.entity(map_entity).push_children(&[id]); - } - } - } - } else { - let mut has_body = - vec![vec![false; map.height as usize + 1]; map.width as usize + 1]; - let mut bottom_left = None; - let mut bottom_right = None; - for y in 0..map.height { - for x in 0..map.width { - trace!("Checking ({x}, {y})"); - if bottom_left.is_some() { - if has_body[x][y] { - trace!("Hit another body, setting bottom right"); - bottom_right = Some((x, y)); - } else if map.at(x, y).is_walkable() { - trace!("Hit an empty tile, setting bottom right to ({x}, {y})",); - bottom_right = Some((x, y)); - } - } - if map.at(x, y).is_blocked() && !has_body[x][y] { - trace!("Blocked, setting has_body"); - has_body[x][y] = true; - if bottom_left.is_none() { - trace!("Setting bottom left"); - bottom_left = Some((x, y)); - } - if bottom_left.is_some() && x == map.width - 1 { - trace!("Hit right edge, setting bottom right"); - bottom_right = Some((x, y)); - } - } - if let (Some(bl), Some(br)) = (bottom_left, bottom_right) { - trace!("Got bottom, checking if can extend up"); - let mut top_left = (bl.0, bl.1 + 1); - let mut top_right = (br.0, br.1 + 1); - if y != map.height - 1 { - let mut can_extend_up = true; - for y in bl.1 + 1..map.height { - for x in bl.0..br.0 { - trace!("Extension check: ({x}, {y})"); - if map.at(x, y).is_walkable() { - trace!("Can't, empty tile"); - can_extend_up = false; - break; - } - } - if can_extend_up { - trace!("Can extend up, setting has_body"); - for x in top_left.0..=top_right.0 { - has_body[x][top_left.1] = true; - } - top_left.1 += 1; - top_right.1 += 1; - } else { - break; - } - } - } - let width = br.0 as f32 - bl.0 as f32; - let half_width = width / 2.; - let height = top_left.1 as f32 - bl.1 as f32; - let half_height = height / 2.; - trace!( - "Top left: {:?}\ntop right: {:?}\nbottom left: {:?}\nbottom right: {:?}", - top_left, top_right, bl, br - ); - let center = (bl.0 as f32 + half_width, br.1 as f32 + half_height); - trace!( - "Create shape at {:?} of width {:?} and height {:?}", - center, - width, - height - ); - let id = commands - .spawn() - .insert(Collider::cuboid(half_width, half_height)) - .insert(Transform::from_xyz(center.x(), center.y(), 0.)) - .insert(GlobalTransform::default()) - .insert(MapObstruction) - .id(); - if map.at(x as usize, y as usize).blocks_visibility() { - commands.entity(id).insert(Visible::opaque()); - } - commands.entity(map_entity).push_children(&[id]); - bottom_left = None; - bottom_right = None; + for y in 0..map.height { + for x in 0..map.width { + let tile = map.at(x, y); + if tile.blocks_motion() { + let id = commands + .spawn() + .insert(Collider::cuboid(0.5, 0.5)) + .insert(Transform::from_xyz(x as f32 + 0.5, y as f32 + 0.5, 0.)) + .insert(GlobalTransform::default()) + .insert(MapObstruction) + .id(); + if tile.blocks_visibility() { + commands.entity(id).insert(Visible::opaque()); } + commands.entity(map_entity).push_children(&[id]); } } } @@ -404,8 +303,8 @@ fn spawn_portals( } } for portal in portals { - let x = portal.0 as f32; - let y = portal.1 as f32; + let x = portal.0 as f32 + 0.5; + let y = portal.1 as f32 + 0.5; let portal = commands .spawn_bundle(PortalBundle { transform: Transform::from_translation(Vec3::new(x, y, 0.)), @@ -421,19 +320,15 @@ fn spawn_portals( fn spawn_portal_colliders( mut commands: Commands, map: Query<&SpawnColliders, With>>, - portals: Query<(Entity, &Transform), (With, Without)>, + portals: Query, Without)>, ) { for spawn_colliders in map.iter() { if **spawn_colliders { - for (portal_entity, coordinates) in portals.iter() { - let position = Vec2::new(coordinates.x() + 0.5, coordinates.y() + 0.5); + for portal_entity in portals.iter() { commands .entity(portal_entity) - .insert(Transform::from_xyz(position.x(), position.y(), 0.)) - .insert(GlobalTransform::default()) .insert(Collider::cuboid(0.5, 0.5)) - .insert(Sensor(true)) - .insert(ActiveEvents::COLLISION_EVENTS); + .insert(Sensor(true)); } } }