diff --git a/Cargo.lock b/Cargo.lock index 3d127f8..a1da89d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -575,6 +575,17 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "bevy_ecs_tilemap" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d880047f5deaf5166ffc08238125a4ccbd2837f781ca6525fa200fcf5785ba3b" +dependencies = [ + "bevy", + "log", + "regex", +] + [[package]] name = "bevy_egui" version = "0.28.0" @@ -2258,7 +2269,11 @@ version = "0.1.0" dependencies = [ "bevy", "bevy-inspector-egui", + "bevy_ecs_tilemap", "bevy_framepace", + "rand", + "rand_pcg", + "rand_seeder", ] [[package]] @@ -2984,6 +2999,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "presser" version = "0.3.1" @@ -3064,6 +3085,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -3072,6 +3105,27 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_seeder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9febe641d2842ffc76ee962668a17578767c4e01735e4802b21ed9a24b2e4e" +dependencies = [ + "rand_core", +] [[package]] name = "range-alloc" diff --git a/Cargo.toml b/Cargo.toml index 050b08f..744f970 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,11 @@ bevy = { version = "0.14.0", default-features = false, features = [ # "detailed_trace", # probably useful troubleshooting information during runtime ] } bevy-inspector-egui = "0.25.1" +bevy_ecs_tilemap = "0.14.0" bevy_framepace = "0.17.1" +rand = "0.8.5" +rand_pcg = "0.3.1" +rand_seeder = "0.3.0" [profile.dev] opt-level = 1 diff --git a/assets/img/tiles.ase b/assets/img/tiles.ase new file mode 100644 index 0000000..792f201 Binary files /dev/null and b/assets/img/tiles.ase differ diff --git a/src/main.rs b/src/main.rs index bea9022..b494d66 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod camera; mod game; mod input; mod main_menu; +mod map; mod movement; mod player; mod prelude; @@ -10,6 +11,7 @@ mod statue; use bevy::asset::load_internal_binary_asset; use bevy::audio::{AudioPlugin, SpatialScale}; use bevy::window::{PrimaryWindow, WindowMode}; +use bevy_ecs_tilemap::TilemapPlugin; use input::Input; use prelude::*; use statue::SpawnStatueEvent; @@ -24,8 +26,9 @@ pub enum Game { #[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)] pub enum View { #[default] - LoadingScreen, + LoadingMenu, MainMenu, + LoadingGame, InGame, } @@ -60,7 +63,8 @@ fn main() -> AppExit { .set(ImagePlugin::default_nearest()), bevy::diagnostic::FrameTimeDiagnosticsPlugin, bevy_framepace::FramepacePlugin, - bevy_inspector_egui::quick::WorldInspectorPlugin::new(), + // bevy_inspector_egui::quick::WorldInspectorPlugin::new(), + TilemapPlugin, )); load_internal_binary_asset!( @@ -91,45 +95,58 @@ fn main() -> AppExit { app.add_event::(); - 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, + app.add_systems( + OnEnter(View::LoadingMenu), + ((startup, camera::startup), main_menu::startup), + ) + .add_systems(OnExit(View::MainMenu), main_menu::exit) + .add_systems( + OnEnter(View::LoadingGame), + (player::startup, statue::startup, map::spawn), + ) + .add_systems( + OnExit(View::InGame), + (player::exit, statue::exit, map::exit), + ) + .add_systems( + Update, + ( + load_menu.run_if(in_state(View::LoadingMenu)), + load_game.run_if(in_state(View::LoadingGame)), + input::process_input, + (update,).after(input::process_input), ( - finish_setup.run_if(in_state(View::LoadingScreen)), - input::process_input, - (update,).after(input::process_input), - ( - player::control, - player::meow_on_r, - player::player_debug_info, - 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), - ) - .after(input::process_input) - .in_set(InGameSet), - (main_menu::update).in_set(MainMenuSet), - ), - ) - .insert_resource(ClearColor(Color::srgb(0.3, 0.1, 0.5))); + player::control, + player::meow_on_r, + player::player_debug_info, + 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), + ) + .after(input::process_input) + .in_set(InGameSet), + (main_menu::update).in_set(MainMenuSet), + ), + ) + .insert_resource(ClearColor(Color::srgb(0.3, 0.1, 0.5))); app.run() } #[derive(Component)] struct FpsText; -fn finish_setup(mut app_state: ResMut>) { +fn load_menu(mut app_state: ResMut>) { app_state.set(View::MainMenu); } +fn load_game(mut app_state: ResMut>) { + app_state.set(View::InGame); +} + fn startup(mut commands: Commands) { let font_size = 48.; commands.spawn(( @@ -144,7 +161,6 @@ fn startup(mut commands: Commands) { ), TextSection::from_style(TextStyle { font_size, - color: Color::hsla(0.5, 0.5, 0.5, 0.5), ..default() }), ]) @@ -170,20 +186,22 @@ fn update( if input.cancel { match view.get() { View::InGame => { - next_state.set(crate::View::MainMenu); + next_state.set(crate::View::LoadingMenu); } View::MainMenu => { app_exit_events.send(AppExit::Success); } - View::LoadingScreen => {} + View::LoadingMenu => {} + View::LoadingGame => {} } } else if input.action { match view.get() { View::InGame => {} View::MainMenu => { - next_state.set(crate::View::InGame); + next_state.set(crate::View::LoadingGame); } - View::LoadingScreen => {} + View::LoadingMenu => {} + View::LoadingGame => {} } } if keys.just_pressed(KeyCode::Enter) diff --git a/src/map.rs b/src/map.rs new file mode 100644 index 0000000..d5dedfc --- /dev/null +++ b/src/map.rs @@ -0,0 +1,82 @@ +use crate::prelude::*; +use bevy_ecs_tilemap::prelude::*; +use rand::prelude::*; +use rand_pcg::Pcg64; +use rand_seeder::Seeder; + +#[derive(Component, Debug)] +pub struct Tilemap; + +pub fn spawn(mut commands: Commands, assets: Res) { + // let task_pool = AsyncComputeTaskPool::get(); + + // let task = task_pool.spawn(async move {}); + + let mut rng: Pcg64 = Seeder::from("stripy zebra").make_rng(); + let size = TilemapSize { x: 1024, y: 1024 }; + let tilemap_entity = commands.spawn_empty().id(); + let mut tile_storage = TileStorage::empty(size); + let mut batch = Vec::::with_capacity(size.x as usize * size.y as usize); + for x in 0..size.x { + for y in 0..size.y { + let tile_pos = TilePos { x, y }; + let texture_index = TileTextureIndex(if rng.gen_range(0..1000) > 925 { + rng.gen_range(0..(16 * 8)) + } else { + 0 + }); + // let texture_index = TileTextureIndex(0); + // let tile_entity = commands + // .spawn(TileBundle { + // position: tile_pos, + // tilemap_id: TilemapId(tilemap_entity), + // texture_index, + // ..Default::default() + // }) + // .id(); + // let tile_entity = commands + batch.push(TileBundle { + position: tile_pos, + tilemap_id: TilemapId(tilemap_entity), + texture_index, + ..Default::default() + }); + // .id(); + // tile_storage.set(&tile_pos, tile_entity); + } + } + + commands.spawn_batch(batch); + + // for tb in batch { + // tile_storage.set(&tile_pos, tile_entity); + // } + + let texture_handle: Handle = assets.load("img/Tileset Grass.png"); + + let tile_size = TilemapTileSize { x: 16.0, y: 16.0 }; + let grid_size = tile_size.into(); + let map_type = TilemapType::default(); + + let texture = TilemapTexture::Single(texture_handle); + + commands.entity(tilemap_entity).insert(( + Tilemap, + TilemapBundle { + grid_size, + map_type, + size, + storage: tile_storage, + texture, + tile_size, + transform: get_tilemap_center_transform(&size, &grid_size, &map_type, f32::MIN), + ..default() + }, + )); +} + +pub fn exit(mut commands: Commands, q: Query>) { + for id in q.iter() { + commands.entity(id).despawn_recursive(); + } +} diff --git a/src/player.rs b/src/player.rs index ba73fd7..444851f 100644 --- a/src/player.rs +++ b/src/player.rs @@ -41,6 +41,7 @@ pub fn startup( commands .spawn(( Player, + Name::new("Player"), VisibilityBundle { visibility: Visibility::Inherited, ..default() @@ -57,6 +58,7 @@ pub fn startup( )) .with_children(|player| { player.spawn(( + Name::new("PlayerSprite"), SpriteBundle { texture: assets.load("img/Player.png"), ..default()