From 570140f156e159af2ebd3294b1aebddb1d6736b2 Mon Sep 17 00:00:00 2001 From: Extbech Date: Sun, 9 Mar 2025 11:41:58 +0100 Subject: [PATCH 1/5] fps counter plugin init --- src/lib.rs | 17 ++-- src/main.rs | 3 +- src/tools/fps_counter_plugin.rs | 156 ++++++++++++++++++++++++++++++++ src/tools/mod.rs | 1 + 4 files changed, 169 insertions(+), 8 deletions(-) create mode 100644 src/tools/fps_counter_plugin.rs diff --git a/src/lib.rs b/src/lib.rs index 2a134f0..dc7dc4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,23 +1,26 @@ /// Z-value for tile layer 1. -pub const TILE_LAYER_1_Z: f32 = 1.0; +pub const TILE_LAYER_1_Z: f32 = 1.; /// Z-value for tile layer 2. -pub const TILE_LAYER_2_Z: f32 = 2.0; +pub const TILE_LAYER_2_Z: f32 = 2.; /// Z-value for tile layer 3. -pub const TILE_LAYER_3_Z: f32 = 3.0; +pub const TILE_LAYER_3_Z: f32 = 3.; /// Z-value for all projectiles. -pub const PROJECTILES_Z: f32 = 20.0; +pub const PROJECTILES_Z: f32 = 20.; /// Z-value for player character(s). -pub const PLAYER_Z: f32 = 10.0; +pub const PLAYER_Z: f32 = 10.; /// Z-value for enemy characters. -pub const ENEMY_Z: f32 = 10.0; +pub const ENEMY_Z: f32 = 10.; /// Z-value for loot drops. -pub const LOOT_DROPS_Z: f32 = 10.0; +pub const LOOT_DROPS_Z: f32 = 10.; + +/// Z-value for FPS Counter. +pub const FPS_COUNTER_Z: i32 = 100; /// Location of save file. pub const SAVE_FILE: &'static str = "save/save_file.json"; diff --git a/src/main.rs b/src/main.rs index 3f4b54a..ce4ca54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,13 +24,14 @@ use sound::sound_plugin::SoundPlugin; use sprites::add_sprite; use start_game::GamePlugin; use std::time::Duration; -use tools::damage_tracking::DamageTracker; use tools::rng::{GameRng, RngPlugin}; +use tools::{damage_tracking::DamageTracker, fps_counter_plugin::FPSCouterPlugin}; use ui::{start_menu::StartMenuPlugin, upgrade_plugin::UpgradePlugin}; use winit::window::Icon; fn main() { App::new() + .add_plugins(FPSCouterPlugin) .add_plugins(GamePlugin) .add_plugins(SoundPlugin) .insert_state(AppState::MainMenu) diff --git a/src/tools/fps_counter_plugin.rs b/src/tools/fps_counter_plugin.rs new file mode 100644 index 0000000..4108446 --- /dev/null +++ b/src/tools/fps_counter_plugin.rs @@ -0,0 +1,156 @@ +use bevy::{ + app::Plugin, + diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}, + prelude::*, +}; +use test_game::FPS_COUNTER_Z; + +pub struct FPSCouterPlugin; + +impl Plugin for FPSCouterPlugin { + fn build(&self, app: &mut App) { + app.add_plugins(FrameTimeDiagnosticsPlugin) + .add_systems(Startup, setup_fps_counter) + .add_systems( + Update, + ( + fps_counter_showhide, + fps_text_update_system, + fps_color_update_system, + ), + ); + } +} + +/// Marker to find the container entity so we can show/hide the FPS counter +#[derive(Component)] +struct FpsRoot; + +/// Marker to find the text entity so we can update it +#[derive(Component)] +struct FpsText; + +#[derive(Component)] +struct ColorText; + +fn setup_fps_counter(mut commands: Commands, asset_server: Res) { + commands + .spawn(( + FpsRoot, + Node { + position_type: PositionType::Absolute, + right: Val::Percent(1.), + top: Val::Percent(1.), + bottom: Val::Auto, + left: Val::Auto, + padding: UiRect::all(Val::Px(4.0)), + ..Default::default() + }, + ZIndex(FPS_COUNTER_Z), + BackgroundColor(Color::Srgba(Srgba { + red: 0.0, + green: 0.0, + blue: 0.0, + alpha: 0.8, + })), + )) + .with_children(|child| { + child + .spawn(( + Text::new("FPS: "), + TextFont { + font: asset_server.load("font/pixel-font.ttf"), + font_size: 16.0, + ..Default::default() + }, + ColorText, + )) + .with_child(( + TextSpan::default(), + TextFont { + font: asset_server.load("font/pixel-font.ttf"), + font_size: 16.0, + ..Default::default() + }, + FpsText, + ColorText, + )); + }); +} + +fn fps_text_update_system( + diagnostics: Res, + mut query_span: Query<&mut TextSpan, With>, +) { + for mut span in &mut query_span { + // try to get a "smoothed" FPS value from Bevy + if let Some(value) = diagnostics + .get(&FrameTimeDiagnosticsPlugin::FPS) + .and_then(|fps| fps.smoothed()) + { + **span = format!("{value:>4.0}"); + } + } +} +fn fps_color_update_system( + diagnostics: Res, + mut query_color: Query<&mut TextColor, With>, +) { + for mut color in &mut query_color { + // try to get a "smoothed" FPS value from Bevy + if let Some(value) = diagnostics + .get(&FrameTimeDiagnosticsPlugin::FPS) + .and_then(|fps| fps.smoothed()) + { + color.0 = if value >= 120.0 { + // Above 120 FPS, use green color + Color::Srgba(Srgba { + red: 0., + green: 1., + blue: 0., + alpha: 1., + }) + } else if value >= 60.0 { + // Between 60-120 FPS, gradually transition from yellow to green + Color::Srgba(Srgba { + red: 1. - (value - 60. / (120. - 60.)) as f32, + green: 1., + blue: 0., + alpha: 1., + }) + } else if value >= 30.0 { + // Between 30-60 FPS, gradually transition from red to yellow + Color::Srgba(Srgba { + red: 1., + green: ((value - 30.0) / (60.0 - 30.0)) as f32, + blue: 0., + alpha: 1., + }) + } else { + // Below 30 FPS, use red color + Color::Srgba(Srgba { + red: 1., + green: 0., + blue: 0., + alpha: 1., + }) + } + } + } +} + +/// Toggle the FPS counter when pressing F12 +fn fps_counter_showhide( + mut q: Query<&mut Visibility, With>, + kbd: Res>, +) { + if kbd.just_pressed(KeyCode::F12) { + if let Some(mut vis) = q.iter_mut().next() { + println!("f12 pressed: {:?}", vis); + *vis = match *vis { + Visibility::Hidden => Visibility::Visible, + _ => Visibility::Hidden, + }; + } + } +} diff --git a/src/tools/mod.rs b/src/tools/mod.rs index b3acad5..7dbc100 100644 --- a/src/tools/mod.rs +++ b/src/tools/mod.rs @@ -1,3 +1,4 @@ pub mod damage_tracking; pub mod debug; +pub mod fps_counter_plugin; pub mod rng; From b26c5eca4c4088d5414a7f407f9745f1c38edceb Mon Sep 17 00:00:00 2001 From: Extbech Date: Sun, 9 Mar 2025 11:44:49 +0100 Subject: [PATCH 2/5] fine tune upgrade button dimensions --- src/ui/upgrade_plugin.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/ui/upgrade_plugin.rs b/src/ui/upgrade_plugin.rs index db8ae5e..c18b038 100644 --- a/src/ui/upgrade_plugin.rs +++ b/src/ui/upgrade_plugin.rs @@ -48,12 +48,6 @@ pub fn spawn_upgrade_ui( align_items: AlignItems::Center, justify_content: JustifyContent::Center, flex_direction: FlexDirection::Column, - margin: UiRect { - left: Val::Percent(0.), - right: Val::Percent(0.), - top: Val::Percent(0.), - bottom: Val::Percent(10.), - }, ..default() }, BackgroundColor(css::BLACK.into()), @@ -105,8 +99,8 @@ pub fn spawn_upgrade_ui( button_box_child .spawn(( Node { - width: Val::Percent(50.), - height: Val::Percent(50.), + width: Val::Px(350.), + height: Val::Px(100.), align_items: AlignItems::Center, justify_content: JustifyContent::Center, ..default() From 98326035586ae5a71875af9ecaa3b05849223da8 Mon Sep 17 00:00:00 2001 From: Extbech Date: Sun, 9 Mar 2025 11:59:20 +0100 Subject: [PATCH 3/5] update main menu ui and exit game functionality to button --- src/ui/start_menu.rs | 58 +++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/src/ui/start_menu.rs b/src/ui/start_menu.rs index 0b411d9..6eb66cc 100644 --- a/src/ui/start_menu.rs +++ b/src/ui/start_menu.rs @@ -9,6 +9,7 @@ pub const GAME_TITLE: &str = "To be Announced"; enum MenuButtonAction { Play, Upgrade, + ExitGame, } #[derive(Component)] struct MainMenuScreen; @@ -47,13 +48,14 @@ pub fn render_start_menu(mut commands: Commands, asset_server: Res) .spawn(( Node { width: Val::Percent(70.0), - height: Val::Percent(50.0), + height: Val::Percent(90.0), align_items: AlignItems::Center, + justify_content: JustifyContent::SpaceEvenly, flex_direction: FlexDirection::Column, margin: UiRect { left: Val::Percent(0.0), right: Val::Percent(0.0), - top: Val::Percent(10.0), + top: Val::Percent(5.0), bottom: Val::Percent(0.0), }, ..default() @@ -73,14 +75,8 @@ pub fn render_start_menu(mut commands: Commands, asset_server: Res) grandchild .spawn(( Node { - width: Val::Px(300.0), - height: Val::Px(100.0), - margin: UiRect { - left: Val::Percent(0.0), - right: Val::Percent(0.0), - top: Val::Percent(15.0), - bottom: Val::Percent(0.0), - }, + width: Val::Px(350.), + height: Val::Px(100.), justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..default() @@ -93,7 +89,7 @@ pub fn render_start_menu(mut commands: Commands, asset_server: Res) great_grandchild.spawn(( Text::new("Start Game"), TextFont { - font_size: 30.0, + font_size: 30., font: asset_server.load("font/pixel-font.ttf"), ..Default::default() }, @@ -103,14 +99,8 @@ pub fn render_start_menu(mut commands: Commands, asset_server: Res) grandchild .spawn(( Node { - width: Val::Px(300.0), - height: Val::Px(100.0), - margin: UiRect { - left: Val::Percent(0.0), - right: Val::Percent(0.0), - top: Val::Percent(15.0), - bottom: Val::Percent(0.0), - }, + width: Val::Px(350.), + height: Val::Px(100.), justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..default() @@ -123,7 +113,31 @@ pub fn render_start_menu(mut commands: Commands, asset_server: Res) great_grandchild.spawn(( Text::new("Upgrades"), TextFont { - font_size: 30.0, + font_size: 30., + font: asset_server.load("font/pixel-font.ttf"), + ..Default::default() + }, + TextColor(css::WHITE.into()), + )); + }); + grandchild + .spawn(( + Node { + width: Val::Px(350.), + height: Val::Px(100.), + justify_content: JustifyContent::Center, + align_items: AlignItems::Center, + ..default() + }, + Button, + BackgroundColor(css::MIDNIGHT_BLUE.into()), + MenuButtonAction::ExitGame, + )) + .with_children(|great_grandchild| { + great_grandchild.spawn(( + Text::new("Exit Game"), + TextFont { + font_size: 30., font: asset_server.load("font/pixel-font.ttf"), ..Default::default() }, @@ -141,6 +155,7 @@ fn handle_button_click( >, mut app_state: ResMut>, mut sound_event: EventWriter, + mut exit: EventWriter, ) { for (interaction, menu_button_action, mut background_color) in &mut interaction_query { match *interaction { @@ -151,6 +166,9 @@ fn handle_button_click( match menu_button_action { MenuButtonAction::Play => app_state.set(AppState::InGame), MenuButtonAction::Upgrade => app_state.set(AppState::Upgrade), + MenuButtonAction::ExitGame => { + exit.send(AppExit::Success); + } } } Interaction::Hovered => { From 6abb8656272385557305e0d97235f8da1b6aceca Mon Sep 17 00:00:00 2001 From: Extbech Date: Sun, 9 Mar 2025 12:00:13 +0100 Subject: [PATCH 4/5] formatting --- src/mechanics/damage.rs | 5 +++-- src/mobs/boss.rs | 5 ++++- src/start_game.rs | 5 +---- src/tools/debug.rs | 8 +++++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/mechanics/damage.rs b/src/mechanics/damage.rs index e3a02c1..f056b3c 100644 --- a/src/mechanics/damage.rs +++ b/src/mechanics/damage.rs @@ -123,8 +123,9 @@ fn overlapping( } else { let proj = v.dot(mid_angle); let proj_ortho = v.dot(mid_angle.rotate(Vec2::new(0., 1.))); - 0. <= proj && proj <= mid_angle.length_squared() - && proj_ortho*proj_ortho <= radius2*radius2*mid_angle.length_squared() + 0. <= proj + && proj <= mid_angle.length_squared() + && proj_ortho * proj_ortho <= radius2 * radius2 * mid_angle.length_squared() } } } diff --git a/src/mobs/boss.rs b/src/mobs/boss.rs index f1557c9..2e47d0e 100644 --- a/src/mobs/boss.rs +++ b/src/mobs/boss.rs @@ -30,7 +30,10 @@ pub fn wizard_bundle(x: f32, y: f32) -> impl Bundle { TakeDamageHitbox(Circle { radius: Vec2::new(WIZARD_HEIGHT as f32, WIZARD_WIDTH as f32).length() / 2., }), - DealDamageHitbox::Cone(Cone { mid_angle: Vec2::new(50., 50.), angular_width: (1./8.)*PI }), + DealDamageHitbox::Cone(Cone { + mid_angle: Vec2::new(50., 50.), + angular_width: (1. / 8.) * PI, + }), Transform::from_xyz(x, y, ENEMY_Z), SpriteKind::Character(Character::Wizard), EndGameIfDead, diff --git a/src/start_game.rs b/src/start_game.rs index ac4cf7b..7d9caa6 100644 --- a/src/start_game.rs +++ b/src/start_game.rs @@ -89,10 +89,7 @@ impl Plugin for RunningPlugin { fn build(&self, app: &mut App) { const STATE: GameState = GameState::Running; app.add_plugins(CooldownPlugin) - .add_plugins(( - DamagePlugin, - DebugPlugin - )) + .add_plugins((DamagePlugin, DebugPlugin)) .add_systems( Update, ( diff --git a/src/tools/debug.rs b/src/tools/debug.rs index 2888bcc..16b51ff 100644 --- a/src/tools/debug.rs +++ b/src/tools/debug.rs @@ -30,7 +30,7 @@ fn show_weakness( blue: 0., alpha: 0.3, })); - for (TakeDamageHitbox(damage::Circle{radius}), ent) in &q { + for (TakeDamageHitbox(damage::Circle { radius }), ent) in &q { if let Some(mut inent) = commands.get_entity(ent) { inent.insert(ShowWeaknessHitbox); inent.with_children(|parent| { @@ -74,10 +74,12 @@ fn show_damaging( angular_width, }) => { let mut tf = Transform::from_xyz(0., 0., 100.); - tf.rotate_z(2.*PI-mid_angle.to_angle().rem_euclid(2.*PI)); + tf.rotate_z(2. * PI - mid_angle.to_angle().rem_euclid(2. * PI)); inent.with_children(|parent| { parent.spawn(( - Mesh2d(meshes.add(CircularSector::new(mid_angle.length(), *angular_width))), + Mesh2d( + meshes.add(CircularSector::new(mid_angle.length(), *angular_width)), + ), MeshMaterial2d(color.clone()), tf, )); From a573153dec8ef2a30200d9297380ef4a1d964d7b Mon Sep 17 00:00:00 2001 From: Extbech Date: Sun, 9 Mar 2025 12:02:57 +0100 Subject: [PATCH 5/5] docs --- src/tools/fps_counter_plugin.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/fps_counter_plugin.rs b/src/tools/fps_counter_plugin.rs index 4108446..3ba4a33 100644 --- a/src/tools/fps_counter_plugin.rs +++ b/src/tools/fps_counter_plugin.rs @@ -5,6 +5,8 @@ use bevy::{ }; use test_game::FPS_COUNTER_Z; +/// Plugin for enabling a fps counter in the game. +/// This fps counter can be toggled on/off by pressing the `f12` key. pub struct FPSCouterPlugin; impl Plugin for FPSCouterPlugin {