State+Scene Transititions

This commit is contained in:
2025-07-05 16:04:43 -04:00
parent a62002ee8b
commit bc0ef5fbfa
14 changed files with 145 additions and 66 deletions

View File

@@ -2,15 +2,14 @@
macro_rules! configure_sets { macro_rules! configure_sets {
( (
$app: expr, $app: expr,
$system_set: expr,
$condition: expr $condition: expr
) => { ) => {
$app.configure_sets(PreUpdate, $system_set.run_if($condition)) $app.configure_sets(PreUpdate, $condition)
.configure_sets(Update, $system_set.run_if($condition)) .configure_sets(Update, $condition)
.configure_sets(PostUpdate, $system_set.run_if($condition)) .configure_sets(PostUpdate, $condition)
.configure_sets(Last, $system_set.run_if($condition)); .configure_sets(Last, $condition);
$app.configure_sets(FixedPreUpdate, $system_set.run_if($condition)) $app.configure_sets(FixedPreUpdate, $condition)
.configure_sets(FixedUpdate, $system_set.run_if($condition)) .configure_sets(FixedUpdate, $condition)
.configure_sets(FixedPostUpdate, $system_set.run_if($condition)); .configure_sets(FixedPostUpdate, $condition);
}; };
} }

View File

@@ -2,16 +2,16 @@ use bevy::prelude::*;
#[cfg(feature = "dev")] #[cfg(feature = "dev")]
use bevy::window::PrimaryWindow; use bevy::window::PrimaryWindow;
use crate::components::camera::*; use crate::{components::camera::*, states::play::PlaySystems};
pub struct CameraPlugin; pub struct CameraPlugin;
impl Plugin for CameraPlugin { impl Plugin for CameraPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, camera_pitch); app.add_systems(Update, camera_pitch.in_set(PlaySystems));
app.add_systems(Update, camera_attachment); app.add_systems(Update, camera_attachment.in_set(PlaySystems));
#[cfg(feature = "dev")] #[cfg(feature = "dev")]
app.add_systems(Update, camera_toggle); app.add_systems(Update, camera_toggle.in_set(PlaySystems));
} }
} }

View File

@@ -1,12 +1,15 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::components::camera::{FollowCam, FollowTarget}; use crate::{
components::camera::{FollowCam, FollowTarget},
states::play::PlaySystems,
};
pub struct FollowCamPlugin; pub struct FollowCamPlugin;
impl Plugin for FollowCamPlugin { impl Plugin for FollowCamPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, (set_cam_target, follow_cam).chain()); app.add_systems(Update, (set_cam_target, follow_cam).chain().in_set(PlaySystems));
} }
} }

View File

@@ -8,8 +8,8 @@ use crate::{
states::{ states::{
game::*, game::*,
input::{InputState, PlayerState}, input::{InputState, PlayerState},
loading::{AssetLoadingState, StartupLoadingState},
menu::MenuState, menu::MenuState,
play::PlayStartupSystems,
}, },
}; };
use bevy::{ use bevy::{
@@ -24,22 +24,11 @@ pub struct GamePlugin;
impl Plugin for GamePlugin { impl Plugin for GamePlugin {
fn build(&self, app: &mut bevy::app::App) { fn build(&self, app: &mut bevy::app::App) {
app.init_state::<AssetLoadingState>();
app.init_state::<StartupLoadingState>();
app.insert_state(GameState::Startup);
app.init_state::<MenuState>();
app.init_state::<PlayerState>();
app.add_loading_state(
LoadingState::new(AssetLoadingState::Loading).continue_to_state(AssetLoadingState::Finalizing),
)
.add_loading_state(
LoadingState::new(StartupLoadingState::Loading).continue_to_state(StartupLoadingState::Finalizing),
);
app.add_plugins(( app.add_plugins((
FollowCamPlugin, FollowCamPlugin,
CameraPlugin, CameraPlugin,
StateManagementPlugin, StateManagementPlugin,
MainMenuPlugin,
// ShipPlugin, // ShipPlugin,
TypesPlugin, TypesPlugin,
PlayerPlugin, PlayerPlugin,
@@ -49,7 +38,7 @@ impl Plugin for GamePlugin {
#[cfg(feature = "dev-phys")] #[cfg(feature = "dev-phys")]
RapierDebugRenderPlugin::default(), RapierDebugRenderPlugin::default(),
)); ));
app.add_systems(Startup, (setup_scene, spawn_ship).chain()); app.add_systems(Update, (setup_scene, spawn_ship).chain().in_set(PlayStartupSystems));
} }
} }

38
src/plugins/main_menu.rs Normal file
View File

@@ -0,0 +1,38 @@
use bevy::prelude::*;
use crate::states::{
game::GameState,
menu::{MainMenuSystems, MenuCleanupSystems, MenuStartupSystems, MenuState},
play::PlayState,
};
pub struct MainMenuPlugin;
impl Plugin for MainMenuPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, spawn_menu.in_set(MenuStartupSystems));
app.add_systems(Update, clean_menu.in_set(MenuCleanupSystems));
app.add_systems(Update, main_menu.in_set(MainMenuSystems));
}
}
fn spawn_menu(mut next: ResMut<NextState<MenuState>>) {
next.set(MenuState::Main);
info_once!("Moving to MenuState:{:?}", MenuState::Main);
}
fn clean_menu(mut next: ResMut<NextState<MenuState>>) {
next.set(MenuState::Idle);
info_once!("Moving to MenuState:{:?}", MenuState::Loading);
}
fn main_menu(
mut next_menu: ResMut<NextState<MenuState>>,
mut next_game: ResMut<NextState<GameState>>,
mut next_play_state: ResMut<NextState<PlayState>>,
) {
next_menu.set(MenuState::Cleanup);
next_game.set(GameState::InGame);
next_play_state.set(PlayState::Loading);
info_once!("Moving to InGame");
}

View File

@@ -2,6 +2,7 @@
mod camera; mod camera;
mod follow_cam; mod follow_cam;
mod game; mod game;
mod main_menu;
mod player; mod player;
mod ship; mod ship;
mod ship_cam; mod ship_cam;
@@ -12,6 +13,7 @@ mod types;
pub use camera::*; pub use camera::*;
pub use follow_cam::*; pub use follow_cam::*;
pub use game::*; pub use game::*;
pub use main_menu::*;
pub use player::*; pub use player::*;
pub use ship::*; pub use ship::*;
pub use ship_cam::*; pub use ship_cam::*;

View File

@@ -9,7 +9,7 @@ use crate::{
player::{GravityDirection, JumpSpeed, MoveSpeed, PlayerDrag, PlayerForce, PlayerMotion, PlayerVelocity}, player::{GravityDirection, JumpSpeed, MoveSpeed, PlayerDrag, PlayerForce, PlayerMotion, PlayerVelocity},
tags::Player, tags::Player,
}, },
states::input::PlayerInputSystems, states::{input::PlayerInputSystems, play::PlaySystems},
utils::{input::get_mouse_delta, rotation::get_alignment_rotation_preserve_twist}, utils::{input::get_mouse_delta, rotation::get_alignment_rotation_preserve_twist},
}; };
@@ -18,8 +18,13 @@ pub struct PlayerPlugin;
impl Plugin for PlayerPlugin { impl Plugin for PlayerPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(PreUpdate, (keyboard_input, player_look).in_set(PlayerInputSystems)); app.add_systems(PreUpdate, (keyboard_input, player_look).in_set(PlayerInputSystems));
app.add_systems(Update, (apply_gravity, apply_forces, apply_motion, apply_drag).chain()); app.add_systems(
app.add_systems(Update, align_with_gravity); Update,
(apply_gravity, apply_forces, apply_motion, apply_drag)
.chain()
.in_set(PlaySystems),
);
app.add_systems(Update, align_with_gravity.in_set(PlaySystems));
} }
} }

View File

@@ -1,15 +1,15 @@
use bevy::{input::mouse::MouseMotion, prelude::*}; use bevy::{input::mouse::MouseMotion, prelude::*};
use bevy_rapier3d::prelude::*; use bevy_rapier3d::prelude::*;
use crate::{components::tags::Ship, utils::input::get_mouse_delta}; use crate::{components::tags::Ship, states::play::PlaySystems, utils::input::get_mouse_delta};
pub struct ShipPlugin; pub struct ShipPlugin;
impl Plugin for ShipPlugin { impl Plugin for ShipPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, ship_controls); app.add_systems(Update, ship_controls.in_set(PlaySystems));
#[cfg(feature = "dev-viz")] #[cfg(feature = "dev-viz")]
app.add_systems(Update, ship_debug); app.add_systems(Update, ship_debug.in_set(PlaySystems));
} }
} }

View File

