Skip to content

Commit

Permalink
Ep 10: UI (#5)
Browse files Browse the repository at this point in the history
* add AssetHandlerPlugin

* alpha main menu skeleton

* alpha title, play button, and quit button bundle

* alpha play and quit button

* title section

* add button color change on interaction

* add on button pressed

* separate main menu code to main_menu.rs

* update button hovered color

* rename UiButton to UIButton and add run condition

* add GameState::Stop when game over

* alpha pause_menu.rs

* simplify main menu

* simplify pause menu

* .

* GameState::Stop

* alpha game over menu

* alpha hud

* .

* move update final score text to one time process on startup

* fix CollidedWithEnemy being spawned twice

* fix size
  • Loading branch information
rahmatnazali authored Jul 17, 2024
1 parent 506bf46 commit e6a66ee
Show file tree
Hide file tree
Showing 11 changed files with 1,085 additions and 41 deletions.
42 changes: 42 additions & 0 deletions src/asset_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use bevy::prelude::{
App, AssetServer, AudioSource, Handle, Image, Plugin, Res, ResMut, Resource, Startup,
};

#[derive(Resource, Debug, Default)]
pub struct AssetHandler {
pub player_texture: Handle<Image>,
pub enemy_texture: Handle<Image>,
pub star_texture: Handle<Image>,
pub bounce_1_sound: Handle<AudioSource>,
pub bounce_2_sound: Handle<AudioSource>,
pub obtain_star_sound: Handle<AudioSource>,
pub game_over_sound: Handle<AudioSource>,
}

pub struct AssetHandlerPlugin;
impl Plugin for AssetHandlerPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<AssetHandler>()
.add_systems(Startup, load_assets);
}
}

