Skip to content

Commit

Permalink
main and pause menu
Browse files Browse the repository at this point in the history
  • Loading branch information
tsukinoko-kun committed Jul 8, 2024
1 parent 5d26509 commit 4c2a777
Show file tree
Hide file tree
Showing 15 changed files with 515 additions and 58 deletions.
4 changes: 2 additions & 2 deletions src/cam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
*/

use bevy::prelude::*;
use bevy::render::camera::ScalingMode;
use bevy::render::camera::*;

fn add_camera(mut commands: Commands) {
let mut my_2d_camera_bundle = Camera2dBundle::default();
my_2d_camera_bundle.projection.scaling_mode = ScalingMode::FixedVertical(1024.0);
my_2d_camera_bundle.transform = Transform::from_xyz(0.0, 0.0, 0.0);

commands.spawn(my_2d_camera_bundle);
commands.spawn((my_2d_camera_bundle, IsDefaultUiCamera));
}

pub struct CamPlugin;
Expand Down
6 changes: 4 additions & 2 deletions src/anim.rs → src/gameplay/anim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

use bevy::prelude::*;

use crate::state::AppState;

#[derive(Component, Debug)]
pub struct AnimationIndices {
pub first: usize,
Expand All @@ -37,7 +39,7 @@ fn animate_sprite(
time: Res<Time>,
mut query: Query<(&AnimationIndices, &mut AnimationTimer, &mut TextureAtlas)>,
) {
for (indices, mut timer, mut atlas) in &mut query {
for (indices, mut timer, mut atlas) in query.iter_mut() {
timer.tick(time.delta());
if timer.just_finished() {
atlas.index = if atlas.index >= indices.first && atlas.index < indices.last {
Expand All @@ -61,6 +63,6 @@ pub struct AnimPlugin;

impl Plugin for AnimPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, animate_sprite);
app.add_systems(Update, animate_sprite.run_if(in_state(AppState::InGame)));
}
}
26 changes: 18 additions & 8 deletions src/cat.rs → src/gameplay/cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@

use bevy::prelude::*;

use crate::anim::{AnimatedSpriteBundle, AnimationIndices, AnimationTimer};
use crate::movement::*;
use crate::player::Player;
use crate::gameplay::anim::*;
use crate::gameplay::movement::*;
use crate::gameplay::player::*;
use crate::state::{AppState, ON_ENTER_GAMEPLAY, ON_EXIT_GAMEPLAY};

const CAT_SPEED: f32 = 75.0;
const CAT_THRESHOLD: f32 = 100.0;
Expand Down Expand Up @@ -71,7 +72,7 @@ fn update_position(
Err(_) => return,
};

for (cat_transform, mut cat_velocity) in &mut cat_q {
for (cat_transform, mut cat_velocity) in cat_q.iter_mut() {
// calc direction from cat to player
let direction = player_transform.translation - cat_transform.translation;
if direction.length() > CAT_THRESHOLD {
Expand All @@ -83,7 +84,7 @@ fn update_position(
}

fn update_animation(mut cats: Query<(&Velocity, &mut AnimationIndices), With<Cat>>) {
for (velocity, mut indices) in &mut cats {
for (velocity, mut indices) in cats.iter_mut() {
if velocity.direction.x < 0.0 {
indices.first = 0;
indices.last = 1;
Expand All @@ -96,10 +97,19 @@ fn update_animation(mut cats: Query<(&Velocity, &mut AnimationIndices), With<Cat
}
}

fn despawn_cat(mut commands: Commands, cat_q: Query<Entity, With<Cat>>) {
for cat_entity in cat_q.iter() {
commands.entity(cat_entity).despawn_recursive();
}
}

impl Plugin for CatPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, spawn_cat)
.add_systems(Update, update_position)
.add_systems(Update, update_animation);
app.add_systems(ON_ENTER_GAMEPLAY, spawn_cat)
.add_systems(
Update,
(update_position, update_animation).run_if(in_state(AppState::InGame)),
)
.add_systems(ON_EXIT_GAMEPLAY, despawn_cat);
}
}
44 changes: 29 additions & 15 deletions src/enemy.rs → src/gameplay/enemy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ use bevy_prng::WyRand;
use bevy_rand::prelude::GlobalEntropy;
use rand_core::RngCore;

use crate::anim::{AnimationIndices, AnimationTimer};
use crate::health::Health;
use crate::movement::*;
use crate::player::Player;
use crate::projectile::Projectile;
use crate::gameplay::anim::*;
use crate::gameplay::health::*;
use crate::gameplay::movement::*;
use crate::gameplay::player::*;
use crate::gameplay::projectile::*;
use crate::state::{AppState, ON_EXIT_GAMEPLAY};

const ENEMY_SPEED: f32 = 40.0;
const ENEMY_THRESHOLD: f32 = ENEMY_SPEED * 2.0;
Expand Down Expand Up @@ -149,18 +150,18 @@ fn projectile_hit_enemy(
projectile_q: Query<(Entity, &Transform), With<Projectile>>,
asset_server: Res<AssetServer>,
) {
for (projectile_entity, projectile_transform) in &mut projectile_q.iter() {
for (enemy_entity, enemy_transform, mut enemy_health) in &mut enemy_q.iter_mut() {
for (projectile_entity, projectile_transform) in projectile_q.iter() {
for (enemy_entity, enemy_transform, mut enemy_health) in enemy_q.iter_mut() {
if projectile_transform
.translation
.distance(enemy_transform.translation)
< 64.0
{
if enemy_health.damage(1) {
commands.entity(enemy_entity).despawn();
commands.entity(enemy_entity).despawn_recursive();
}
enemy_hit_fx(&mut commands, &asset_server);
commands.entity(projectile_entity).despawn();
commands.entity(projectile_entity).despawn_recursive();
}
}
}
Expand Down Expand Up @@ -191,7 +192,7 @@ fn update_position(
player_transform_q: Query<&Transform, With<Player>>,
) {
if let Ok(player_transform) = player_transform_q.get_single() {
for (enemy_transform, mut enemy_vel) in &mut enemy_q.iter_mut() {
for (enemy_transform, mut enemy_vel) in enemy_q.iter_mut() {
let direction = player_transform.translation - enemy_transform.translation;
if direction.length() >= ENEMY_THRESHOLD {
enemy_vel.direction = direction.normalize();
Expand Down Expand Up @@ -227,12 +228,25 @@ fn update_animation(mut enemy_q: Query<(&mut Enemy, &Velocity, &mut AnimationInd
}
}

fn despawn_enemy(mut commands: Commands, enemy_q: Query<Entity, With<Enemy>>) {
for enemy_entity in enemy_q.iter() {
commands.entity(enemy_entity).despawn_recursive();
}
}

impl Plugin for EnemyPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, spawn_enemy)
.add_systems(Update, update_position)
.add_systems(Update, enemy_attack)
.add_systems(Update, update_animation)
.add_systems(Update, projectile_hit_enemy);
app.add_systems(
Update,
(
spawn_enemy,
update_position,
enemy_attack,
update_animation,
projectile_hit_enemy,
)
.run_if(in_state(AppState::InGame)),
)
.add_systems(ON_EXIT_GAMEPLAY, despawn_enemy);
}
}
File renamed without changes.
45 changes: 45 additions & 0 deletions src/gameplay/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Mageanoid - A computer game
* Copyright (C) 2024 Frank Mayer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use bevy::prelude::*;

mod anim;
mod cat;
mod enemy;
mod health;
mod movement;
mod overlap;
mod pause_menu;
mod player;
mod projectile;

pub struct GameplayPlugin;

impl Plugin for GameplayPlugin {
fn build(&self, app: &mut App) {
app.add_plugins(anim::AnimPlugin)
.add_plugins(cat::CatPlugin)
.add_plugins(enemy::EnemyPlugin)
.add_plugins(health::HealthPlugin)
.add_plugins(pause_menu::HudPlugin)
.add_plugins(movement::MovementPlugin)
.add_plugins(overlap::OverlapPlugin)
.add_plugins(player::PlayerPlugin)
.add_plugins(projectile::ProjectilePlugin);
}
}
4 changes: 3 additions & 1 deletion src/movement.rs → src/gameplay/movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
use bevy::math::f32;
use bevy::prelude::*;

use crate::state::AppState;

#[derive(Component, Debug)]
pub struct Velocity {
pub direction: Vec3,
Expand Down Expand Up @@ -59,6 +61,6 @@ pub struct MovementPlugin;

impl Plugin for MovementPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, update_position);
app.add_systems(Update, update_position.run_if(in_state(AppState::InGame)));
}
}
6 changes: 4 additions & 2 deletions src/overlap.rs → src/gameplay/overlap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

use bevy::prelude::*;

use crate::state::AppState;

fn overlap(mut transform_q: Query<&mut Transform>) {
for mut transform in &mut transform_q.iter_mut() {
for mut transform in transform_q.iter_mut() {
transform.translation.z = -transform.translation.y;
}
}
Expand All @@ -28,6 +30,6 @@ pub struct OverlapPlugin;

impl Plugin for OverlapPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, overlap);
app.add_systems(Update, overlap.run_if(in_state(AppState::InGame)));
}
}
121 changes: 121 additions & 0 deletions src/gameplay/pause_menu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Mageanoid - A computer game
* Copyright (C) 2024 Frank Mayer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use bevy::prelude::*;

use crate::state::AppState;
use crate::style::{ButtonId, text_button, text_title, v_space};

#[derive(Component, Debug)]
struct PauseMenu;

fn spawn_pause_menu(mut commands: Commands) {
let container = NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
display: Display::Flex,
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
..default()
};

let (resume_btn, resume_btn_text) = text_button("Resume", 0);
let (main_menu_btn, main_menu_btn_text) = text_button("Main Menu", 1);

commands
.spawn((PauseMenu, container))
.with_children(|parent| {
parent.spawn(text_title("Mageanoid"));
parent.spawn(v_space(20.0));
parent.spawn(resume_btn).with_children(|parent| {
parent.spawn(resume_btn_text);
});
parent.spawn(main_menu_btn).with_children(|parent| {
parent.spawn(main_menu_btn_text);
});
});
}

fn on_button_click(
mut next_state: ResMut<NextState<AppState>>,
button_q: Query<(&Interaction, &ButtonId), (Changed<Interaction>, With<Button>)>,
) {
for (interaction, button_id) in button_q.iter() {
match *interaction {
Interaction::Pressed => match button_id.id {
0 => next_state.set(AppState::InGame),
1 => next_state.set(AppState::MainMenu),
_ => {}
},
_ => {}
}
}
}

fn despawn_pause_menu(mut commands: Commands, query: Query<Entity, With<PauseMenu>>) {
for entity in query.iter() {
commands.entity(entity).despawn_recursive();
}
}

fn button_press_pause(
state: Res<State<AppState>>,
mut next_state: ResMut<NextState<AppState>>,
keys: Res<ButtonInput<KeyCode>>,
gamepads: Res<Gamepads>,
buttons: Res<ButtonInput<GamepadButton>>,
) {
if keys.just_pressed(KeyCode::Escape) {
next_state.set(match state.get() {
AppState::Paused => AppState::InGame,
_ => AppState::Paused,
});
return;
}

for gamepad in gamepads.iter() {
let pause_button = GamepadButton {
gamepad,
button_type: GamepadButtonType::Start,
};

if buttons.just_pressed(pause_button) {
next_state.set(AppState::Paused);
return;
}
}
}

pub struct HudPlugin;

impl Plugin for HudPlugin {
fn build(&self, app: &mut App) {
app.add_systems(OnEnter(AppState::Paused), spawn_pause_menu)
.add_systems(Update, on_button_click.run_if(in_state(AppState::Paused)))
.add_systems(
Update,
button_press_pause
.run_if(in_state(AppState::InGame).or_else(in_state(AppState::Paused))),
)
.add_systems(OnExit(AppState::Paused), despawn_pause_menu);
}
}
Loading

0 comments on commit 4c2a777

Please sign in to comment.