Cleanup my asset stupidity...?
This commit is contained in:
parent
7d2e46c263
commit
aaddc46c65
|
@ -1,72 +0,0 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Resource, Debug, Default)]
|
|
||||||
pub struct AssetLoader {
|
|
||||||
pub layouts: Layouts,
|
|
||||||
pub images: Images,
|
|
||||||
pub sounds: Sounds,
|
|
||||||
pub fonts: Fonts,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Resource, Debug, Default)]
|
|
||||||
pub struct Layouts {
|
|
||||||
pub player: Handle<TextureAtlasLayout>,
|
|
||||||
pub statue: Handle<TextureAtlasLayout>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Resource, Debug, Default)]
|
|
||||||
pub struct Images {
|
|
||||||
pub player: Handle<Image>,
|
|
||||||
pub statue: Handle<Image>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Resource, Debug, Default)]
|
|
||||||
pub struct Sounds {
|
|
||||||
pub meow: Handle<AudioSource>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Resource, Debug, Default)]
|
|
||||||
pub struct Fonts {
|
|
||||||
pub iosevkalytemin: Handle<Font>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn startup(
|
|
||||||
mut assets: ResMut<AssetLoader>,
|
|
||||||
asset_server: Res<AssetServer>,
|
|
||||||
mut texture_atlases: ResMut<Assets<TextureAtlasLayout>>,
|
|
||||||
) {
|
|
||||||
let props = asset_server.load("img/Props.png");
|
|
||||||
let player = asset_server.load("img/Player.png");
|
|
||||||
|
|
||||||
let player_atlas = TextureAtlasLayout::from_grid(
|
|
||||||
UVec2::new(32, 64),
|
|
||||||
3,
|
|
||||||
1,
|
|
||||||
Some(UVec2 { x: 0, y: 0 }),
|
|
||||||
Some(UVec2 { x: 0, y: 0 }),
|
|
||||||
);
|
|
||||||
let statue_atlas =
|
|
||||||
TextureAtlasLayout::from_grid(UVec2::new(40, 74), 1, 1, None, Some(UVec2::new(443, 20)));
|
|
||||||
|
|
||||||
let player_atlas_handle = texture_atlases.add(player_atlas);
|
|
||||||
let statue_atlas_handle = texture_atlases.add(statue_atlas);
|
|
||||||
|
|
||||||
*assets = AssetLoader {
|
|
||||||
images: Images {
|
|
||||||
player,
|
|
||||||
statue: props.clone(),
|
|
||||||
},
|
|
||||||
layouts: Layouts {
|
|
||||||
player: player_atlas_handle,
|
|
||||||
statue: statue_atlas_handle,
|
|
||||||
},
|
|
||||||
|
|
||||||
sounds: Sounds {
|
|
||||||
meow: asset_server.load("sfx/meow.wav"),
|
|
||||||
},
|
|
||||||
|
|
||||||
fonts: Fonts {
|
|
||||||
iosevkalytemin: asset_server.load("font/iosevka-lyteterm-regular.subset.ttf"),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -2,8 +2,8 @@ use bevy::prelude::*;
|
||||||
use bevy::render::camera::Camera;
|
use bevy::render::camera::Camera;
|
||||||
|
|
||||||
pub fn startup(mut commands: Commands) {
|
pub fn startup(mut commands: Commands) {
|
||||||
let bundle = (Camera2dBundle::default(), IsDefaultUiCamera);
|
let mut bundle = (Camera2dBundle::default(), IsDefaultUiCamera);
|
||||||
// bundle.0.projection.scale = 1;
|
bundle.0.projection.scale = 1.;
|
||||||
commands.spawn(bundle);
|
commands.spawn(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
src/game.rs
Normal file
4
src/game.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct Gameobject;
|
53
src/input.rs
Normal file
53
src/input.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Resource, Default, Debug, Clone, PartialEq)]
|
||||||
|
pub struct Input {
|
||||||
|
pub movement: Vec2,
|
||||||
|
pub angle: f32,
|
||||||
|
pub action: bool,
|
||||||
|
pub cancel: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_input(
|
||||||
|
mut input: ResMut<Input>,
|
||||||
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
|
// mouse: Res<ButtonInput<MouseButton>>,
|
||||||
|
) {
|
||||||
|
input.movement.x = 0.;
|
||||||
|
input.movement.y = 0.;
|
||||||
|
for key in keys.get_pressed() {
|
||||||
|
match key {
|
||||||
|
KeyCode::KeyA | KeyCode::ArrowLeft => {
|
||||||
|
input.movement -= Vec2::X;
|
||||||
|
}
|
||||||
|
KeyCode::KeyD | KeyCode::ArrowRight => {
|
||||||
|
input.movement += Vec2::X;
|
||||||
|
}
|
||||||
|
KeyCode::KeyW | KeyCode::ArrowUp => {
|
||||||
|
input.movement += Vec2::Y;
|
||||||
|
}
|
||||||
|
KeyCode::KeyS | KeyCode::ArrowDown => {
|
||||||
|
input.movement -= Vec2::Y;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input.movement = input.movement.normalize_or_zero();
|
||||||
|
// input.target // not set using keyboard, see mouse
|
||||||
|
input.action = input.action || keys.any_pressed([KeyCode::Space, KeyCode::Enter]);
|
||||||
|
input.cancel = input.cancel || keys.just_pressed(KeyCode::Escape);
|
||||||
|
|
||||||
|
info!("Input: {:#?}", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: controller input: https://bevy-cheatbook.github.io/input/gamepad.html
|
||||||
|
// Iterate controllers on startup and assign to players/units?
|
||||||
|
// What logic for handling controller connection/disconnection?
|
||||||
|
// Will we have splitscreen?
|
||||||
|
// Once a controller is assigned to a player, we can handle its input
|
||||||
|
// pub fn controller_input(
|
||||||
|
// axes: Res<Axis<GamepadAxis>>,
|
||||||
|
// buttons: Res<ButtonInput<GamepadButton>>,
|
||||||
|
// my_gamepad: Option<Res<MyGamepad>>,
|
||||||
|
// ) {
|
||||||
|
// }
|
121
src/main.rs
121
src/main.rs
|
@ -1,15 +1,20 @@
|
||||||
use bevy::audio::{AudioPlugin, SpatialScale};
|
|
||||||
use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin};
|
|
||||||
use bevy::prelude::{default, *};
|
|
||||||
use bevy::window::{PrimaryWindow, WindowMode};
|
|
||||||
|
|
||||||
mod assets;
|
|
||||||
mod camera;
|
mod camera;
|
||||||
|
mod game;
|
||||||
|
mod input;
|
||||||
mod main_menu;
|
mod main_menu;
|
||||||
mod movement;
|
mod movement;
|
||||||
mod player;
|
mod player;
|
||||||
|
mod prelude;
|
||||||
mod statue;
|
mod statue;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Game {
|
pub enum Game {
|
||||||
#[default]
|
#[default]
|
||||||
|
@ -39,7 +44,8 @@ fn main() -> AppExit {
|
||||||
.set(WindowPlugin {
|
.set(WindowPlugin {
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
title: "Kodo Tag".into(),
|
title: "Kodo Tag".into(),
|
||||||
mode: bevy::window::WindowMode::BorderlessFullscreen,
|
// mode: bevy::window::WindowMode::BorderlessFullscreen,
|
||||||
|
mode: bevy::window::WindowMode::Windowed,
|
||||||
// resolution: (640. * 2., 360. * 2.).into(),
|
// resolution: (640. * 2., 360. * 2.).into(),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
|
@ -52,38 +58,54 @@ fn main() -> AppExit {
|
||||||
})
|
})
|
||||||
.set(ImagePlugin::default_nearest()),
|
.set(ImagePlugin::default_nearest()),
|
||||||
FrameTimeDiagnosticsPlugin,
|
FrameTimeDiagnosticsPlugin,
|
||||||
))
|
));
|
||||||
.init_resource::<assets::AssetLoader>()
|
|
||||||
|
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::<View>()
|
||||||
.init_state::<Game>()
|
.init_state::<Game>();
|
||||||
.add_systems(OnEnter(View::MainMenu), main_menu::startup)
|
|
||||||
|
app.configure_sets(
|
||||||
|
Update,
|
||||||
|
(
|
||||||
|
MainMenuSet.run_if(in_state(View::MainMenu)),
|
||||||
|
InGameSet
|
||||||
|
.run_if(in_state(View::InGame))
|
||||||
|
.after(input::process_input),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
app.add_event::<SpawnStatueEvent>();
|
||||||
|
|
||||||
|
app.add_systems(OnEnter(View::MainMenu), main_menu::startup)
|
||||||
.add_systems(OnExit(View::MainMenu), main_menu::exit)
|
.add_systems(OnExit(View::MainMenu), main_menu::exit)
|
||||||
.add_systems(OnEnter(View::InGame), (player::startup, statue::startup))
|
.add_systems(OnEnter(View::InGame), (player::startup, statue::startup))
|
||||||
.add_systems(OnExit(View::InGame), (player::exit, statue::exit))
|
.add_systems(OnExit(View::InGame), (player::exit, statue::exit))
|
||||||
.add_systems(
|
.add_systems(OnEnter(View::LoadingScreen), (startup, camera::startup))
|
||||||
OnEnter(View::LoadingScreen),
|
|
||||||
(startup, assets::startup, camera::startup),
|
|
||||||
)
|
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
update,
|
|
||||||
finish_setup.run_if(in_state(View::LoadingScreen)),
|
finish_setup.run_if(in_state(View::LoadingScreen)),
|
||||||
|
input::process_input,
|
||||||
|
(update,).after(input::process_input),
|
||||||
(
|
(
|
||||||
player::sprite_select,
|
player::control,
|
||||||
player::controls,
|
statue::spawn_statue,
|
||||||
movement::update_velocity_by_heading,
|
movement::update_velocity_by_heading,
|
||||||
movement::resolve_velocity.after(movement::update_velocity_by_heading),
|
movement::resolve_velocity.after(movement::update_velocity_by_heading),
|
||||||
movement::ysort.after(movement::update_velocity_by_heading),
|
movement::ysort.after(movement::update_velocity_by_heading),
|
||||||
camera::update
|
camera::update
|
||||||
.after(player::controls)
|
.after(player::control)
|
||||||
.after(movement::resolve_velocity),
|
.after(movement::resolve_velocity),
|
||||||
)
|
)
|
||||||
.in_set(InGameSet)
|
.in_set(InGameSet),
|
||||||
.run_if(in_state(View::InGame)),
|
(main_menu::update).in_set(MainMenuSet),
|
||||||
(main_menu::update)
|
|
||||||
.in_set(MainMenuSet)
|
|
||||||
.run_if(in_state(View::MainMenu)),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.insert_resource(ClearColor(Color::srgb(0.3, 0.1, 0.5)));
|
.insert_resource(ClearColor(Color::srgb(0.3, 0.1, 0.5)));
|
||||||
|
@ -97,14 +119,6 @@ fn main() -> AppExit {
|
||||||
app.run()
|
app.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_fullscreen(mut window: Mut<Window>) {
|
|
||||||
if window.mode == WindowMode::Windowed {
|
|
||||||
window.mode = WindowMode::BorderlessFullscreen
|
|
||||||
} else {
|
|
||||||
window.mode = WindowMode::Windowed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct FpsText;
|
struct FpsText;
|
||||||
|
|
||||||
|
@ -112,22 +126,21 @@ fn finish_setup(mut app_state: ResMut<NextState<View>>) {
|
||||||
app_state.set(View::MainMenu);
|
app_state.set(View::MainMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn startup(mut commands: Commands, assets: Res<assets::AssetLoader>) {
|
fn startup(mut commands: Commands, mut ui_scale: ResMut<UiScale>) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
FpsText,
|
FpsText,
|
||||||
TextBundle::from_sections([
|
TextBundle::from_sections([
|
||||||
TextSection::new(
|
TextSection::new(
|
||||||
"FPS: ",
|
"FPS: ",
|
||||||
TextStyle {
|
TextStyle {
|
||||||
font: assets.fonts.iosevkalytemin.clone(),
|
|
||||||
font_size: 60.,
|
font_size: 60.,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TextSection::from_style(TextStyle {
|
TextSection::from_style(TextStyle {
|
||||||
font: assets.fonts.iosevkalytemin.clone(),
|
|
||||||
font_size: 60.,
|
font_size: 60.,
|
||||||
color: Color::hsla(0.5, 0.5, 0.5, 0.5),
|
color: Color::hsla(0.5, 0.5, 0.5, 0.5),
|
||||||
|
..default()
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
.with_style(Style {
|
.with_style(Style {
|
||||||
|
@ -137,19 +150,49 @@ fn startup(mut commands: Commands, assets: Res<assets::AssetLoader>) {
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
ui_scale.0 = 1.;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
|
view: Res<State<View>>,
|
||||||
|
input: Res<Input>,
|
||||||
|
mut next_state: ResMut<NextState<crate::View>>,
|
||||||
diagnostics: Res<DiagnosticsStore>,
|
diagnostics: Res<DiagnosticsStore>,
|
||||||
mut query: Query<&mut Text, With<FpsText>>,
|
mut query: Query<&mut Text, With<FpsText>>,
|
||||||
keyboard: Res<ButtonInput<KeyCode>>,
|
|
||||||
mut window: Query<&mut Window, With<PrimaryWindow>>,
|
mut window: Query<&mut Window, With<PrimaryWindow>>,
|
||||||
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
|
mut app_exit_events: ResMut<Events<bevy::app::AppExit>>,
|
||||||
) {
|
) {
|
||||||
if keyboard.just_pressed(KeyCode::Enter)
|
if input.cancel {
|
||||||
&& (keyboard.pressed(KeyCode::AltLeft) || keyboard.pressed(KeyCode::AltRight))
|
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))
|
||||||
{
|
{
|
||||||
if let Ok(window) = window.get_single_mut() {
|
if let Ok(window) = window.get_single_mut() {
|
||||||
toggle_fullscreen(window)
|
let mut window = window;
|
||||||
|
if window.mode == WindowMode::Windowed {
|
||||||
|
window.mode = WindowMode::BorderlessFullscreen
|
||||||
|
} else {
|
||||||
|
window.mode = WindowMode::Windowed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for mut text in &mut query {
|
for mut text in &mut query {
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::assets::AssetLoader;
|
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct MainMenu;
|
pub struct MainMenu;
|
||||||
|
|
||||||
pub fn startup(mut commands: Commands, assets: Res<AssetLoader>) {
|
pub fn startup(mut commands: Commands) {
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
MainMenu,
|
MainMenu,
|
||||||
|
@ -25,7 +23,6 @@ pub fn startup(mut commands: Commands, assets: Res<AssetLoader>) {
|
||||||
TextBundle::from_section(
|
TextBundle::from_section(
|
||||||
"Text Example\nPress ENTER to play",
|
"Text Example\nPress ENTER to play",
|
||||||
TextStyle {
|
TextStyle {
|
||||||
font: assets.fonts.iosevkalytemin.clone(),
|
|
||||||
font_size: 100.0,
|
font_size: 100.0,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
@ -63,20 +60,4 @@ pub fn exit(mut commands: Commands, q: Query<Entity, With<MainMenu>>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(
|
pub fn update() {}
|
||||||
keyboard: Res<ButtonInput<KeyCode>>,
|
|
||||||
mut next_state: ResMut<NextState<crate::View>>,
|
|
||||||
mut app_exit_events: ResMut<Events<bevy::app::AppExit>>,
|
|
||||||
) {
|
|
||||||
for key in keyboard.get_just_pressed() {
|
|
||||||
match key {
|
|
||||||
KeyCode::Escape => {
|
|
||||||
app_exit_events.send(AppExit::Success);
|
|
||||||
}
|
|
||||||
KeyCode::Enter => {
|
|
||||||
next_state.set(crate::View::InGame);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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);
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug, Default)]
|
||||||
pub struct YSortable;
|
pub struct YSortable;
|
||||||
|
|
||||||
pub fn resolve_velocity(mut query: Query<(&Velocity, &mut Transform)>, time: Res<Time>) {
|
pub fn resolve_velocity(mut query: Query<(&Velocity, &mut Transform)>, time: Res<Time>) {
|
||||||
|
|
189
src/player.rs
189
src/player.rs
|
@ -1,17 +1,19 @@
|
||||||
use bevy::sprite::MaterialMesh2dBundle;
|
|
||||||
use bevy::sprite::Mesh2dHandle;
|
|
||||||
use bevy::{prelude::*, window::PrimaryWindow};
|
|
||||||
|
|
||||||
use crate::camera::Watched;
|
use crate::camera::Watched;
|
||||||
use crate::movement::YSortable;
|
use crate::movement::{Heading, Mover, Speed, Velocity, YSortable};
|
||||||
use crate::statue;
|
use crate::prelude::*;
|
||||||
use crate::{
|
use bevy::sprite::MaterialMesh2dBundle;
|
||||||
assets::AssetLoader,
|
|
||||||
movement::{Heading, Mover, Speed, Velocity},
|
|
||||||
};
|
|
||||||
|
|
||||||
const PLAYER_SPEED: f32 = 1000.;
|
const PLAYER_SPEED: f32 = 1000.;
|
||||||
|
|
||||||
|
// #[derive(Resource, Default)]
|
||||||
|
// pub struct Layout(Handle<TextureAtlasLayout>);
|
||||||
|
|
||||||
|
// #[derive(Resource)]
|
||||||
|
// pub struct CrosshairMaterial(Handle<ColorMaterial>);
|
||||||
|
|
||||||
|
// #[derive(Resource)]
|
||||||
|
// pub struct CrosshairMesh(Mesh2dHandle);
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Player;
|
pub struct Player;
|
||||||
|
|
||||||
|
@ -20,21 +22,28 @@ pub struct Crosshair;
|
||||||
|
|
||||||
pub fn startup(
|
pub fn startup(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
assets: Res<AssetLoader>,
|
assets: Res<AssetServer>,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
) {
|
) {
|
||||||
|
let layout = assets.add(TextureAtlasLayout::from_grid(
|
||||||
|
UVec2::new(32, 64),
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
Some(UVec2 { x: 0, y: 0 }),
|
||||||
|
Some(UVec2 { x: 0, y: 0 }),
|
||||||
|
));
|
||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Player,
|
Player,
|
||||||
YSortable,
|
YSortable,
|
||||||
Watched,
|
Watched,
|
||||||
SpriteBundle {
|
SpriteBundle {
|
||||||
texture: assets.images.player.clone(),
|
texture: assets.load("img/Player.png"),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
TextureAtlas {
|
TextureAtlas {
|
||||||
layout: assets.layouts.player.clone(),
|
layout,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
Mover {
|
Mover {
|
||||||
|
@ -44,7 +53,7 @@ pub fn startup(
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.with_children(|player| {
|
.with_children(|player| {
|
||||||
let mesh = Mesh2dHandle(meshes.add(Capsule2d::new(3.0, 25.0)));
|
let mesh = meshes.add(Capsule2d::new(3.0, 25.0));
|
||||||
let material = materials.add(Color::hsl(360. * 1 as f32 / 3 as f32, 0.95, 0.7));
|
let material = materials.add(Color::hsl(360. * 1 as f32 / 3 as f32, 0.95, 0.7));
|
||||||
// let global_transform = GlobalTransform::from_xyz(
|
// let global_transform = GlobalTransform::from_xyz(
|
||||||
// 0.0, 20.0,
|
// 0.0, 20.0,
|
||||||
|
@ -62,138 +71,34 @@ pub fn startup(
|
||||||
|
|
||||||
player.spawn((
|
player.spawn((
|
||||||
Crosshair,
|
Crosshair,
|
||||||
// SpatialBundle::default(),
|
// TODO: crosshair transform?
|
||||||
// SpatialListener::new(1.),
|
MaterialMesh2dBundle {
|
||||||
// MaterialMesh2dBundle {
|
// global_transform,
|
||||||
// // global_transform,
|
mesh: mesh.into(),
|
||||||
// mesh,
|
material,
|
||||||
// material,
|
transform,
|
||||||
// transform,
|
..default()
|
||||||
// ..default()
|
},
|
||||||
// },
|
|
||||||
// Text2dBundle {
|
|
||||||
// text: Text::from_section(
|
|
||||||
// "You",
|
|
||||||
// TextStyle {
|
|
||||||
// font_size: 11.0,
|
|
||||||
// font: assets.fonts.iosevkalytemin.clone(),
|
|
||||||
// color: Color::WHITE,
|
|
||||||
// ..default()
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// transform: Transform::from_translation(Vec3::new(30.0, -30.0, 0.)),
|
|
||||||
// ..default()
|
|
||||||
// },
|
|
||||||
));
|
));
|
||||||
|
player.spawn((SpatialBundle::default(), SpatialListener::new(1.)));
|
||||||
|
player.spawn((Text2dBundle {
|
||||||
|
text: Text::from_section(
|
||||||
|
"You",
|
||||||
|
TextStyle {
|
||||||
|
font_size: 18.,
|
||||||
|
color: Color::WHITE,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
transform: Transform::from_translation(Vec3::new(30.0, -30.0, 0.)),
|
||||||
|
..default()
|
||||||
|
},));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn controls(
|
pub fn control(input: Res<Input>, mut player: Query<&mut Heading, With<Player>>) {
|
||||||
mut commands: Commands,
|
if let Ok(mut heading) = player.get_single_mut() {
|
||||||
mut player: Query<(&mut Sprite, &mut TextureAtlas, &mut Heading, Entity), With<Player>>,
|
heading.0 = input.movement;
|
||||||
input: Res<ButtonInput<KeyCode>>,
|
|
||||||
mouse_input: Res<ButtonInput<MouseButton>>,
|
|
||||||
assets: Res<AssetLoader>,
|
|
||||||
win: Query<&Window, With<PrimaryWindow>>,
|
|
||||||
cam: Query<(&Camera, &GlobalTransform), With<Camera>>,
|
|
||||||
mut next_state: ResMut<NextState<crate::View>>,
|
|
||||||
mut crosshair: Query<&mut Transform, With<Crosshair>>,
|
|
||||||
) {
|
|
||||||
let (mut sprite, mut texture, mut heading, player_entity) =
|
|
||||||
player.get_single_mut().expect("no player_q entities");
|
|
||||||
let (camera, camera_transform) = cam.single();
|
|
||||||
|
|
||||||
let mouse_world_position = win
|
|
||||||
.single()
|
|
||||||
.cursor_position()
|
|
||||||
.and_then(|cursor| camera.viewport_to_world(&GlobalTransform::from_xyz(0., 0., 0.), cursor))
|
|
||||||
.map(|ray| ray.origin.truncate());
|
|
||||||
|
|
||||||
if let Some(pos) = mouse_world_position {
|
|
||||||
if let Ok(mut t) = crosshair.get_single_mut() {
|
|
||||||
t.look_at(Vec3::ZERO, pos.extend(0.));
|
|
||||||
t.translation = camera_transform.translation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
**heading = Vec2::ZERO;
|
|
||||||
for button in mouse_input.get_just_pressed() {
|
|
||||||
match button {
|
|
||||||
MouseButton::Left => {
|
|
||||||
if let Some(world_position) = win
|
|
||||||
.single()
|
|
||||||
.cursor_position()
|
|
||||||
.and_then(|cursor| camera.viewport_to_world(camera_transform, cursor))
|
|
||||||
.map(|ray| ray.origin.truncate())
|
|
||||||
{
|
|
||||||
let spos = world_position.extend(-world_position.y);
|
|
||||||
commands.spawn(statue::statue_at_position(&assets, spos));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for key in input.get_just_pressed() {
|
|
||||||
match key {
|
|
||||||
KeyCode::Escape => next_state.set(crate::View::MainMenu),
|
|
||||||
KeyCode::Enter => next_state.set(crate::View::MainMenu),
|
|
||||||
KeyCode::Space => {
|
|
||||||
let child = commands
|
|
||||||
.spawn(AudioSourceBundle {
|
|
||||||
source: assets.sounds.meow.clone(),
|
|
||||||
settings: PlaybackSettings::DESPAWN.with_spatial(false),
|
|
||||||
})
|
|
||||||
.id();
|
|
||||||
commands.entity(player_entity).push_children(&[child]);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for key in input.get_pressed() {
|
|
||||||
match key {
|
|
||||||
KeyCode::KeyA | KeyCode::ArrowLeft => {
|
|
||||||
**heading -= Vec2::X;
|
|
||||||
}
|
|
||||||
KeyCode::KeyD | KeyCode::ArrowRight => {
|
|
||||||
**heading += Vec2::X;
|
|
||||||
}
|
|
||||||
KeyCode::KeyW | KeyCode::ArrowUp => {
|
|
||||||
**heading += Vec2::Y;
|
|
||||||
}
|
|
||||||
KeyCode::KeyS | KeyCode::ArrowDown => {
|
|
||||||
**heading -= Vec2::Y;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if heading.y < 0. {
|
|
||||||
texture.index = 0;
|
|
||||||
} else if heading.y > 0. {
|
|
||||||
texture.index = 1;
|
|
||||||
} else if heading.x != 0. {
|
|
||||||
texture.index = 2;
|
|
||||||
sprite.flip_x = heading.x > 0.;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sprite_select(
|
|
||||||
mut q: Query<(&Handle<TextureAtlasLayout>, &mut TextureAtlas), With<Player>>,
|
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
|
||||||
texture_atlases: Res<Assets<TextureAtlasLayout>>,
|
|
||||||
) {
|
|
||||||
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
|
|
||||||
.get(texture)
|
|
||||||
.expect("could not load player texture");
|
|
||||||
if sprite.index < t.textures.len() - 1 {
|
|
||||||
sprite.index += 1;
|
|
||||||
} else {
|
|
||||||
sprite.index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
src/prelude.rs
Normal file
3
src/prelude.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub use crate::game::Gameobject;
|
||||||
|
pub use crate::input::Input;
|
||||||
|
pub use bevy::prelude::*;
|
|
@ -1,36 +1,58 @@
|
||||||
use crate::{assets::AssetLoader, movement::YSortable};
|
use crate::movement::YSortable;
|
||||||
use bevy::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug, Default)]
|
||||||
pub struct Statue;
|
pub struct Statue;
|
||||||
|
|
||||||
pub fn statue_at_position(
|
#[derive(Bundle, Default)]
|
||||||
assets: &Res<AssetLoader>,
|
pub struct StatueBundle {
|
||||||
translation: Vec3,
|
gameobject: Gameobject,
|
||||||
) -> (
|
statue: Statue,
|
||||||
Statue,
|
ysort: YSortable,
|
||||||
YSortable,
|
sprite: SpriteBundle,
|
||||||
bevy::prelude::SpriteBundle,
|
texture: TextureAtlas,
|
||||||
bevy::prelude::TextureAtlas,
|
|
||||||
) {
|
|
||||||
(
|
|
||||||
Statue,
|
|
||||||
YSortable,
|
|
||||||
SpriteBundle {
|
|
||||||
transform: Transform::from_translation(translation),
|
|
||||||
texture: assets.images.statue.clone(),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
TextureAtlas {
|
|
||||||
layout: assets.layouts.statue.clone(),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn startup(mut commands: Commands, assets: Res<AssetLoader>) {
|
pub fn startup(mut events: EventWriter<SpawnStatueEvent>) {
|
||||||
commands.spawn(statue_at_position(&assets, Vec3::new(50., 50., 0.)));
|
events.send_batch([
|
||||||
commands.spawn(statue_at_position(&assets, Vec3::new(50., 100., 0.)));
|
SpawnStatueEvent(Vec3::new(50., 50., 0.)),
|
||||||
|
SpawnStatueEvent(Vec3::new(50., 100., 0.)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Event)]
|
||||||
|
pub struct SpawnStatueEvent(Vec3);
|
||||||
|
|
||||||
|
pub fn spawn_statue(
|
||||||
|
mut events: EventReader<SpawnStatueEvent>,
|
||||||
|
mut commands: Commands,
|
||||||
|
assets: Res<AssetServer>,
|
||||||
|
mut layouts: ResMut<Assets<TextureAtlasLayout>>,
|
||||||
|
) {
|
||||||
|
// TODO: rebuilding this layout each spawn is surely not correct?
|
||||||
|
let layout = layouts.add(TextureAtlasLayout::from_grid(
|
||||||
|
UVec2::new(40, 74),
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
None,
|
||||||
|
Some(UVec2::new(443, 20)),
|
||||||
|
));
|
||||||
|
|
||||||
|
for ev in events.read() {
|
||||||
|
let bundle = StatueBundle {
|
||||||
|
sprite: SpriteBundle {
|
||||||
|
transform: Transform::from_translation(ev.0),
|
||||||
|
texture: assets.load("img/Props.png"),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
texture: TextureAtlas {
|
||||||
|
layout: layout.clone(),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
..default()
|
||||||
|
};
|
||||||
|
commands.spawn(bundle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit(mut commands: Commands, q: Query<Entity, With<Statue>>) {
|
pub fn exit(mut commands: Commands, q: Query<Entity, With<Statue>>) {
|
||||||
|
|
Loading…
Reference in a new issue