Allow collider/portal spawning to be run separately.

This commit is contained in:
Nolan Darilek 2021-07-14 12:52:03 -05:00
parent e705451020
commit 3de4b69030

View File

@ -34,6 +34,26 @@ pub struct MapObstruction;
#[reflect(Component)] #[reflect(Component)]
pub struct Portal; pub struct Portal;
#[derive(Clone, Debug, Deref, DerefMut, Reflect)]
#[reflect(Component)]
pub struct SpawnColliders(pub bool);
impl Default for SpawnColliders {
fn default() -> Self {
Self(true)
}
}
#[derive(Clone, Debug, Deref, DerefMut, Reflect)]
#[reflect(Component)]
pub struct SpawnPortals(pub bool);
impl Default for SpawnPortals {
fn default() -> Self {
Self(true)
}
}
pub trait ITileType { pub trait ITileType {
fn blocks_motion(&self) -> bool; fn blocks_motion(&self) -> bool;
fn blocks_visibility(&self) -> bool; fn blocks_visibility(&self) -> bool;
@ -51,7 +71,6 @@ impl ITileType for Tile {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct MapConfig { pub struct MapConfig {
pub autospawn_portals: bool,
pub describe_undescribed_areas: bool, pub describe_undescribed_areas: bool,
pub speak_area_descriptions: bool, pub speak_area_descriptions: bool,
pub start_revealed: bool, pub start_revealed: bool,
@ -60,7 +79,6 @@ pub struct MapConfig {
impl Default for MapConfig { impl Default for MapConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
autospawn_portals: true,
describe_undescribed_areas: false, describe_undescribed_areas: false,
speak_area_descriptions: true, speak_area_descriptions: true,
start_revealed: false, start_revealed: false,
@ -94,6 +112,8 @@ impl Default for PortalBundle {
#[derive(Bundle, Clone, Default)] #[derive(Bundle, Clone, Default)]
pub struct MapBundle { pub struct MapBundle {
pub map: Map, pub map: Map,
pub spawn_colliders: SpawnColliders,
pub spawn_portals: SpawnPortals,
pub children: Children, pub children: Children,
pub transform: Transform, pub transform: Transform,
pub global_transform: GlobalTransform, pub global_transform: GlobalTransform,
@ -171,61 +191,67 @@ impl MapFilter for GridBuilder {
} }
} }
fn add_map_colliders(mut commands: Commands, maps: Query<(Entity, &Map), Added<Map>>) { fn spawn_colliders(
for (map_entity, map) in maps.iter() { mut commands: Commands,
commands.entity(map_entity).insert_bundle(RigidBodyBundle { maps: Query<(Entity, &Map, &SpawnColliders), Changed<SpawnColliders>>,
body_type: RigidBodyType::Static, ) {
..Default::default() for (map_entity, map, spawn_colliders) in maps.iter() {
}); if **spawn_colliders {
for x in 0..map.width { commands.entity(map_entity).remove::<SpawnColliders>();
for y in 0..map.height { commands.entity(map_entity).insert_bundle(RigidBodyBundle {
let tile = map.at(x, y); body_type: RigidBodyType::Static,
if tile.blocks_motion() { ..Default::default()
let id = commands });
.spawn_bundle(ColliderBundle { for x in 0..map.width {
shape: ColliderShape::cuboid(0.5, 0.5), for y in 0..map.height {
..Default::default() let tile = map.at(x, y);
}) if tile.blocks_motion() {
.insert(ColliderParent { let id = commands
handle: map_entity.handle(), .spawn_bundle(ColliderBundle {
pos_wrt_parent: Vec2::new(x as f32 + 0.5, y as f32 + 0.5).into(), shape: ColliderShape::cuboid(0.5, 0.5),
}) ..Default::default()
.insert(MapObstruction) })
.id(); .insert(ColliderParent {
if tile.blocks_visibility() { handle: map_entity.handle(),
commands.entity(id).insert(BlocksVisibility); pos_wrt_parent: Vec2::new(x as f32 + 0.5, y as f32 + 0.5).into(),
})
.insert(MapObstruction)
.id();
if tile.blocks_visibility() {
commands.entity(id).insert(BlocksVisibility);
}
} }
} }
} }
} for room in &map.rooms {
for room in &map.rooms { let shape =
let shape = ColliderShape::cuboid((room.width() / 2) as f32, (room.height() / 2) as f32);
ColliderShape::cuboid((room.width() / 2) as f32, (room.height() / 2) as f32); let position = Vec2::new(room.center().x(), room.center().y()).into();
let position = Vec2::new(room.center().x(), room.center().y()).into(); commands
commands .spawn_bundle(ColliderBundle {
.spawn_bundle(ColliderBundle { collider_type: ColliderType::Sensor,
collider_type: ColliderType::Sensor, shape: shape.clone(),
shape: shape.clone(), flags: ActiveEvents::INTERSECTION_EVENTS.into(),
flags: ActiveEvents::INTERSECTION_EVENTS.into(), ..Default::default()
..Default::default() })
}) .insert(ColliderParent {
.insert(ColliderParent { handle: map_entity.handle(),
handle: map_entity.handle(), pos_wrt_parent: position,
pos_wrt_parent: position, })
}) .insert(shape.compute_aabb(&position))
.insert(shape.compute_aabb(&position)) .insert(AreaTag);
.insert(AreaTag); }
} }
} }
} }
fn portal_spawner( fn spawn_portals(
mut commands: Commands, mut commands: Commands,
map: Query<(Entity, &Map), Added<RigidBodyColliders>>, map: Query<(Entity, &Map, &SpawnPortals), Changed<SpawnPortals>>,
config: Res<MapConfig>,
) { ) {
for (entity, map) in map.iter() { for (entity, map, spawn_portals) in map.iter() {
if config.autospawn_portals { if **spawn_portals {
commands.entity(entity).remove::<SpawnPortals>();
let mut portals: Vec<(f32, f32)> = vec![]; let mut portals: Vec<(f32, f32)> = vec![];
for x in 1..map.width { for x in 1..map.width {
for y in 1..map.height { for y in 1..map.height {
@ -267,6 +293,23 @@ fn portal_spawner(
coordinates, coordinates,
..Default::default() ..Default::default()
}) })
.id();
commands.entity(entity).push_children(&[portal]);
}
}
}
}
fn spawn_portal_colliders(
mut commands: Commands,
map: Query<(Entity, &SpawnColliders), With<Map>>,
portals: Query<(Entity, &Coordinates), Without<ColliderShape>>,
) {
for (map_entity, spawn_colliders) in map.iter() {
if **spawn_colliders {
for (portal_entity, coordinates) in portals.iter() {
commands
.entity(portal_entity)
.insert_bundle(ColliderBundle { .insert_bundle(ColliderBundle {
collider_type: ColliderType::Sensor, collider_type: ColliderType::Sensor,
shape: ColliderShape::cuboid(0.5, 0.5), shape: ColliderShape::cuboid(0.5, 0.5),
@ -275,11 +318,10 @@ fn portal_spawner(
}) })
.insert(ColliderPositionSync::Discrete) .insert(ColliderPositionSync::Discrete)
.insert(ColliderParent { .insert(ColliderParent {
handle: entity.handle(), handle: map_entity.handle(),
pos_wrt_parent: Vec2::new(x + 0.5, y + 0.5).into(), pos_wrt_parent: Vec2::new(coordinates.x() + 0.5, coordinates.y() + 0.5)
}) .into(),
.id(); });
commands.entity(entity).push_children(&[portal]);
} }
} }
} }
@ -331,8 +373,9 @@ impl Plugin for MapPlugin {
} }
let config = app.world().get_resource::<MapConfig>().unwrap().clone(); let config = app.world().get_resource::<MapConfig>().unwrap().clone();
app.register_type::<Portal>() app.register_type::<Portal>()
.add_system(add_map_colliders.system()) .add_system(spawn_colliders.system())
.add_system(portal_spawner.system()); .add_system(spawn_portals.system())
.add_system(spawn_portal_colliders.system());
if config.speak_area_descriptions { if config.speak_area_descriptions {
app.add_system_to_stage(CoreStage::PostUpdate, area_description.system()); app.add_system_to_stage(CoreStage::PostUpdate, area_description.system());
} }