diff --git a/src/map.rs b/src/map.rs index c96a61b..258135e 100644 --- a/src/map.rs +++ b/src/map.rs @@ -82,8 +82,7 @@ impl ITileType for Tile { pub struct PortalBundle { pub portal: Portal, pub mappable: Mappable, - pub transform: Transform, - pub global_transform: GlobalTransform, + pub transform: TransformBundle, } #[derive(Bundle, Clone, Default)] @@ -91,8 +90,75 @@ pub struct MapBundle { pub map: Map, pub spawn_colliders: SpawnColliders, pub spawn_portals: SpawnPortals, - pub transform: Transform, - pub global_transform: GlobalTransform, + pub transform: TransformBundle, +} + +#[derive(Bundle, Clone, Debug)] +pub struct TileBundle { + pub transform: TransformBundle, + pub collider: Collider, + pub rigid_body: RigidBody, + pub active_collision_types: ActiveCollisionTypes, + pub map_obstruction: MapObstruction, +} + +impl Default for TileBundle { + fn default() -> Self { + Self { + transform: default(), + collider: Collider::cuboid(0.5, 0.5), + rigid_body: RigidBody::Fixed, + active_collision_types: ActiveCollisionTypes::default() + | ActiveCollisionTypes::KINEMATIC_STATIC + | ActiveCollisionTypes::DYNAMIC_STATIC, + map_obstruction: MapObstruction, + } + } +} + +impl TileBundle { + pub fn new(x: i32, y: i32) -> Self { + Self { + transform: Transform::from_xyz(x as f32 + 0.5, y as f32 + 0.5, 0.).into(), + ..default() + } + } +} + +#[derive(Bundle, Clone, Debug)] +pub struct ZoneBundle { + pub collider: Collider, + pub transform: TransformBundle, + pub area: Area, + pub zone: Zone, + pub sensor: Sensor, + pub active_events: ActiveEvents, +} + +impl ZoneBundle { + fn new(collider: Collider, position: (f32, f32)) -> Self { + let point = Isometry2::new(Vector2::new(position.0, position.1), 0.); + let aabb = collider.raw.compute_aabb(&point); + Self { + collider, + area: Area(aabb), + transform: Transform::from_translation(Vec3::new(position.0, position.1, 0.)).into(), + zone: default(), + sensor: default(), + active_events: ActiveEvents::COLLISION_EVENTS, + } + } +} + +impl From<&MRect> for ZoneBundle { + fn from(rect: &MRect) -> Self { + let collider = Collider::cuboid( + rect.width() as f32 / 2. + 0.5, + rect.height() as f32 / 2. + 0.5, + ); + let position = (rect.center().x(), rect.center().y()); + Self::new(collider, position) + } } pub struct GridBuilder { @@ -125,14 +191,13 @@ impl MapFilter for GridBuilder { if let Ok(maze) = generator.generate(self.width_in_rooms as i32, self.height_in_rooms as i32) { - let total_height = (self.room_height + 1) * self.height_in_rooms + 1; + let total_height = self.room_height * self.height_in_rooms + self.height_in_rooms + 1; let half_width = self.room_width / 2; let half_height = self.room_height / 2; for y in 0..self.height_in_rooms { for x in 0..self.width_in_rooms { let x_offset = x * (self.room_width + 1); - let y_offset = - total_height - (y * (self.room_height + 1)) - self.room_height - 2; + let y_offset = total_height - (y + 1) * (self.room_height + 1) - 1; let room = MRect::new_i32( x_offset as i32 + 1, y_offset as i32 + 1, @@ -190,21 +255,7 @@ fn spawn_colliders( for x in 0..map.width { if let Some(tile) = map.at(x, y) { if tile.blocks_motion() { - let id = commands - .spawn(( - RigidBody::Fixed, - TransformBundle::from_transform(Transform::from_xyz( - x as f32 + 0.5, - y as f32 + 0.5, - 0., - )), - Collider::cuboid(0.5, 0.5), - ActiveCollisionTypes::default() - | ActiveCollisionTypes::KINEMATIC_STATIC - | ActiveCollisionTypes::DYNAMIC_STATIC, - MapObstruction, - )) - .id(); + let id = commands.spawn(TileBundle::new(x as i32, y as i32)).id(); if tile.blocks_visibility() { commands.entity(id).insert(Visible::opaque()); } @@ -214,26 +265,8 @@ fn spawn_colliders( } } for room in &map.rooms { - let shape = Collider::cuboid( - (room.width() / 2) as f32 + 0.5, - (room.height() / 2) as f32 + 0.5, - ); - let position = - Isometry2::new(Vector2::new(room.center().x(), room.center().y()), 0.); - let aabb = shape.raw.compute_aabb(&position); commands.entity(map_entity).with_children(|parent| { - parent.spawn(( - TransformBundle::from_transform(Transform::from_xyz( - position.translation.x, - position.translation.y, - 0., - )), - shape, - Sensor, - ActiveEvents::COLLISION_EVENTS, - Area(aabb), - Zone, - )); + parent.spawn(ZoneBundle::from(room)); }); } } @@ -248,21 +281,19 @@ fn spawn_portals( if **spawn_portals { commands.entity(map_entity).remove::(); let mut portals: Vec<(f32, f32)> = vec![]; - for x in 1..map.width { - for y in 1..map.height { + for x in 0..map.width { + for y in 0..map.height { + let idx = (x, y).to_index(map.width); let mut spawn_portal = false; - if map.get_available_exits(x, y).len() > 2 { - let idx = (x, y).to_index(map.width); - if map.tiles[idx].is_walkable() - && (x > 1 && map.tiles[idx - 1].is_walkable()) + if map.get_available_exits(x, y).len() > 2 && map.tiles[idx].is_walkable() { + if (x > 1 && map.tiles[idx - 1].is_walkable()) && (x < map.width - 2 && map.tiles[idx + 1].is_walkable()) && (y > 1 && map.tiles[idx - map.width].is_blocked()) && (y < map.height - 2 && map.tiles[idx + map.width].is_blocked()) { spawn_portal = true; } - if map.tiles[idx].is_walkable() - && (x > 1 && map.tiles[idx - 1].is_blocked()) + if (x > 1 && map.tiles[idx - 1].is_blocked()) && (x < map.width - 2 && map.tiles[idx + 1].is_blocked()) && (y > 1 && map.tiles[idx - map.width].is_walkable()) && (y < map.height - 2 && map.tiles[idx + map.width].is_walkable()) @@ -282,7 +313,7 @@ fn spawn_portals( for (x, y) in portals { commands.entity(map_entity).with_children(|parent| { parent.spawn(PortalBundle { - transform: Transform::from_translation(Vec3::new(x, y, 0.)), + transform: Transform::from_translation(Vec3::new(x, y, 0.)).into(), ..default() }); });