fn load_assets(mut scene_assets: ResMut<AssetHandler>, asset_server: Res<AssetServer>) {
scene_assets.player_texture = asset_server.load("sprites/ball_blue_large.png");
scene_assets.enemy_texture = asset_server.load("sprites/ball_red_large.png");
scene_assets.star_texture = asset_server.load("sprites/star.png");
scene_assets.bounce_1_sound = asset_server.load("audio/pluck_001.ogg");
scene_assets.bounce_2_sound = asset_server.load("audio/pluck_002.ogg");
scene_assets.obtain_star_sound = asset_server.load("audio/laserLarge_000.ogg");
scene_assets.game_over_sound = asset_server.load("audio/explosionCrunch_000.ogg");

// *scene_assets = SceneAssets {
// player_texture: asset_server.load("sprites/ball_blue_large.png"),
// enemy_texture: asset_server.load("sprites/ball_red_large.png"),
// star_texture: asset_server.load("sprites/star.png"),
// bounce_1_sound: asset_server.load("audio/pluck_001.ogg"),
// bounce_2_sound: asset_server.load("audio/pluck_002.ogg"),
// obtain_star_sound: asset_server.load("audio/laserLarge_000.ogg"),
// game_over_sound: asset_server.load("audio/explosionCrunch_000.ogg"),
// };
}
15 changes: 8 additions & 7 deletions src/game/enemy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use bevy::prelude::{
use bevy::window::PrimaryWindow;

use crate::{ApplicationState, ScheduleDespawn};
use crate::asset_handler::AssetHandler;
use crate::game::{Confined, GameState, Size};
use crate::helpers::{AudioHelper, RandomHelper, SpriteHelper};
use crate::helpers::{AudioHelper, RandomHelper};

pub struct EnemyPlugin;

Expand Down Expand Up @@ -57,7 +58,7 @@ impl EnemyBundle {

pub fn at_randomized_location(
window: &Window,
asset_server: &Res<AssetServer>,
asset_handler: &Res<AssetHandler>,
) -> (Name, Enemy, Confined, Size, SpriteBundle) {
let random_x = RandomHelper::random_f32() * window.width();
let random_y = RandomHelper::random_f32() * window.height();
Expand All @@ -71,7 +72,7 @@ impl EnemyBundle {
Size { value: ENEMY_SIZE },
SpriteBundle {
transform: Transform::from_xyz(random_x, random_y, 0.0),
texture: asset_server.load(SpriteHelper::enemy_sprite()),
texture: asset_handler.enemy_texture.clone(),
..default()
},
)
Expand All @@ -93,12 +94,12 @@ impl Default for EnemySpawnTimer {

pub fn spawn_initial_enemies(
mut commands: Commands,
asset_server: Res<AssetServer>,
asset_handler: Res<AssetHandler>,
window_query: Query<&Window, With<PrimaryWindow>>,
) {
if let Ok(window) = window_query.get_single() {
for _ in 0..NUMBER_OF_ENEMIES {
commands.spawn(EnemyBundle::at_randomized_location(window, &asset_server));
commands.spawn(EnemyBundle::at_randomized_location(window, &asset_handler));
}
}
}
Expand Down Expand Up @@ -150,11 +151,11 @@ pub fn spawn_enemy_overtime(
mut commands: Commands,
enemy_spawn_timer: Res<EnemySpawnTimer>,
window_query: Query<&Window, With<PrimaryWindow>>,
asset_server: Res<AssetServer>,
asset_handler: Res<AssetHandler>,
) {
if enemy_spawn_timer.timer.just_finished() {
if let Ok(window) = window_query.get_single() {
commands.spawn(EnemyBundle::at_randomized_location(window, &asset_server));
commands.spawn(EnemyBundle::at_randomized_location(window, &asset_handler));
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/game/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use bevy::app::App;
use bevy::input::ButtonInput;
use bevy::log::info;
use bevy::prelude::{
Component, EventReader, in_state, IntoSystemConfigs, KeyCode, NextState, OnEnter, OnExit,
Plugin, Res, ResMut, State, States, Update,
ButtonInput, Component, EventReader, in_state, info, IntoSystemConfigs, KeyCode, NextState,
OnEnter, OnExit, Plugin, Res, ResMut, State, States, Update,
};

use crate::ApplicationState;
Expand Down Expand Up @@ -38,13 +36,14 @@ impl Plugin for GamePlugin {
Update,
toggle_pause.run_if(in_state(ApplicationState::InGame)),
)
.add_systems(Update, on_collided_with_enemy_set_pause);
.add_systems(Update, on_collided_with_enemy_set_game_over);
}
}

#[derive(States, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub enum GameState {
#[default]
Stop,
Running,
Paused,
}
Expand All @@ -62,6 +61,7 @@ pub fn toggle_pause(
GameState::Paused => {
resume_game(next_state);
}
_ => {}
}
}
}
Expand All @@ -76,12 +76,12 @@ pub fn resume_game(mut next_state: ResMut<NextState<GameState>>) {
info!("{:?}", GameState::Running);
}

pub fn on_collided_with_enemy_set_pause(
pub fn on_collided_with_enemy_set_game_over(
mut event_reader: EventReader<CollidedWithEnemy>,
mut next_state: ResMut<NextState<GameState>>,
mut game_state: ResMut<NextState<GameState>>,
) {
for _event in event_reader.read() {
next_state.set(GameState::Paused);
game_state.set(GameState::Stop);
}
}

Expand Down
26 changes: 17 additions & 9 deletions src/game/player.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use bevy::prelude::{
App, AssetServer, Bundle, ButtonInput, Commands, Component, default, Entity, Event, EventReader,
EventWriter, in_state, IntoSystemConfigs, KeyCode, Name, OnEnter, OnExit, Plugin, Query,
Res, ResMut, SpriteBundle, Time, Transform, Update, Window, With, Without,
EventWriter, in_state, info, IntoSystemConfigs, KeyCode, Name, OnEnter, OnExit, Plugin,
Query, Res, ResMut, SpriteBundle, Time, Transform, Update, Window, With, Without,
};
use bevy::window::PrimaryWindow;

use crate::{ApplicationState, ScheduleDespawn};
use crate::asset_handler::AssetHandler;
use crate::game::{Confined, GameState, Size};
use crate::game::enemy::{Enemy, ENEMY_SIZE};
use crate::game::score::Score;
use crate::game::star::{Star, STAR_SIZE};
use crate::helpers::{AudioHelper, MovementHelper, SpriteHelper, WindowHelper};
use crate::helpers::{AudioHelper, MovementHelper, WindowHelper};

pub struct PlayerPlugin;

Expand All @@ -37,8 +38,11 @@ impl Plugin for PlayerPlugin {
.add_systems(
Update,
(
on_hit_enemy_emit_collide_event,
on_enemy_collide_despawn_player,
(
on_hit_enemy_emit_collide_event,
on_enemy_collide_despawn_player,
)
.chain(),
on_enemy_collide_play_game_over_sound,
on_star_collide_play_star_despawn_sound,
on_star_collide_event_add_score,
Expand Down Expand Up @@ -77,7 +81,7 @@ pub struct PlayerBundle {
impl PlayerBundle {
pub fn at_center_of_the_screen(
window: &Window,
asset_server: &Res<AssetServer>,
asset_handler: &Res<AssetHandler>,
) -> (Name, Player, Confined, Size, SpriteBundle) {
(
Name::new("Player"),
Expand All @@ -86,7 +90,7 @@ impl PlayerBundle {
Size { value: PLAYER_SIZE },
SpriteBundle {
transform: WindowHelper::center(window),
texture: asset_server.load(SpriteHelper::player_sprite()),
texture: asset_handler.player_texture.clone(),
..default()
},
)
Expand All @@ -96,10 +100,13 @@ impl PlayerBundle {
pub fn spawn_player(
mut commands: Commands,
window_query: Query<&Window, With<PrimaryWindow>>,
asset_server: Res<AssetServer>,
asset_handler: Res<AssetHandler>,
) {
if let Ok(window) = window_query.get_single() {
commands.spawn(PlayerBundle::at_center_of_the_screen(window, &asset_server));
commands.spawn(PlayerBundle::at_center_of_the_screen(
window,
&asset_handler,
));
}
}

Expand Down Expand Up @@ -130,6 +137,7 @@ pub fn on_hit_enemy_emit_collide_event(
);

if is_collided {
info!("Event Writer: CollidedWithEnemy");
if let Some(score) = &score {
event_writer.send(CollidedWithEnemy { score: score.value });
} else {
Expand Down
12 changes: 0 additions & 12 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,3 @@ impl AudioHelper {
"audio/explosionCrunch_000.ogg".to_string()
}
}

pub struct SpriteHelper {}

impl SpriteHelper {
pub fn enemy_sprite() -> String {
"sprites/ball_red_large.png".to_string()
}

pub fn player_sprite() -> String {
"sprites/ball_blue_large.png".to_string()
}
}
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ use bevy::window::PrimaryWindow;

use game::player::CollidedWithEnemy;

use crate::asset_handler::AssetHandlerPlugin;
use crate::helpers::WindowHelper;

mod asset_handler;
pub mod game;
pub mod helpers;
pub mod ui;
Expand All @@ -18,7 +20,8 @@ pub struct ApplicationPlugin;

impl Plugin for ApplicationPlugin {
fn build(&self, app: &mut App) {
app.init_state::<ApplicationState>()
app.add_plugins(AssetHandlerPlugin)
.init_state::<ApplicationState>()
.add_systems(Startup, spawn_camera)
.add_systems(Update, exit_on_escape)
.add_systems(Update, transition_in_game_state)
Expand Down
Loading

0 comments on commit e6a66ee

Please sign in to comment.