@@ -1,8 +1,10 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_asset_loader::prelude::*;
use crate::{ use crate::{
configure_sets, configure_sets,
states::{ states::{
game::{GameState, InGameSystems, MenuSystems},
input::{InputState, PlayerInputSystems, PlayerState}, input::{InputState, PlayerInputSystems, PlayerState},
menu::{ menu::{
MainMenuSystems, MenuCleanupSystems, MenuStartupSystems, MenuState, OptionsMenuSystems, SavesMenuSystems, MainMenuSystems, MenuCleanupSystems, MenuStartupSystems, MenuState, OptionsMenuSystems, SavesMenuSystems,
@@ -17,25 +19,76 @@ impl Plugin for StateManagementPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_state::<PlayerState>(); app.init_state::<PlayerState>();
app.init_state::<InputState>(); app.init_state::<InputState>();
app.init_state::<GameState>();
app.init_state::<MenuState>();
app.init_state::<PlayState>();
//Loading
app.add_loading_state(LoadingState::new(MenuState::Loading).continue_to_state(MenuState::Startup))
.add_loading_state(LoadingState::new(PlayState::Loading).continue_to_state(PlayState::Startup));
//Game
configure_sets!(app, MenuSystems.run_if(in_state(GameState::MainMenu)));
configure_sets!(app, InGameSystems.run_if(in_state(GameState::InGame)));
//Menu //Menu
configure_sets!(app, MenuStartupSystems, in_state(MenuState::Startup)); configure_sets!(
configure_sets!(app, MainMenuSystems, in_state(MenuState::Main)); app,
configure_sets!(app, OptionsMenuSystems, in_state(MenuState::Options)); MenuStartupSystems
configure_sets!(app, SavesMenuSystems, in_state(MenuState::Saves)); .run_if(in_state(MenuState::Startup))
configure_sets!(app, MenuCleanupSystems, in_state(MenuState::Cleanup)); .in_set(MenuSystems)
);
configure_sets!(
app,
MainMenuSystems.run_if(in_state(MenuState::Main)).in_set(MenuSystems)
);
configure_sets!(
app,
OptionsMenuSystems
.run_if(in_state(MenuState::Options))
.in_set(MenuSystems)
);
configure_sets!(
app,
SavesMenuSystems.run_if(in_state(MenuState::Saves)).in_set(MenuSystems)
);
configure_sets!(app, MenuCleanupSystems.run_if(in_state(MenuState::Cleanup)));
//Play //Play
configure_sets!(app, PlayStartupSystems, in_state(PlayState::Startup)); configure_sets!(
configure_sets!(app, PausedSystems, in_state(PlayState::Paused)); app,
configure_sets!(app, PlaySystems, in_state(PlayState::Playing)); PlayStartupSystems
configure_sets!(app, PlayCleanupSystems, in_state(PlayState::Cleanup)); .run_if(in_state(PlayState::Startup))
.in_set(InGameSystems)
);
configure_sets!(
app,
PausedSystems.run_if(in_state(PlayState::Paused)).in_set(InGameSystems)
);
configure_sets!(
app,
PlaySystems.run_if(in_state(PlayState::Playing)).in_set(InGameSystems)
);
configure_sets!(app, PlayCleanupSystems.run_if(in_state(PlayState::Cleanup)));
//Input //Input
configure_sets!( configure_sets!(
app, app,
PlayerInputSystems, PlayerInputSystems
in_state(InputState::World).and(in_state(PlayState::Playing)) .run_if(in_state(InputState::World))
.in_set(PlaySystems)
); );
//State Transitions
app.add_systems(Update, game_startup.in_set(PlayStartupSystems));
app.add_systems(Update, game_cleanup.in_set(PlayCleanupSystems));
} }
} }
fn game_startup(mut next: ResMut<NextState<PlayState>>) {
next.set(PlayState::Playing);
}
fn game_cleanup(mut next: ResMut<NextState<PlayState>>) {
next.set(PlayState::Idle);
}

View File

@@ -3,7 +3,12 @@ use bevy::prelude::*;
#[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)] #[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GameState { pub enum GameState {
#[default] #[default]
Startup,
MainMenu, MainMenu,
PlayGame, InGame,
} }
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
pub struct MenuSystems;
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
pub struct InGameSystems;

View File

@@ -1,18 +0,0 @@
use bevy::prelude::*;
#[derive(States, Debug, Default, Clone, PartialEq, Eq, Hash)]
pub enum StartupLoadingState {
#[default]
Pending,
Loading,
Finalizing,
Done,
}
#[derive(States, Debug, Default, Clone, PartialEq, Eq, Hash)]
pub enum AssetLoadingState {
#[default]
Pending,
Loading,
Finalizing,
Done,
}

View File

@@ -3,7 +3,9 @@ use bevy::prelude::*;
#[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)] #[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MenuState { pub enum MenuState {
#[default] #[default]
Idle,
Loading, Loading,
AssetFinalize,
Startup, Startup,
Main, Main,
Saves, Saves,

View File

@@ -1,5 +1,4 @@
pub mod game; pub mod game;
pub mod input; pub mod input;
pub mod loading;
pub mod menu; pub mod menu;
pub mod play; pub mod play;

View File

@@ -2,8 +2,10 @@ use bevy::prelude::*;
#[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)] #[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PlayState { pub enum PlayState {
Idle,
#[default] #[default]
Loading, Loading,
AssetFinalize,
Startup, Startup,
Playing, Playing,
Paused, Paused,