From ac87da83d858b2e07cb3672a41bf2469c27bf3ee Mon Sep 17 00:00:00 2001 From: extrawurst Date: Wed, 26 Mar 2025 02:18:40 +0100 Subject: [PATCH] use gamestates and assetloader --- src/aim/mod.rs | 13 ++++--- src/aim/target_ui.rs | 19 ++++++---- src/alien.rs | 9 ++++- src/backpack/backpack_ui.rs | 25 ++++++------- src/backpack/mod.rs | 4 +- src/camera.rs | 18 +++++---- src/cash.rs | 14 ++++--- src/control/controller.rs | 7 ++-- src/control/controls.rs | 7 +++- src/control/mod.rs | 6 ++- src/cutscene.rs | 3 +- src/heads_ui.rs | 22 +++++------ src/keys.rs | 5 ++- src/loading_assets.rs | 51 ++++++++++++++++++++++++++ src/loading_map.rs | 35 ++++++++++++++++++ src/main.rs | 57 ++++++++++++----------------- src/movables.rs | 7 +++- src/npc.rs | 8 ++-- src/platforms.rs | 8 +++- src/player.rs | 18 ++++++--- src/shooting.rs | 7 +++- src/sounds.rs | 14 ++++--- src/{ => utils}/billboards.rs | 9 ++++- src/utils/mod.rs | 2 + src/{ => utils}/squish_animation.rs | 0 25 files changed, 245 insertions(+), 123 deletions(-) create mode 100644 src/loading_assets.rs create mode 100644 src/loading_map.rs rename src/{ => utils}/billboards.rs (88%) create mode 100644 src/utils/mod.rs rename src/{ => utils}/squish_animation.rs (100%) diff --git a/src/aim/mod.rs b/src/aim/mod.rs index 048f6c6..e7e783a 100644 --- a/src/aim/mod.rs +++ b/src/aim/mod.rs @@ -1,7 +1,9 @@ mod target_ui; use crate::{ + GameState, billboards::Billboard, + loading_assets::UIAssets, player::{Player, PlayerRig}, tb_entities::EnemySpawn, }; @@ -43,14 +45,17 @@ pub fn plugin(app: &mut App) { app.add_plugins(target_ui::plugin); - app.add_systems(Update, (update, move_marker)); + app.add_systems( + Update, + (update, move_marker).run_if(in_state(GameState::Playing)), + ); app.add_observer(marker_event); } fn marker_event( trigger: Trigger, mut commands: Commands, - asset_server: Res, + assets: Res, mut sprite_params: Sprite3dParams, marker: Query>, ) { @@ -62,8 +67,6 @@ fn marker_event( return; }; - let selector = asset_server.load("ui/selector.png"); - let id = commands .spawn(( Name::new("aim-marker"), @@ -71,7 +74,7 @@ fn marker_event( Marker, Transform::default(), Sprite3dBuilder { - image: selector, + image: assets.head_selector.clone(), pixels_per_metre: 30., alpha_mode: AlphaMode::Blend, unlit: true, diff --git a/src/aim/target_ui.rs b/src/aim/target_ui.rs index 943081b..de55ff1 100644 --- a/src/aim/target_ui.rs +++ b/src/aim/target_ui.rs @@ -1,7 +1,9 @@ use super::AimState; use crate::{ + GameState, backpack::BackpackHead, heads_ui::HeadsImages, + loading_assets::UIAssets, npc::{Hitpoints, NpcHead}, }; use bevy::prelude::*; @@ -20,15 +22,11 @@ struct TargetUi { } pub fn plugin(app: &mut App) { - app.add_systems(Startup, setup); - app.add_systems(Update, (sync, update)); + app.add_systems(OnEnter(GameState::Playing), setup); + app.add_systems(Update, (sync, update).run_if(in_state(GameState::Playing))); } -fn setup(mut commands: Commands, asset_server: Res) { - let bg = asset_server.load("ui/head_bg.png"); - let regular = asset_server.load("ui/head_regular.png"); - let damage = asset_server.load("ui/head_damage.png"); - +fn setup(mut commands: Commands, assets: Res) { commands .spawn(( Name::new("target-ui"), @@ -41,7 +39,12 @@ fn setup(mut commands: Commands, asset_server: Res) { }, )) .with_children(|parent| { - spawn_head_ui(parent, bg.clone(), regular.clone(), damage.clone()); + spawn_head_ui( + parent, + assets.head_bg.clone(), + assets.head_regular.clone(), + assets.head_damage.clone(), + ); }); commands.insert_resource(TargetUi::default()); diff --git a/src/alien.rs b/src/alien.rs index adf1d72..4093ab3 100644 --- a/src/alien.rs +++ b/src/alien.rs @@ -1,6 +1,8 @@ use bevy::prelude::*; use std::time::Duration; +use crate::GameState; + pub const ALIEN_ASSET_PATH: &str = "models/alien_naked.glb"; #[derive(Resource)] @@ -10,8 +12,11 @@ pub struct Animations { } pub fn plugin(app: &mut App) { - app.add_systems(Startup, setup); - app.add_systems(Update, (setup_once_loaded, toggle_animation)); + app.add_systems(OnEnter(GameState::Playing), setup); + app.add_systems( + Update, + (setup_once_loaded, toggle_animation).run_if(in_state(GameState::Playing)), + ); } fn setup( diff --git a/src/backpack/backpack_ui.rs b/src/backpack/backpack_ui.rs index 3315a2d..1a4258a 100644 --- a/src/backpack/backpack_ui.rs +++ b/src/backpack/backpack_ui.rs @@ -1,5 +1,5 @@ use super::{BackbackSwapEvent, Backpack, BackpackHead}; -use crate::heads_ui::HeadsImages; +use crate::{GameState, heads_ui::HeadsImages, loading_assets::UIAssets}; use bevy::prelude::*; static HEAD_SLOTS: usize = 5; @@ -44,20 +44,17 @@ impl BackpackUiState { pub fn plugin(app: &mut App) { app.init_resource::(); - app.add_systems(Startup, setup); + app.add_systems(OnEnter(GameState::Playing), setup); app.add_systems( Update, - (update, sync_on_change, update_visibility, update_count), + (update, sync_on_change, update_visibility, update_count) + .run_if(in_state(GameState::Playing)), ); + app.add_observer(swap_head_inputs); } -fn setup(mut commands: Commands, asset_server: Res) { - let bg = asset_server.load("ui/head_bg.png"); - let regular = asset_server.load("ui/head_regular.png"); - let damage = asset_server.load("ui/head_damage.png"); - let selector = asset_server.load("ui/selector.png"); - +fn setup(mut commands: Commands, assets: Res) { commands .spawn(( Name::new("backpack"), @@ -75,10 +72,10 @@ fn setup(mut commands: Commands, asset_server: Res) { for i in 0..HEAD_SLOTS { spawn_head_ui( parent, - bg.clone(), - regular.clone(), - selector.clone(), - damage.clone(), + assets.head_bg.clone(), + assets.head_regular.clone(), + assets.head_selector.clone(), + assets.head_damage.clone(), i, ); } @@ -88,7 +85,7 @@ fn setup(mut commands: Commands, asset_server: Res) { Text::new("0"), BackpackCountText, TextFont { - font: asset_server.load("font.ttf"), + font: assets.font.clone(), font_size: 34.0, ..default() }, diff --git a/src/backpack/mod.rs b/src/backpack/mod.rs index feaac3f..18d5dd4 100644 --- a/src/backpack/mod.rs +++ b/src/backpack/mod.rs @@ -1,6 +1,6 @@ mod backpack_ui; -use crate::heads_ui::HEAD_COUNT; +use crate::{GameState, heads_ui::HEAD_COUNT}; use bevy::prelude::*; pub use backpack_ui::BackpackAction; @@ -28,7 +28,7 @@ pub struct BackbackSwapEvent(pub usize); pub fn plugin(app: &mut App) { app.add_plugins(backpack_ui::plugin); - app.add_systems(Startup, setup); + app.add_systems(OnEnter(GameState::Playing), setup); } fn setup(mut commands: Commands) { diff --git a/src/camera.rs b/src/camera.rs index 27c2688..c24466d 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,7 +1,12 @@ use avian3d::prelude::*; use bevy::prelude::*; -use crate::{control::Controls, control::controller::PlayerMovement, physics_layers::GameLayer}; +use crate::{ + GameState, + control::{Controls, controller::PlayerMovement}, + loading_assets::UIAssets, + physics_layers::GameLayer, +}; #[derive(Component, Reflect, Debug)] pub struct CameraTarget; @@ -43,7 +48,7 @@ pub fn plugin(app: &mut App) { app.register_type::(); app.init_resource::(); - app.add_systems(Startup, startup); + app.add_systems(OnEnter(GameState::Playing), startup); app.add_systems( Update, ( @@ -52,7 +57,8 @@ pub fn plugin(app: &mut App) { update_look_around, rotate_view_keyboard, rotate_view_gamepad, - ), + ) + .run_if(in_state(GameState::Playing)), ); } @@ -76,15 +82,13 @@ fn update_look_around(controls: Res, mut cam_state: ResMut, - asset_server: Res, + assets: Res, query: Query>, ) { if cam_state.is_changed() { let show_ui = cam_state.look_around || cam_state.cutscene; if show_ui { - let image = asset_server.load("ui/camera.png"); - commands .spawn(( CameraUi, @@ -102,7 +106,7 @@ fn update_ui( position_type: PositionType::Absolute, ..default() }, - ImageNode::new(image), + ImageNode::new(assets.camera.clone()), )); } else { for entity in query.iter() { diff --git a/src/cash.rs b/src/cash.rs index ac52750..3c968cb 100644 --- a/src/cash.rs +++ b/src/cash.rs @@ -1,7 +1,6 @@ +use crate::{GameState, loading_assets::UIAssets, sounds::PlaySound}; use bevy::prelude::*; -use crate::sounds::PlaySound; - #[derive(Component, Reflect, Default)] #[reflect(Component)] #[require(Transform)] @@ -21,8 +20,11 @@ pub struct CashCollectEvent; pub fn plugin(app: &mut App) { app.init_resource::(); - app.add_systems(Startup, setup); - app.add_systems(Update, (rotate, update_ui)); + app.add_systems(OnEnter(GameState::Playing), setup); + app.add_systems( + Update, + (rotate, update_ui).run_if(in_state(GameState::Playing)), + ); app.add_observer(on_collect); } @@ -56,12 +58,12 @@ fn update_ui( } } -fn setup(mut commands: Commands, asset_server: Res) { +fn setup(mut commands: Commands, assets: Res) { commands.spawn(( Text::new("0"), CashText, TextFont { - font: asset_server.load("font.ttf"), + font: assets.font.clone(), font_size: 34.0, ..default() }, diff --git a/src/control/controller.rs b/src/control/controller.rs index 3c14cdc..31d3d02 100644 --- a/src/control/controller.rs +++ b/src/control/controller.rs @@ -1,7 +1,7 @@ use avian3d::{math::*, prelude::*}; use bevy::{ecs::query::Has, prelude::*}; -use crate::player::PlayerRig; +use crate::{GameState, player::PlayerRig}; use super::{ControllerSet, Controls, collisions::kinematic_controller_collisions}; @@ -28,7 +28,8 @@ impl Plugin for CharacterControllerPlugin { apply_movement_damping, ) .chain() - .in_set(ControllerSet::ApplyControls), + .in_set(ControllerSet::ApplyControls) + .run_if(in_state(GameState::Playing)), ); app.add_systems( // Run collision handling after collision detection. @@ -36,7 +37,7 @@ impl Plugin for CharacterControllerPlugin { // NOTE: The collision implementation here is very basic and a bit buggy. // A collide-and-slide algorithm would likely work better. PostProcessCollisions, - kinematic_controller_collisions, + kinematic_controller_collisions.run_if(in_state(GameState::Playing)), ); } } diff --git a/src/control/controls.rs b/src/control/controls.rs index 63cc577..5e7bce1 100644 --- a/src/control/controls.rs +++ b/src/control/controls.rs @@ -1,4 +1,6 @@ -use crate::{backpack::BackpackAction, heads_ui::SelectActiveHead, shooting::TriggerState}; +use crate::{ + GameState, backpack::BackpackAction, heads_ui::SelectActiveHead, shooting::TriggerState, +}; use bevy::{ input::{ ButtonState, @@ -22,7 +24,8 @@ pub fn plugin(app: &mut App) { mouse_click.run_if(on_event::), gamepad_connections.run_if(on_event::), ) - .in_set(ControllerSet::CollectInputs), + .in_set(ControllerSet::CollectInputs) + .run_if(in_state(GameState::Playing)), ); } diff --git a/src/control/mod.rs b/src/control/mod.rs index b6fa455..2ecbf99 100644 --- a/src/control/mod.rs +++ b/src/control/mod.rs @@ -1,5 +1,7 @@ use bevy::prelude::*; +use crate::GameState; + mod collisions; pub mod controller; pub mod controls; @@ -28,6 +30,8 @@ pub fn plugin(app: &mut App) { app.add_plugins(controls::plugin); app.configure_sets( Update, - (ControllerSet::CollectInputs, ControllerSet::ApplyControls).chain(), + (ControllerSet::CollectInputs, ControllerSet::ApplyControls) + .chain() + .run_if(in_state(GameState::Playing)), ); } diff --git a/src/cutscene.rs b/src/cutscene.rs index c3d774c..e17603d 100644 --- a/src/cutscene.rs +++ b/src/cutscene.rs @@ -1,4 +1,5 @@ use crate::{ + GameState, camera::CameraState, tb_entities::{CameraTarget, CutsceneCamera, CutsceneCameraMovementEnd}, }; @@ -21,7 +22,7 @@ enum CutsceneState { pub fn plugin(app: &mut App) { app.init_resource::(); - app.add_systems(Update, update); + app.add_systems(Update, update.run_if(in_state(GameState::Playing))); app.add_observer(on_start_cutscene); } diff --git a/src/heads_ui.rs b/src/heads_ui.rs index 655d3ed..1dc375e 100644 --- a/src/heads_ui.rs +++ b/src/heads_ui.rs @@ -1,5 +1,7 @@ use crate::{ + GameState, backpack::{BackbackSwapEvent, Backpack, BackpackHead}, + loading_assets::UIAssets, player::head_id_to_str, }; use bevy::prelude::*; @@ -41,18 +43,13 @@ pub struct HeadChanged(pub usize); pub fn plugin(app: &mut App) { app.register_type::(); - app.add_systems(Startup, setup); - app.add_systems(Update, update); + app.add_systems(OnEnter(GameState::Playing), setup); + app.add_systems(Update, update.run_if(in_state(GameState::Playing))); app.add_observer(on_select_active_head); app.add_observer(on_swap_backpack); } -fn setup(mut commands: Commands, asset_server: Res) { - let bg = asset_server.load("ui/head_bg.png"); - let regular = asset_server.load("ui/head_regular.png"); - let damage = asset_server.load("ui/head_damage.png"); - let selector = asset_server.load("ui/selector.png"); - +fn setup(mut commands: Commands, asset_server: Res, assets: Res) { commands .spawn(Node { position_type: PositionType::Absolute, @@ -65,15 +62,16 @@ fn setup(mut commands: Commands, asset_server: Res) { for i in 0..HEAD_SLOTS { spawn_head_ui( parent, - bg.clone(), - regular.clone(), - selector.clone(), - damage.clone(), + assets.head_bg.clone(), + assets.head_regular.clone(), + assets.head_selector.clone(), + assets.head_damage.clone(), i, ); } }); + // TODO: load via asset loader let heads = (0usize..HEAD_COUNT) .map(|i| asset_server.load(format!("ui/heads/{}.png", head_id_to_str(i)))) .collect(); diff --git a/src/keys.rs b/src/keys.rs index 06492c2..d0c8385 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,5 +1,6 @@ use crate::{ - billboards::Billboard, player::Player, sounds::PlaySound, squish_animation::SquishAnimation, + GameState, billboards::Billboard, player::Player, sounds::PlaySound, + squish_animation::SquishAnimation, }; use avian3d::prelude::*; use bevy::prelude::*; @@ -16,7 +17,7 @@ struct Key(pub String); pub struct KeyCollected(pub String); pub fn plugin(app: &mut App) { - app.add_systems(Update, collect_key); + app.add_systems(Update, collect_key.run_if(in_state(GameState::Playing))); app.add_observer(on_spawn); } diff --git a/src/loading_assets.rs b/src/loading_assets.rs new file mode 100644 index 0000000..e7f3f5a --- /dev/null +++ b/src/loading_assets.rs @@ -0,0 +1,51 @@ +use crate::GameState; +use bevy::prelude::*; +use bevy_asset_loader::prelude::*; + +#[derive(AssetCollection, Resource)] +pub struct AudioAssets { + #[asset(path = "sfx/music/02.ogg")] + pub music: Handle, + #[asset(path = "sfx/ambient/downtown.ogg")] + pub ambient: Handle, + #[asset(path = "sfx/effects/key_collect.ogg")] + pub key_collect: Handle, + #[asset(path = "sfx/abilities/gun.ogg")] + pub gun: Handle, + #[asset(path = "sfx/effects/gate.ogg")] + pub gate: Handle, + #[asset(path = "sfx/effects/cash.ogg")] + pub cash: Handle, + #[asset(path = "sfx/hit", collection(typed))] + pub hit: Vec>, +} + +#[derive(AssetCollection, Resource)] +pub struct UIAssets { + #[asset(path = "font.ttf")] + pub font: Handle, + + #[asset(path = "ui/head_bg.png")] + pub head_bg: Handle, + #[asset(path = "ui/head_regular.png")] + pub head_regular: Handle, + #[asset(path = "ui/head_damage.png")] + pub head_damage: Handle, + #[asset(path = "ui/selector.png")] + pub head_selector: Handle, + + #[asset(path = "ui/camera.png")] + pub camera: Handle, +} + +pub struct LoadingPlugin; +impl Plugin for LoadingPlugin { + fn build(&self, app: &mut App) { + app.add_loading_state( + LoadingState::new(GameState::AssetLoading) + .continue_to_state(GameState::MapLoading) + .load_collection::() + .load_collection::(), + ); + } +} diff --git a/src/loading_map.rs b/src/loading_map.rs new file mode 100644 index 0000000..f6b430d --- /dev/null +++ b/src/loading_map.rs @@ -0,0 +1,35 @@ +use crate::{GameState, physics_layers::GameLayer}; +use avian3d::prelude::*; +use bevy::{prelude::*, scene::SceneInstanceReady}; + +pub fn plugin(app: &mut App) { + app.add_systems(OnEnter(GameState::MapLoading), setup_scene); +} + +fn setup_scene(mut commands: Commands, asset_server: Res) { + commands + .spawn(( + CollisionLayers::new(LayerMask(GameLayer::Level.to_bits()), LayerMask::ALL), + SceneRoot(asset_server.load("maps/map1.map#Scene")), + )) + .observe( + |_t: Trigger, mut next_game_state: ResMut>| { + info!("map loaded"); + + next_game_state.set(GameState::Playing); + }, + ); + + commands.spawn(( + DirectionalLight { + illuminance: light_consts::lux::OVERCAST_DAY, + shadows_enabled: true, + ..default() + }, + Transform { + translation: Vec3::new(0.0, 2.0, 0.0), + rotation: Quat::from_rotation_x(-1.7), + ..default() + }, + )); +} diff --git a/src/main.rs b/src/main.rs index 4d74387..40fd0cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ mod aim; mod alien; mod backpack; -mod billboards; mod camera; mod cash; mod control; @@ -9,6 +8,8 @@ mod cutscene; mod gates; mod heads_ui; mod keys; +mod loading_assets; +mod loading_map; mod movables; mod npc; mod physics_layers; @@ -16,8 +17,8 @@ mod platforms; mod player; mod shooting; mod sounds; -mod squish_animation; mod tb_entities; +mod utils; use avian3d::prelude::*; use bevy::audio::PlaybackMode; @@ -25,12 +26,13 @@ use bevy::audio::Volume; use bevy::core_pipeline::tonemapping::Tonemapping; use bevy::prelude::*; use bevy::render::view::ColorGrading; -use bevy::scene::SceneInstanceReady; use bevy_polyline::PolylinePlugin; use bevy_sprite3d::Sprite3dPlugin; use bevy_trenchbroom::prelude::*; use control::controller::CharacterControllerPlugin; -use physics_layers::GameLayer; +use loading_assets::AudioAssets; +use utils::billboards; +use utils::squish_animation; #[derive(Resource, Reflect, Debug)] #[reflect(Resource)] @@ -42,6 +44,14 @@ struct DebugVisuals { pub cam_follow: bool, } +#[derive(States, Default, Clone, Eq, PartialEq, Debug, Hash)] +enum GameState { + #[default] + AssetLoading, + MapLoading, + Playing, +} + fn main() { let mut app = App::new(); @@ -100,6 +110,10 @@ fn main() { app.add_plugins(sounds::plugin); app.add_plugins(camera::plugin); app.add_plugins(backpack::plugin); + app.add_plugins(loading_assets::LoadingPlugin); + app.add_plugins(loading_map::plugin); + + app.init_state::(); app.insert_resource(AmbientLight { color: Color::WHITE, @@ -107,41 +121,16 @@ fn main() { }); app.insert_resource(ClearColor(Color::BLACK)); - app.add_systems(Startup, (write_trenchbroom_config, music)); - app.add_systems(PostStartup, setup_scene); + app.add_systems(Startup, write_trenchbroom_config); + app.add_systems(OnEnter(GameState::Playing), music); app.add_systems(Update, (set_materials_unlit, set_tonemapping, set_shadows)); app.run(); } -fn setup_scene(mut commands: Commands, asset_server: Res) { - commands - .spawn(( - CollisionLayers::new(LayerMask(GameLayer::Level.to_bits()), LayerMask::ALL), - SceneRoot(asset_server.load("maps/map1.map#Scene")), - )) - .observe(|_t: Trigger| { - //TODO: use for state driven map loading - info!("map loaded"); - }); - +fn music(assets: Res, mut commands: Commands) { commands.spawn(( - DirectionalLight { - illuminance: light_consts::lux::OVERCAST_DAY, - shadows_enabled: true, - ..default() - }, - Transform { - translation: Vec3::new(0.0, 2.0, 0.0), - rotation: Quat::from_rotation_x(-1.7), - ..default() - }, - )); -} - -fn music(asset_server: Res, mut commands: Commands) { - commands.spawn(( - AudioPlayer::new(asset_server.load("sfx/music/02.ogg")), + AudioPlayer::new(assets.music.clone()), PlaybackSettings { mode: PlaybackMode::Loop, volume: Volume::new(0.6), @@ -150,7 +139,7 @@ fn music(asset_server: Res, mut commands: Commands) { )); commands.spawn(( - AudioPlayer::new(asset_server.load("sfx/ambient/downtown.ogg")), + AudioPlayer::new(assets.ambient.clone()), PlaybackSettings { mode: PlaybackMode::Loop, volume: Volume::new(1.), diff --git a/src/movables.rs b/src/movables.rs index 2d614a5..091786a 100644 --- a/src/movables.rs +++ b/src/movables.rs @@ -1,4 +1,7 @@ -use crate::tb_entities::{Movable, MoveTarget}; +use crate::{ + GameState, + tb_entities::{Movable, MoveTarget}, +}; use bevy::{prelude::*, utils::HashSet}; use bevy_trenchbroom::class::Target; @@ -16,7 +19,7 @@ pub struct TriggerMovableEvent(pub HashSet); pub fn plugin(app: &mut App) { app.register_type::(); - app.add_systems(Update, move_active); + app.add_systems(Update, move_active.run_if(in_state(GameState::Playing))); app.add_observer(trigger); } diff --git a/src/npc.rs b/src/npc.rs index 73897ba..90d4d70 100644 --- a/src/npc.rs +++ b/src/npc.rs @@ -1,10 +1,9 @@ -use std::collections::HashMap; - use crate::{ - heads_ui::HEAD_COUNT, keys::KeySpawn, player::head_id_to_str, sounds::PlaySound, + GameState, heads_ui::HEAD_COUNT, keys::KeySpawn, player::head_id_to_str, sounds::PlaySound, tb_entities::EnemySpawn, }; use bevy::prelude::*; +use std::collections::HashMap; #[derive(Event, Reflect)] pub struct Hit { @@ -31,10 +30,9 @@ impl Hitpoints { pub struct NpcHead(pub usize); pub fn plugin(app: &mut App) { - app.add_systems(Update, init); + app.add_systems(OnEnter(GameState::Playing), init); } -// TODO: use game state to initialize only once fn init(mut commands: Commands, query: Query<(Entity, &EnemySpawn), Without>) { let mut names: HashMap = HashMap::default(); for i in 0..HEAD_COUNT { diff --git a/src/platforms.rs b/src/platforms.rs index 406deb2..704ca03 100644 --- a/src/platforms.rs +++ b/src/platforms.rs @@ -1,4 +1,7 @@ -use crate::tb_entities::{Platform, PlatformTarget}; +use crate::{ + GameState, + tb_entities::{Platform, PlatformTarget}, +}; use bevy::{math::ops::sin, prelude::*}; use bevy_trenchbroom::class::Target; @@ -11,7 +14,8 @@ struct ActivePlatform { pub fn plugin(app: &mut App) { app.register_type::(); - app.add_systems(Update, (init, move_active)); + app.add_systems(OnEnter(GameState::Playing), init); + app.add_systems(Update, move_active.run_if(in_state(GameState::Playing))); } fn init( diff --git a/src/player.rs b/src/player.rs index 0c59d5b..d1039d8 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,9 +1,12 @@ use crate::{ + GameState, alien::{ALIEN_ASSET_PATH, Animations}, camera::{CameraArmRotation, CameraTarget}, cash::{Cash, CashCollectEvent}, - control::Controls, - control::controller::{CharacterControllerBundle, PlayerMovement}, + control::{ + Controls, + controller::{CharacterControllerBundle, PlayerMovement}, + }, heads_ui::HeadChanged, physics_layers::GameLayer, tb_entities::SpawnPoint, @@ -40,18 +43,22 @@ struct PlayerSpawned { pub fn plugin(app: &mut App) { app.init_resource::(); app.add_systems(Startup, (toggle_cursor_system, cursor_recenter)); + app.add_systems(OnEnter(GameState::Playing), spawn); app.add_systems( Update, ( - spawn, collect_cash, toggle_animation, setup_animations_marker_for_player, toggle_cursor_system.run_if(input_just_pressed(KeyCode::Escape)), - ), + ) + .run_if(in_state(GameState::Playing)), ); - app.add_systems(Update, (rotate_view_keyboard, rotate_view_gamepad)); + app.add_systems( + Update, + (rotate_view_keyboard, rotate_view_gamepad).run_if(in_state(GameState::Playing)), + ); app.add_observer(update_head); } @@ -259,6 +266,7 @@ fn update_head( let head_str = head_id_to_str(trigger.0); + //TODO: use asset loader commands.spawn(( AudioPlayer::new(asset_server.load(format!("sfx/heads/{}.ogg", head_str))), PlaybackSettings::DESPAWN, diff --git a/src/shooting.rs b/src/shooting.rs index bf49522..41b8cc1 100644 --- a/src/shooting.rs +++ b/src/shooting.rs @@ -1,4 +1,5 @@ use crate::{ + GameState, aim::AimState, billboards::Billboard, npc::Hit, @@ -39,10 +40,11 @@ struct ShotAssets { struct AnimationTimer(Timer); pub fn plugin(app: &mut App) { - app.add_systems(Startup, setup); + app.add_systems(OnEnter(GameState::Playing), setup); app.add_systems( Update, - (update, shot_collision, enemy_hit, timeout, animate_sprite), + (update, shot_collision, enemy_hit, timeout, animate_sprite) + .run_if(in_state(GameState::Playing)), ); app.add_observer(on_trigger_state); } @@ -52,6 +54,7 @@ fn setup( asset_server: Res, mut sprite_params: Sprite3dParams, ) { + // TODO: use asset server let image = asset_server.load("textures/fx/impact.png"); let layout = TextureAtlasLayout::from_grid(UVec2::splat(256), 7, 6, None, None); let texture_atlas_layout = sprite_params.atlas_layouts.add(layout); diff --git a/src/sounds.rs b/src/sounds.rs index 3e1841c..6e746f4 100644 --- a/src/sounds.rs +++ b/src/sounds.rs @@ -1,5 +1,7 @@ use bevy::prelude::*; +use crate::loading_assets::AudioAssets; + #[derive(Event, Copy, Clone, Debug)] pub enum PlaySound { Hit, @@ -18,7 +20,7 @@ fn spawn_sounds( mut commands: Commands, // sound_res: Res, // settings: SettingsRead, - asset_server: Res, + assets: Res, ) { let event = trigger.event(); @@ -29,12 +31,12 @@ fn spawn_sounds( let source = match event { PlaySound::Hit => { let version = rand::random::() % 3; - asset_server.load(format!("sfx/hit/hit_0{version}.ogg")) + assets.hit[version as usize].clone() } - PlaySound::KeyCollect => asset_server.load("sfx/effects/key_collect.ogg"), - PlaySound::Gun => asset_server.load("sfx/abilities/gun.ogg"), - PlaySound::Gate => asset_server.load("sfx/effects/gate.ogg"), - PlaySound::CashCollect => asset_server.load("sfx/effects/cash.ogg"), + PlaySound::KeyCollect => assets.key_collect.clone(), + PlaySound::Gun => assets.gun.clone(), + PlaySound::Gate => assets.gate.clone(), + PlaySound::CashCollect => assets.cash.clone(), }; commands.spawn(( diff --git a/src/billboards.rs b/src/utils/billboards.rs similarity index 88% rename from src/billboards.rs rename to src/utils/billboards.rs index ccd4ebd..64dc111 100644 --- a/src/billboards.rs +++ b/src/utils/billboards.rs @@ -22,7 +22,10 @@ fn face_camera( >, parent_transform: Query<&GlobalTransform>, ) { - let cam_transform = cam_query.single(); + let Ok(cam_transform) = cam_query.get_single() else { + return; + }; + for (mut transform, parent, visible) in query.iter_mut() { if !matches!(*visible, InheritedVisibility::VISIBLE) { continue; @@ -41,7 +44,9 @@ fn face_camera_no_parent( cam_query: Query<&GlobalTransform, With>, mut query: Query<&mut Transform, (With, Without, Without)>, ) { - let cam_transform = cam_query.single(); + let Ok(cam_transform) = cam_query.get_single() else { + return; + }; for mut transform in query.iter_mut() { transform.look_at(cam_transform.translation(), Vec3::Y); } diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..d7f2272 --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1,2 @@ +pub mod billboards; +pub mod squish_animation; diff --git a/src/squish_animation.rs b/src/utils/squish_animation.rs similarity index 100% rename from src/squish_animation.rs rename to src/utils/squish_animation.rs