Commit 96901f6e authored by Rahix's avatar Rahix 🦀
Browse files

Configure shift-specific entities, resources, and systems

Add a new method to the AngelShiftImpl trait which angel shifts use to
configure any shift-specific entities, resources, and ECS systems.

As a first implementation, properly implement this for the bottle angel
shift and move the `collect_bottledrops` systems here instead of it
being a generic system.
parent fffb31ae
use crate::colliders;
use crate::components;
use crate::entities;
use crate::resources;
use crate::svg_loader;
pub struct BottleAngelShift {
hours: usize,
level: String,
......@@ -26,4 +32,65 @@ impl super::AngelShiftImpl for BottleAngelShift {
fn level_name(&self) -> &str {
&self.level
}
fn init_gameworld(
&self,
world: &mut legion::World,
resources: &mut legion::Resources,
schedule_builder: &mut legion::systems::Builder,
level: &svg_loader::SvgLevel,
) {
entities::create_drop_points(world, level);
resources.insert(BottleAngelState::new(4));
schedule_builder.add_thread_local(collect_bottledrops_system());
}
}
pub struct BottleAngelState {
collected_drops: usize,
drops_in_map: usize,
}
impl BottleAngelState {
fn new(drops_in_map: usize) -> BottleAngelState {
BottleAngelState {
collected_drops: 0,
drops_in_map,
}
}
}
#[legion::system]
#[read_component(colliders::Collider)]
#[read_component(components::Matebottledrop)]
pub fn collect_bottledrops(
world: &legion::world::SubWorld,
cmd: &mut legion::systems::CommandBuffer,
#[resource] player: &resources::Player,
#[resource] collision_world: &colliders::CollisionWorld,
#[resource] bottle_angel_state: &mut BottleAngelState,
) {
use legion::IntoQuery;
let collider = <&colliders::Collider>::query()
.get(world, player.0)
.unwrap();
let mut bottledrops = <&components::Matebottledrop>::query();
for pair in collision_world
.world
.proximities_with(collider.handle.unwrap(), false)
.unwrap()
{
if pair.3 != ncollide2d::query::Proximity::Intersecting {
continue;
}
let entity = *collision_world.world.objects.get(pair.1).unwrap().data();
if bottledrops.get(world, entity).is_ok() {
cmd.remove(entity);
bottle_angel_state.collected_drops += 1;
}
}
}
use crate::svg_loader;
pub trait AngelShiftImpl {
/// Return metadata about this shift.
///
......@@ -6,6 +8,19 @@ pub trait AngelShiftImpl {
/// Return name of the selected level for this shift.
fn level_name(&self) -> &str;
/// Initialize the shift-specific bits of the game-world
///
/// The world will already contain all common entities and resources. The schedule is
/// configured to run all "game world" systems like collision detection/movement before
/// whatever is added here. After the systems added here, rendering will be scheduled.
fn init_gameworld(
&self,
world: &mut legion::World,
resources: &mut legion::Resources,
schedule_builder: &mut legion::systems::Builder,
level: &svg_loader::SvgLevel,
);
}
pub struct ShiftMetadata {
......@@ -27,4 +42,15 @@ impl AngelShift {
pub fn level_name(&self) -> &str {
self.0.level_name()
}
pub fn init_gameworld(
&self,
world: &mut legion::World,
resources: &mut legion::Resources,
schedule_builder: &mut legion::systems::Builder,
level: &svg_loader::SvgLevel,
) {
self.0
.init_gameworld(world, resources, schedule_builder, level);
}
}
mod bottle_angel;
pub mod bottle_angel;
mod definitions;
pub use definitions::AngelShift;
......
use crate::angel_shifts;
use crate::colliders;
use crate::colors;
use crate::components;
......@@ -21,6 +22,7 @@ impl InGameState {
level: svg_loader::SvgLevel,
mut rendering: resources::Rendering,
player: components::Player,
assigned_shift: angel_shifts::AngelShift,
) -> InGameState {
let sanity_bar = utils::get_element_by_id("sanity-amount").unwrap();
......@@ -38,29 +40,31 @@ impl InGameState {
let player = entities::create_player(&mut world, &resources, &level, player);
resources.insert(resources::Player(player));
entities::create_drop_points(&mut world, &level);
level.apply_colliders(&mut world);
let schedule = legion::Schedule::builder()
let mut schedule_builder = legion::Schedule::builder();
schedule_builder
.add_system(colliders::synchronize_collisision_world_system())
.flush()
.add_system(colliders::update_collision_world_system())
.flush()
.add_thread_local(systems::move_movable_system())
.add_thread_local(systems::sanity_goes_up_and_down_system())
.add_thread_local(systems::collect_bottledrops_system())
.flush();
assigned_shift.init_gameworld(&mut world, &mut resources, &mut schedule_builder, &level);
schedule_builder
.flush()
.add_thread_local(systems::move_camera_to_player_system())
.flush()
.add_thread_local(systems::camera_system())
.add_thread_local(systems::update_sanity_bar_system(sanity_bar))
.flush()
.add_thread_local(systems::draw_level_layer_system(background))
.add_thread_local(systems::draw_sprites_system())
.add_thread_local(systems::draw_level_layer_system(foreground))
.add_thread_local(systems::draw_tmp_matebottledrop_system())
// .add_thread_local(systems::draw_debug_colliders_system())
.build();
;
let schedule = schedule_builder.build();
InGameState {
gui_svg: utils::get_element_by_id("ingame-ui").unwrap(),
......
......@@ -68,6 +68,7 @@ impl gamestate::State for LevelLoadingState {
level,
rendering,
player.clone(),
assigned_shift,
)));
});
gamestate::Transition::Loop
......
......@@ -12,4 +12,4 @@ pub use level::draw_level_layer_system;
pub use moving::{move_camera_to_player_system, move_movable_system};
pub use player::{sanity_goes_up_and_down_system, update_sanity_bar_system};
pub use sprite::draw_sprites_system;
pub use tmp_matebottledrop::{collect_bottledrops_system, draw_tmp_matebottledrop_system};
pub use tmp_matebottledrop::draw_tmp_matebottledrop_system;
use crate::colliders;
use crate::colors;
use crate::components;
use crate::resources;
use legion::IntoQuery;
#[legion::system(for_each)]
pub fn draw_tmp_matebottledrop(
_player: &components::Matebottledrop,
......@@ -22,33 +19,3 @@ pub fn draw_tmp_matebottledrop(
);
rendering.fill();
}
#[legion::system]
#[read_component(colliders::Collider)]
#[read_component(components::Matebottledrop)]
pub fn collect_bottledrops(
world: &legion::world::SubWorld,
cmd: &mut legion::systems::CommandBuffer,
#[resource] player: &resources::Player,
#[resource] collision_world: &colliders::CollisionWorld,
) {
let collider = <&colliders::Collider>::query()
.get(world, player.0)
.unwrap();
let mut bottledrops = <&components::Matebottledrop>::query();
for pair in collision_world
.world
.proximities_with(collider.handle.unwrap(), false)
.unwrap()
{
if pair.3 != ncollide2d::query::Proximity::Intersecting {
continue;
}
let entity = *collision_world.world.objects.get(pair.1).unwrap().data();
if bottledrops.get(world, entity).is_ok() {
cmd.remove(entity);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment