use gamestates and assetloader

This commit is contained in:
2025-03-26 02:18:40 +01:00
parent 9842148010
commit ac87da83d8
25 changed files with 245 additions and 123 deletions

View File

@@ -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<MarkerEvent>,
mut commands: Commands,
asset_server: Res<AssetServer>,
assets: Res<UIAssets>,
mut sprite_params: Sprite3dParams,
marker: Query<Entity, With<Marker>>,
) {
@@ -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,

View File

@@ -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<AssetServer>) {
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<UIAssets>) {
commands
.spawn((
Name::new("target-ui"),
@@ -41,7 +39,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
},
))
.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());

View File

@@ -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(

View File

@@ -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::<BackpackUiState>();
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<AssetServer>) {
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<UIAssets>) {
commands
.spawn((
Name::new("backpack"),
@@ -75,10 +72,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
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<AssetServer>) {
Text::new("0"),
BackpackCountText,
TextFont {
font: asset_server.load("font.ttf"),
font: assets.font.clone(),
font_size: 34.0,
..default()
},

View File

@@ -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) {

View File

@@ -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::<MainCamera>();
app.init_resource::<CameraState>();
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<Controls>, mut cam_state: ResMut<CameraState
fn update_ui(
mut commands: Commands,
cam_state: Res<CameraState>,
asset_server: Res<AssetServer>,
assets: Res<UIAssets>,
query: Query<Entity, With<CameraUi>>,
) {
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() {

View File

@@ -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::<CashResource>();
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<AssetServer>) {
fn setup(mut commands: Commands, assets: Res<UIAssets>) {
commands.spawn((
Text::new("0"),
CashText,
TextFont {
font: asset_server.load("font.ttf"),
font: assets.font.clone(),
font_size: 34.0,
..default()
},

View File

@@ -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)),
);
}
}

View File

@@ -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::<MouseButtonInput>),
gamepad_connections.run_if(on_event::<GamepadEvent>),
)
.in_set(ControllerSet::CollectInputs),
.in_set(ControllerSet::CollectInputs)
.run_if(in_state(GameState::Playing)),
);
}

View File

@@ -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)),
);
}

View File

@@ -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::<CutsceneState>();
app.add_systems(Update, update);
app.add_systems(Update, update.run_if(in_state(GameState::Playing)));
app.add_observer(on_start_cutscene);
}

View File

@@ -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::<HeadDamage>();
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<AssetServer>) {
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<AssetServer>, assets: Res<UIAssets>) {
commands
.spawn(Node {
position_type: PositionType::Absolute,
@@ -65,15 +62,16 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
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();

View File

@@ -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);
}

51
src/loading_assets.rs Normal file
View File

@@ -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<AudioSource>,
#[asset(path = "sfx/ambient/downtown.ogg")]
pub ambient: Handle<AudioSource>,
#[asset(path = "sfx/effects/key_collect.ogg")]
pub key_collect: Handle<AudioSource>,
#[asset(path = "sfx/abilities/gun.ogg")]
pub gun: Handle<AudioSource>,
#[asset(path = "sfx/effects/gate.ogg")]
pub gate: Handle<AudioSource>,
#[asset(path = "sfx/effects/cash.ogg")]
pub cash: Handle<AudioSource>,
#[asset(path = "sfx/hit", collection(typed))]
pub hit: Vec<Handle<AudioSource>>,
}
#[derive(AssetCollection, Resource)]
pub struct UIAssets {
#[asset(path = "font.ttf")]
pub font: Handle<Font>,
#[asset(path = "ui/head_bg.png")]
pub head_bg: Handle<Image>,
#[asset(path = "ui/head_regular.png")]
pub head_regular: Handle<Image>,
#[asset(path = "ui/head_damage.png")]
pub head_damage: Handle<Image>,
#[asset(path = "ui/selector.png")]
pub head_selector: Handle<Image>,
#[asset(path = "ui/camera.png")]
pub camera: Handle<Image>,
}
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::<AudioAssets>()
.load_collection::<UIAssets>(),
);
}
}

35
src/loading_map.rs Normal file
View File

@@ -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<AssetServer>) {
commands
.spawn((
CollisionLayers::new(LayerMask(GameLayer::Level.to_bits()), LayerMask::ALL),
SceneRoot(asset_server.load("maps/map1.map#Scene")),
))
.observe(
|_t: Trigger<SceneInstanceReady>, mut next_game_state: ResMut<NextState<GameState>>| {
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()
},
));
}

View File

@@ -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::<GameState>();
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<AssetServer>) {
commands
.spawn((
CollisionLayers::new(LayerMask(GameLayer::Level.to_bits()), LayerMask::ALL),
SceneRoot(asset_server.load("maps/map1.map#Scene")),
))
.observe(|_t: Trigger<SceneInstanceReady>| {
//TODO: use for state driven map loading
info!("map loaded");
});
fn music(assets: Res<AudioAssets>, 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<AssetServer>, 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<AssetServer>, 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.),

View File

@@ -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<String>);
pub fn plugin(app: &mut App) {
app.register_type::<ActiveMovable>();
app.add_systems(Update, move_active);
app.add_systems(Update, move_active.run_if(in_state(GameState::Playing)));
app.add_observer(trigger);
}

View File

@@ -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<Hitpoints>>) {
let mut names: HashMap<String, usize> = HashMap::default();
for i in 0..HEAD_COUNT {

View File

@@ -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::<ActivePlatform>();
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(

View File

@@ -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::<PlayerSpawned>();
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,

View File

@@ -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<AssetServer>,
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);

View File

@@ -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<AudioAssets>,
// settings: SettingsRead,
asset_server: Res<AssetServer>,
assets: Res<AudioAssets>,
) {
let event = trigger.event();
@@ -29,12 +31,12 @@ fn spawn_sounds(
let source = match event {
PlaySound::Hit => {
let version = rand::random::<u8>() % 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((

View File

@@ -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<Camera>>,
mut query: Query<&mut Transform, (With<Billboard>, Without<Camera>, Without<Parent>)>,
) {
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);
}

2
src/utils/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod billboards;
pub mod squish_animation;