use bevy::{ prelude::*, ui_widgets::ScrollbarPlugin, }; use bevy_common_assets::toml::TomlAssetPlugin; use bevy_rapier2d::{ prelude::*, rapier::prelude::IntegrationParameters, }; pub mod input; pub mod inventory; pub mod item; pub mod layout; pub mod player; #[cfg(test)] mod tests; pub mod ui; pub const PIXELS_PER_METER: f32 = 16.0; pub struct ExpeditionPlugin; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States, Reflect)] #[reflect(Clone, PartialEq, Debug, Default, Hash, State)] pub enum GameState { #[default] Running, Inventory, } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States, Reflect)] #[reflect(Clone, PartialEq, Debug, Default, Hash, State)] pub enum LoadingState { #[default] Loading, Ready, } fn camera_bundle() -> impl Bundle { ( Camera2d, Camera { clear_color: ClearColorConfig::Custom(Color::hsl(0.02, 0.67, 0.65)), ..default() }, Projection::Orthographic(OrthographicProjection { scaling_mode: bevy::camera::ScalingMode::FixedVertical { viewport_height: 384., }, scale: 1., ..OrthographicProjection::default_2d() }), Name::new("Camera2d"), ) } fn insert_entity_name(names: Query<(Entity, &mut Name), Added>) { for (entity, mut name) in names { name.mutate(|name| name.insert_str(0, format!("{entity}: ").as_str())); } } #[inline(always)] pub const fn meters(value: f32) -> f32 { PIXELS_PER_METER * value } fn setup_global(mut commands: Commands) { commands.spawn(camera_bundle()); commands.spawn(ui::UiRoot::new()); } impl Plugin for ExpeditionPlugin { fn build(&self, app: &mut App) { let rapier_init = RapierContextInitialization::InitializeDefaultRapierContext { integration_parameters: IntegrationParameters { length_unit: PIXELS_PER_METER, ..default() }, rapier_configuration: RapierConfiguration { gravity: Vec2::ZERO, physics_pipeline_active: true, scaled_shape_subdivision: 10, force_update_from_transform_changes: false, }, }; app.add_plugins(( RapierDebugRenderPlugin::default(), RapierPhysicsPlugin::<()>::default() .with_custom_initialization(rapier_init), ScrollbarPlugin, TomlAssetPlugin::::new(&["toml"]), input::plugin::InputAssetPlugin::::default(), input::plugin::InputAssetPlugin::::default(), )) .init_state::() .init_state::() .insert_resource(ui::WindowSize::default()) .add_systems(Startup, ( setup_global, layout::systems::setup_world, )) .add_systems(Update, ( insert_entity_name, layout::asset::check_loading .run_if(|state: Res>| *state == LoadingState::Loading), layout::systems::detect_interact_collisions, layout::systems::lock_door, player::systems::handle_input, ui::update_window_size, ui::handle_input, )) .add_systems(OnEnter(LoadingState::Ready), layout::asset::load_level) .add_systems(OnEnter(GameState::Inventory), ui::inventory::systems::setup_ui_inventory) .add_systems(OnExit(GameState::Inventory), ui::inventory::systems::clear_ui_inventory) .add_observer(ui::inventory::observers::on_ui_rotate) .add_observer(layout::container::on_container_interact) .add_observer(layout::door::on_door_interact) .add_observer(layout::lock::on_padlock_interaction) .add_observer(layout::stairs::on_stairs_interact); } }