2023-12-20 13:24:16 -06:00
|
|
|
mod camera;
|
2024-07-31 15:37:11 -05:00
|
|
|
mod game;
|
|
|
|
mod input;
|
2024-02-03 21:15:30 -06:00
|
|
|
mod main_menu;
|
2023-12-20 13:36:34 -06:00
|
|
|
mod movement;
|
|
|
|
mod player;
|
2024-07-31 15:37:11 -05:00
|
|
|
mod prelude;
|
2023-12-23 16:50:08 -06:00
|
|
|
mod statue;
|
2023-12-19 11:17:49 -06:00
|
|
|
|
2024-07-31 15:37:11 -05:00
|
|
|
use bevy::asset::load_internal_binary_asset;
|
|
|
|
use bevy::audio::{AudioPlugin, SpatialScale};
|
|
|
|
use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin};
|
|
|
|
use bevy::window::{PrimaryWindow, WindowMode};
|
|
|
|
use input::Input;
|
|
|
|
use prelude::*;
|
|
|
|
use statue::SpawnStatueEvent;
|
|
|
|
|
2024-07-29 16:29:39 -05:00
|
|
|
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub enum Game {
|
|
|
|
#[default]
|
|
|
|
Running,
|
|
|
|
Paused,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub enum View {
|
|
|
|
#[default]
|
2024-07-30 12:56:30 -05:00
|
|
|
LoadingScreen,
|
2024-07-29 16:29:39 -05:00
|
|
|
MainMenu,
|
|
|
|
InGame,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
struct MainMenuSet;
|
|
|
|
|
|
|
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
struct InGameSet;
|
|
|
|
|
2024-07-30 12:56:30 -05:00
|
|
|
fn main() -> AppExit {
|
2023-12-19 11:17:49 -06:00
|
|
|
let mut app = App::new();
|
2023-12-24 21:30:18 -06:00
|
|
|
|
2024-07-29 16:54:43 -05:00
|
|
|
app.add_plugins((
|
|
|
|
DefaultPlugins
|
|
|
|
.set(WindowPlugin {
|
|
|
|
primary_window: Some(Window {
|
|
|
|
title: "Kodo Tag".into(),
|
2024-07-31 15:37:11 -05:00
|
|
|
// mode: bevy::window::WindowMode::BorderlessFullscreen,
|
|
|
|
mode: bevy::window::WindowMode::Windowed,
|
2024-07-29 16:54:43 -05:00
|
|
|
// resolution: (640. * 2., 360. * 2.).into(),
|
|
|
|
..default()
|
|
|
|
}),
|
2023-12-24 21:30:18 -06:00
|
|
|
..default()
|
2024-07-29 16:54:43 -05:00
|
|
|
})
|
|
|
|
.set(AudioPlugin {
|
|
|
|
default_spatial_scale: SpatialScale::new_2d(1.),
|
|
|
|
global_volume: GlobalVolume::new(1.),
|
|
|
|
..default()
|
|
|
|
})
|
|
|
|
.set(ImagePlugin::default_nearest()),
|
|
|
|
FrameTimeDiagnosticsPlugin,
|
2024-08-01 14:03:02 -05:00
|
|
|
bevy_framepace::FramepacePlugin,
|
2024-07-31 15:37:11 -05:00
|
|
|
));
|
|
|
|
|
|
|
|
load_internal_binary_asset!(
|
|
|
|
app,
|
|
|
|
TextStyle::default().font,
|
|
|
|
"../assets/font/iosevka-lyteterm-regular.subset.ttf",
|
|
|
|
|bytes: &[u8], _path: String| { Font::try_from_bytes(bytes.to_vec()).unwrap() }
|
|
|
|
);
|
|
|
|
|
|
|
|
app.init_resource::<input::Input>()
|
|
|
|
.init_state::<View>()
|
|
|
|
.init_state::<Game>();
|
|
|
|
|
|
|
|
app.configure_sets(
|
2024-07-29 16:54:43 -05:00
|
|
|
Update,
|
|
|
|
(
|
2024-07-31 15:37:11 -05:00
|
|
|
MainMenuSet.run_if(in_state(View::MainMenu)),
|
|
|
|
InGameSet
|
|
|
|
.run_if(in_state(View::InGame))
|
|
|
|
.after(input::process_input),
|
2024-07-29 16:54:43 -05:00
|
|
|
),
|
2024-07-31 15:37:11 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
app.add_event::<SpawnStatueEvent>();
|
|
|
|
|
|
|
|
app.add_systems(OnEnter(View::MainMenu), main_menu::startup)
|
|
|
|
.add_systems(OnExit(View::MainMenu), main_menu::exit)
|
|
|
|
.add_systems(OnEnter(View::InGame), (player::startup, statue::startup))
|
|
|
|
.add_systems(OnExit(View::InGame), (player::exit, statue::exit))
|
|
|
|
.add_systems(OnEnter(View::LoadingScreen), (startup, camera::startup))
|
|
|
|
.add_systems(
|
|
|
|
Update,
|
|
|
|
(
|
|
|
|
finish_setup.run_if(in_state(View::LoadingScreen)),
|
|
|
|
input::process_input,
|
|
|
|
(update,).after(input::process_input),
|
|
|
|
(
|
|
|
|
player::control,
|
2024-07-31 15:55:17 -05:00
|
|
|
player::player_debug_info,
|
2024-07-31 15:37:11 -05:00
|
|
|
statue::spawn_statue,
|
|
|
|
movement::update_velocity_by_heading,
|
|
|
|
movement::resolve_velocity.after(movement::update_velocity_by_heading),
|
|
|
|
movement::ysort.after(movement::update_velocity_by_heading),
|
|
|
|
camera::update
|
|
|
|
.after(player::control)
|
|
|
|
.after(movement::resolve_velocity),
|
|
|
|
)
|
2024-08-01 14:02:38 -05:00
|
|
|
.after(input::process_input)
|
2024-07-31 15:37:11 -05:00
|
|
|
.in_set(InGameSet),
|
|
|
|
(main_menu::update).in_set(MainMenuSet),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.insert_resource(ClearColor(Color::srgb(0.3, 0.1, 0.5)));
|
2024-07-30 11:16:36 -05:00
|
|
|
// NOTE: would need to add PBR feature I think?
|
|
|
|
// Was intending to use this for day/night cycle type stuff a la V Rising?
|
|
|
|
// app.insert_resource(AmbientLight {
|
|
|
|
// color: Color::srgb(1., 1., 1.),
|
|
|
|
// brightness: 1.,
|
|
|
|
// });
|
2023-12-19 11:17:49 -06:00
|
|
|
|
2024-07-30 12:56:30 -05:00
|
|
|
app.run()
|
2023-12-19 11:17:49 -06:00
|
|
|
}
|
2024-07-29 16:36:16 -05:00
|
|
|
|
2024-07-29 16:54:43 -05:00
|
|
|
#[derive(Component)]
|
|
|
|
struct FpsText;
|
|
|
|
|
2024-07-30 12:56:30 -05:00
|
|
|
fn finish_setup(mut app_state: ResMut<NextState<View>>) {
|
|
|
|
app_state.set(View::MainMenu);
|
|
|
|
}
|
|
|
|
|
2024-07-31 16:39:53 -05:00
|
|
|
fn startup(mut commands: Commands) {
|
|
|
|
let font_size = 48.;
|
2024-07-29 16:54:43 -05:00
|
|
|
commands.spawn((
|
|
|
|
FpsText,
|
|
|
|
TextBundle::from_sections([
|
|
|
|
TextSection::new(
|
|
|
|
"FPS: ",
|
|
|
|
TextStyle {
|
2024-07-31 16:39:53 -05:00
|
|
|
font_size,
|
2024-07-29 16:54:43 -05:00
|
|
|
..default()
|
|
|
|
},
|
|
|
|
),
|
|
|
|
TextSection::from_style(TextStyle {
|
2024-07-31 16:39:53 -05:00
|
|
|
font_size,
|
2024-07-30 11:16:36 -05:00
|
|
|
color: Color::hsla(0.5, 0.5, 0.5, 0.5),
|
2024-07-31 15:37:11 -05:00
|
|
|
..default()
|
2024-07-29 16:54:43 -05:00
|
|
|
}),
|
|
|
|
])
|
|
|
|
.with_style(Style {
|
|
|
|
position_type: PositionType::Absolute,
|
|
|
|
bottom: Val::Px(5.0),
|
|
|
|
right: Val::Px(5.0),
|
|
|
|
..default()
|
|
|
|
}),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
fn update(
|
2024-07-31 15:37:11 -05:00
|
|
|
view: Res<State<View>>,
|
|
|
|
input: Res<Input>,
|
|
|
|
mut next_state: ResMut<NextState<crate::View>>,
|
2024-07-29 16:54:43 -05:00
|
|
|
diagnostics: Res<DiagnosticsStore>,
|
|
|
|
mut query: Query<&mut Text, With<FpsText>>,
|
2024-07-29 16:36:16 -05:00
|
|
|
mut window: Query<&mut Window, With<PrimaryWindow>>,
|
2024-07-31 15:37:11 -05:00
|
|
|
keys: Res<ButtonInput<KeyCode>>,
|
|
|
|
mut app_exit_events: ResMut<Events<bevy::app::AppExit>>,
|
2024-07-29 16:36:16 -05:00
|
|
|
) {
|
2024-07-31 15:37:11 -05:00
|
|
|
if input.cancel {
|
|
|
|
match view.get() {
|
|
|
|
View::InGame => {
|
|
|
|
next_state.set(crate::View::MainMenu);
|
|
|
|
}
|
|
|
|
View::MainMenu => {
|
|
|
|
app_exit_events.send(AppExit::Success);
|
|
|
|
}
|
|
|
|
View::LoadingScreen => {}
|
|
|
|
}
|
|
|
|
} else if input.action {
|
|
|
|
match view.get() {
|
|
|
|
View::InGame => {}
|
|
|
|
View::MainMenu => {
|
|
|
|
next_state.set(crate::View::InGame);
|
|
|
|
}
|
|
|
|
View::LoadingScreen => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if keys.just_pressed(KeyCode::Enter)
|
|
|
|
&& (keys.pressed(KeyCode::AltLeft) || keys.pressed(KeyCode::AltRight))
|
2024-07-29 16:36:16 -05:00
|
|
|
{
|
|
|
|
if let Ok(window) = window.get_single_mut() {
|
2024-07-31 15:37:11 -05:00
|
|
|
let mut window = window;
|
|
|
|
if window.mode == WindowMode::Windowed {
|
|
|
|
window.mode = WindowMode::BorderlessFullscreen
|
|
|
|
} else {
|
|
|
|
window.mode = WindowMode::Windowed
|
|
|
|
}
|
2024-07-29 16:36:16 -05:00
|
|
|
}
|
|
|
|
}
|
2024-07-29 16:54:43 -05:00
|
|
|
for mut text in &mut query {
|
|
|
|
if let Some(fps) = diagnostics.get(&FrameTimeDiagnosticsPlugin::FPS) {
|
|
|
|
if let Some(value) = fps.smoothed() {
|
|
|
|
text.sections[1].value = format!("{value:.2}");
|
|
|
|
}
|
|
|
|
}
|
2024-07-29 16:36:16 -05:00
|
|
|
}
|
|
|
|
}
|