Menus, hurray!
This commit is contained in:
parent
9d5b554f7e
commit
8c26fa7eb8
|
@ -23,16 +23,7 @@ pub struct Fonts {
|
||||||
pub iosevkalytemin: Handle<Font>,
|
pub iosevkalytemin: Handle<Font>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AssetPlugin;
|
pub fn startup(
|
||||||
|
|
||||||
impl Plugin for AssetPlugin {
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.init_resource::<AssetLoader>()
|
|
||||||
.add_systems(Startup, load_assets);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_assets(
|
|
||||||
mut assets: ResMut<AssetLoader>,
|
mut assets: ResMut<AssetLoader>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut texture_atlases: ResMut<Assets<TextureAtlasLayout>>,
|
mut texture_atlases: ResMut<Assets<TextureAtlasLayout>>,
|
||||||
|
|
|
@ -1,29 +1,24 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::camera::Camera as BevyCamera;
|
use bevy::render::camera::Camera;
|
||||||
|
|
||||||
pub struct CameraPlugin;
|
pub fn startup(mut commands: Commands) {
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
|
||||||
pub struct CameraTarget;
|
|
||||||
|
|
||||||
impl Plugin for CameraPlugin {
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.add_systems(Startup, spawn)
|
|
||||||
.add_systems(PostUpdate, follow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn(mut commands: Commands) {
|
|
||||||
let mut bundle = (Camera2dBundle::default(), IsDefaultUiCamera);
|
let mut bundle = (Camera2dBundle::default(), IsDefaultUiCamera);
|
||||||
bundle.0.projection.scale = 0.5;
|
bundle.0.projection.scale = 0.5;
|
||||||
commands.spawn(bundle);
|
commands.spawn(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn follow(
|
#[derive(Component, Debug)]
|
||||||
player: Query<&Transform, With<CameraTarget>>,
|
pub struct Watched;
|
||||||
mut camera: Query<&mut Transform, (With<BevyCamera>, Without<CameraTarget>)>,
|
|
||||||
|
pub fn update(
|
||||||
|
watched: Query<&Transform, With<Watched>>,
|
||||||
|
mut camera: Query<&mut Transform, (With<Camera>, Without<Watched>)>,
|
||||||
) {
|
) {
|
||||||
if let Ok(player) = player.get_single() {
|
if let Ok(mut camera) = camera.get_single_mut() {
|
||||||
camera.single_mut().translation = player.translation
|
if let Ok(watched) = watched.get_single() {
|
||||||
|
camera.translation.x = watched.translation.x
|
||||||
|
} else {
|
||||||
|
camera.translation = Vec3::ZERO;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
114
src/main.rs
114
src/main.rs
|
@ -1,5 +1,5 @@
|
||||||
use bevy::audio::{AudioPlugin, SpatialScale};
|
use bevy::audio::{AudioPlugin, SpatialScale};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::{default, *};
|
||||||
|
|
||||||
mod assets;
|
mod assets;
|
||||||
mod camera;
|
mod camera;
|
||||||
|
@ -8,50 +8,82 @@ mod movement;
|
||||||
mod player;
|
mod player;
|
||||||
mod statue;
|
mod statue;
|
||||||
|
|
||||||
|
#[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]
|
||||||
|
// LoadingScreen,
|
||||||
|
#[default]
|
||||||
|
MainMenu,
|
||||||
|
InGame,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct MainMenuSet;
|
||||||
|
|
||||||
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct InGameSet;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
|
||||||
app.add_plugins(
|
app.init_resource::<assets::AssetLoader>();
|
||||||
DefaultPlugins
|
|
||||||
.set(WindowPlugin {
|
app.insert_state(View::default());
|
||||||
primary_window: Some(Window {
|
app.insert_state(Game::default());
|
||||||
title: "Kodo Tag".into(),
|
|
||||||
mode: bevy::window::WindowMode::BorderlessFullscreen,
|
app.add_plugins((DefaultPlugins
|
||||||
// resolution: (640. * 2., 360. * 2.).into(),
|
.set(WindowPlugin {
|
||||||
..default()
|
primary_window: Some(Window {
|
||||||
}),
|
title: "Kodo Tag".into(),
|
||||||
|
mode: bevy::window::WindowMode::BorderlessFullscreen,
|
||||||
|
// resolution: (640. * 2., 360. * 2.).into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
}),
|
||||||
.set(AudioPlugin {
|
..default()
|
||||||
default_spatial_scale: SpatialScale::new_2d(1.),
|
})
|
||||||
global_volume: GlobalVolume::new(1.),
|
.set(AudioPlugin {
|
||||||
..default()
|
default_spatial_scale: SpatialScale::new_2d(1.),
|
||||||
})
|
global_volume: GlobalVolume::new(1.),
|
||||||
.set(ImagePlugin::default_nearest()),
|
..default()
|
||||||
)
|
})
|
||||||
.add_plugins((
|
.set(ImagePlugin::default_nearest()),))
|
||||||
statue::Statue,
|
.add_systems(OnEnter(View::MainMenu), main_menu::startup)
|
||||||
camera::CameraPlugin,
|
.add_systems(OnExit(View::MainMenu), main_menu::exit)
|
||||||
assets::AssetPlugin,
|
.add_systems(OnEnter(View::InGame), (player::startup, statue::startup))
|
||||||
player::Player,
|
.add_systems(OnExit(View::InGame), (player::exit, statue::exit))
|
||||||
main_menu::MainMenu,
|
.add_systems(Startup, (assets::startup, camera::startup))
|
||||||
movement::Movement,
|
.add_systems(
|
||||||
))
|
Update,
|
||||||
.add_systems(Update, exit_on_escape)
|
(
|
||||||
.insert_resource(ClearColor(Color::rgb(0.1, 0., 0.3)))
|
(
|
||||||
.insert_resource(AmbientLight {
|
player::sprite_select,
|
||||||
color: Color::rgb(1., 1., 1.),
|
player::controls,
|
||||||
brightness: 1.,
|
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::controls)
|
||||||
|
.after(movement::resolve_velocity),
|
||||||
|
)
|
||||||
|
.in_set(InGameSet)
|
||||||
|
.run_if(in_state(View::InGame)),
|
||||||
|
(main_menu::update)
|
||||||
|
.in_set(MainMenuSet)
|
||||||
|
.run_if(in_state(View::MainMenu)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.insert_resource(ClearColor(Color::rgb(0.1, 0.1, 0.1)))
|
||||||
|
.insert_resource(AmbientLight {
|
||||||
|
color: Color::rgb(1., 1., 1.),
|
||||||
|
brightness: 1.,
|
||||||
|
});
|
||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit_on_escape(
|
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
|
||||||
mut app_exit_events: ResMut<Events<bevy::app::AppExit>>,
|
|
||||||
) {
|
|
||||||
if keyboard_input.pressed(KeyCode::Escape) {
|
|
||||||
app_exit_events.send(bevy::app::AppExit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,23 +5,20 @@ use crate::assets::AssetLoader;
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct MainMenu;
|
pub struct MainMenu;
|
||||||
|
|
||||||
impl Plugin for MainMenu {
|
pub fn startup(mut commands: Commands, assets: Res<AssetLoader>) {
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.add_systems(PostStartup, setup_main_menu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_main_menu(mut commands: Commands, assets: Res<AssetLoader>) {
|
|
||||||
commands
|
commands
|
||||||
.spawn(NodeBundle {
|
.spawn((
|
||||||
style: Style {
|
MainMenu,
|
||||||
width: Val::Percent(100.0),
|
NodeBundle {
|
||||||
height: Val::Percent(100.0),
|
style: Style {
|
||||||
justify_content: JustifyContent::SpaceBetween,
|
width: Val::Percent(100.0),
|
||||||
|
height: Val::Percent(100.0),
|
||||||
|
justify_content: JustifyContent::SpaceBetween,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
))
|
||||||
})
|
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
// text
|
// text
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
|
@ -59,3 +56,21 @@ fn setup_main_menu(mut commands: Commands, assets: Res<AssetLoader>) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exit(mut commands: Commands, q: Query<Entity, With<MainMenu>>) {
|
||||||
|
for id in q.iter() {
|
||||||
|
commands.entity(id).despawn_recursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(
|
||||||
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
mut next_state: ResMut<NextState<crate::View>>,
|
||||||
|
mut app_exit_events: ResMut<Events<bevy::app::AppExit>>,
|
||||||
|
) {
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Escape) {
|
||||||
|
app_exit_events.send(bevy::app::AppExit);
|
||||||
|
} else if keyboard_input.pressed(KeyCode::Enter) {
|
||||||
|
next_state.set(crate::View::InGame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct SystemSet;
|
||||||
|
|
||||||
#[derive(Component, Deref, DerefMut, Debug, Default)]
|
#[derive(Component, Deref, DerefMut, Debug, Default)]
|
||||||
pub struct Velocity(pub Vec2);
|
pub struct Velocity(pub Vec2);
|
||||||
|
|
||||||
|
@ -9,19 +12,19 @@ pub struct Heading(pub Vec2);
|
||||||
#[derive(Component, Deref, DerefMut, Debug, Default)]
|
#[derive(Component, Deref, DerefMut, Debug, Default)]
|
||||||
pub struct Speed(pub f32);
|
pub struct Speed(pub f32);
|
||||||
|
|
||||||
fn update_position(mut query: Query<(&Velocity, &mut Transform)>, time: Res<Time>) {
|
pub fn resolve_velocity(mut query: Query<(&Velocity, &mut Transform)>, time: Res<Time>) {
|
||||||
for (velocity, mut transform) in query.iter_mut() {
|
for (velocity, mut transform) in query.iter_mut() {
|
||||||
transform.translation += (velocity.0 * time.delta_seconds()).extend(0.);
|
transform.translation += (velocity.0 * time.delta_seconds()).extend(0.);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mover_movement(mut query: Query<(&mut Velocity, &Speed, &Heading)>) {
|
pub fn update_velocity_by_heading(mut query: Query<(&mut Velocity, &Speed, &Heading)>) {
|
||||||
if let Ok((mut velocity, speed, heading)) = query.get_single_mut() {
|
if let Ok((mut velocity, speed, heading)) = query.get_single_mut() {
|
||||||
**velocity = heading.normalize_or_zero() * (**speed);
|
**velocity = heading.normalize_or_zero() * (**speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ysort(mut q: Query<&mut Transform>) {
|
pub fn ysort(mut q: Query<&mut Transform>) {
|
||||||
q.iter_mut()
|
q.iter_mut()
|
||||||
.for_each(|mut tf| tf.translation.z = -tf.translation.y)
|
.for_each(|mut tf| tf.translation.z = -tf.translation.y)
|
||||||
}
|
}
|
||||||
|
@ -32,19 +35,3 @@ pub struct Mover {
|
||||||
pub heading: Heading,
|
pub heading: Heading,
|
||||||
pub speed: Speed,
|
pub speed: Speed,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Movement;
|
|
||||||
|
|
||||||
impl Plugin for Movement {
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
// TODO: these systems probably needs ordering?
|
|
||||||
app.add_systems(
|
|
||||||
Update,
|
|
||||||
(
|
|
||||||
update_position,
|
|
||||||
mover_movement.after(update_position),
|
|
||||||
ysort.after(mover_movement),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use bevy::sprite::MaterialMesh2dBundle;
|
||||||
use bevy::sprite::Mesh2dHandle;
|
use bevy::sprite::Mesh2dHandle;
|
||||||
use bevy::{prelude::*, window::PrimaryWindow};
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
|
|
||||||
use crate::camera::CameraTarget;
|
use crate::camera::Watched;
|
||||||
use crate::{
|
use crate::{
|
||||||
assets::AssetLoader,
|
assets::AssetLoader,
|
||||||
movement::{Heading, Mover, Speed, Velocity},
|
movement::{Heading, Mover, Speed, Velocity},
|
||||||
|
@ -17,14 +17,7 @@ pub struct Player;
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Crosshair;
|
pub struct Crosshair;
|
||||||
|
|
||||||
impl Plugin for Player {
|
pub fn startup(
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.add_systems(PostStartup, spawn_player)
|
|
||||||
.add_systems(Update, (sprite_select, controls.after(sprite_select)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn_player(
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
assets: Res<AssetLoader>,
|
assets: Res<AssetLoader>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
@ -37,7 +30,7 @@ fn spawn_player(
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Player,
|
Player,
|
||||||
CameraTarget,
|
Watched,
|
||||||
SpriteSheetBundle {
|
SpriteSheetBundle {
|
||||||
texture,
|
texture,
|
||||||
atlas: assets.images.player.clone().into(),
|
atlas: assets.images.player.clone().into(),
|
||||||
|
@ -95,7 +88,7 @@ fn spawn_player(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn controls(
|
pub fn controls(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut player_q: Query<(&mut Sprite, &mut TextureAtlas, &mut Heading, Entity), With<Player>>,
|
mut player_q: Query<(&mut Sprite, &mut TextureAtlas, &mut Heading, Entity), With<Player>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
@ -104,6 +97,7 @@ fn controls(
|
||||||
assets: Res<AssetLoader>,
|
assets: Res<AssetLoader>,
|
||||||
win_q: Query<&Window, With<PrimaryWindow>>,
|
win_q: Query<&Window, With<PrimaryWindow>>,
|
||||||
cam_q: Query<(&Camera, &GlobalTransform), With<Camera>>,
|
cam_q: Query<(&Camera, &GlobalTransform), With<Camera>>,
|
||||||
|
mut next_state: ResMut<NextState<crate::View>>,
|
||||||
mut crosshair_q: Query<&mut Transform, With<Crosshair>>,
|
mut crosshair_q: Query<&mut Transform, With<Crosshair>>,
|
||||||
) {
|
) {
|
||||||
let (mut sprite, mut texture, mut heading, player_entity) = player_q.single_mut();
|
let (mut sprite, mut texture, mut heading, player_entity) = player_q.single_mut();
|
||||||
|
@ -153,6 +147,7 @@ fn controls(
|
||||||
}
|
}
|
||||||
for key in input.get_just_pressed() {
|
for key in input.get_just_pressed() {
|
||||||
match key {
|
match key {
|
||||||
|
KeyCode::Escape => next_state.set(crate::View::MainMenu),
|
||||||
KeyCode::Space => {
|
KeyCode::Space => {
|
||||||
let child = commands
|
let child = commands
|
||||||
.spawn(AudioSourceBundle {
|
.spawn(AudioSourceBundle {
|
||||||
|
@ -192,13 +187,15 @@ fn controls(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sprite_select(
|
pub fn sprite_select(
|
||||||
mut q: Query<(&Handle<TextureAtlasLayout>, &mut TextureAtlas), With<Player>>,
|
mut q: Query<(&Handle<TextureAtlasLayout>, &mut TextureAtlas), With<Player>>,
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
texture_atlases: Res<Assets<TextureAtlasLayout>>,
|
texture_atlases: Res<Assets<TextureAtlasLayout>>,
|
||||||
) {
|
) {
|
||||||
if let Ok((texture, mut sprite)) = q.get_single_mut() {
|
if keyboard_input.just_pressed(KeyCode::KeyN) {
|
||||||
if keyboard_input.just_pressed(KeyCode::KeyN) {
|
info!("pressed N");
|
||||||
|
if let Ok((texture, mut sprite)) = q.get_single_mut() {
|
||||||
|
info!("next tex: {}", sprite.index);
|
||||||
let t = texture_atlases
|
let t = texture_atlases
|
||||||
.get(texture)
|
.get(texture)
|
||||||
.expect("could not load player texture");
|
.expect("could not load player texture");
|
||||||
|
@ -210,3 +207,9 @@ fn sprite_select(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exit(mut commands: Commands, q: Query<Entity, With<Player>>) {
|
||||||
|
for id in q.iter() {
|
||||||
|
commands.entity(id).despawn_recursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,10 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
use crate::assets::AssetLoader;
|
use crate::assets::AssetLoader;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Statue;
|
pub struct Statue;
|
||||||
|
|
||||||
impl Plugin for Statue {
|
pub fn startup(mut commands: Commands, assets: Res<AssetLoader>, asset_server: Res<AssetServer>) {
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.add_systems(PostStartup, spawn_statue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn_statue(mut commands: Commands, assets: Res<AssetLoader>, asset_server: Res<AssetServer>) {
|
|
||||||
let texture = asset_server.load("img/Props.png");
|
let texture = asset_server.load("img/Props.png");
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Statue,
|
Statue,
|
||||||
|
@ -38,3 +31,9 @@ fn spawn_statue(mut commands: Commands, assets: Res<AssetLoader>, asset_server:
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exit(mut commands: Commands, q: Query<Entity, With<Statue>>) {
|
||||||
|
for id in q.iter() {
|
||||||
|
commands.entity(id).despawn_recursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue