bevy-learning

A learning project of mine.
git clone git://archive.git.mtrnord.blog/MTRNord/bevy-learning.git
Log | Files | Refs

commit 9fdcfbf0319894cdcf70ccd9036085a58ba7302b
parent 08178cd94b5133862634507fda68e2cf74c12e22
Author: MTRNord <mtrnord1@gmail.com>
Date:   Thu,  1 Apr 2021 02:17:12 +0200

Improve texture loading

Took 50 minutes

Diffstat:
Msrc/main.rs | 27++++++++++++++++++++++++++-
Msrc/plugins/player.rs | 41++++++++++++++++++++++++++++++++++-------
Msrc/plugins/world.rs | 49++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 102 insertions(+), 15 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -7,14 +7,19 @@ use crate::plugins::{ use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; use bevy::render::camera::{OrthographicProjection, ScalingMode}; use bevy::{prelude::*, window::WindowMode}; +use std::collections::HashMap; mod entities; mod plugins; +#[derive(Default)] +pub struct AssetsLoading(Vec<HandleUntyped>); + #[derive(Default, Clone)] pub struct GameState { pub spawned: bool, pub world_state: WorldState, + pub asset_map: HashMap<String, Handle<Texture>>, } fn main() { @@ -29,6 +34,7 @@ fn main() { ..Default::default() }) .init_resource::<GameState>() + .init_resource::<AssetsLoading>() .add_plugins(DefaultPlugins) .add_plugin(FrameTimeDiagnosticsPlugin::default()) .add_plugin(LogDiagnosticsPlugin::default()) @@ -39,7 +45,12 @@ fn main() { .run(); } -fn setup(commands: &mut Commands /*mut kurinji: ResMut<Kurinji>*/) { +fn setup( + commands: &mut Commands, + mut loading: ResMut<AssetsLoading>, + asset_server: Res<AssetServer>, + mut game_state: ResMut<GameState>, +) { commands // Spawn a camera .spawn(OrthographicCameraBundle { @@ -58,4 +69,18 @@ fn setup(commands: &mut Commands /*mut kurinji: ResMut<Kurinji>*/) { }) .with(PLAYER_START) .with(MainCamera); + + let sunny_texture_handle = asset_server.load("tilesets/SunnyLand_by_Ansimuz-extended.png"); + loading.0.push(sunny_texture_handle.clone_untyped()); + game_state + .asset_map + .insert("Sunnyland".into(), sunny_texture_handle); + let dungeon_tileset_texture_handle = + asset_server.load("tilesets/0x72_DungeonTilesetII_v1.3.png"); + loading + .0 + .push(dungeon_tileset_texture_handle.clone_untyped()); + game_state + .asset_map + .insert("DungeonTileset".into(), dungeon_tileset_texture_handle); } diff --git a/src/plugins/player.rs b/src/plugins/player.rs @@ -2,7 +2,8 @@ use crate::entities::common::Health; use crate::entities::markers::{Movable, Player, Wall}; use crate::entities::player::{PlayerBundle, PlayerName, PlayerXp}; use crate::plugins::world::{GridLocation, MainCamera, SPRITE_HEIGHT, SPRITE_WIDTH}; -use crate::GameState; +use crate::{AssetsLoading, GameState}; +use bevy::asset::LoadState; use bevy::prelude::*; use std::collections::HashMap; @@ -13,8 +14,7 @@ pub struct PlayerPlugin; impl Plugin for PlayerPlugin { fn build(&self, app: &mut AppBuilder) { app.add_system(player_movement.system()) - .add_system(setup_player.system()) - .add_startup_system(setup_player.system()); + .add_system(setup_player.system()); } } @@ -23,14 +23,33 @@ fn setup_player( asset_server: Res<AssetServer>, texture_atlases: ResMut<Assets<TextureAtlas>>, game_state: ResMut<GameState>, + loading: Res<AssetsLoading>, + textures: Res<Assets<Texture>>, ) { if !game_state.spawned { + let mut ready = true; + for handle in loading.0.iter() { + match asset_server.get_load_state(handle) { + LoadState::Failed => { + ready = false; + } + LoadState::Loaded => {} + _ => { + ready = false; + } + } + } + + if !ready { + return; + } + setup_player_internal( PLAYER_START, &mut commands, - asset_server, texture_atlases, game_state, + &textures, ); } } @@ -38,12 +57,20 @@ fn setup_player( fn setup_player_internal( grid_location: GridLocation, commands: &mut Commands, - asset_server: Res<AssetServer>, mut texture_atlases: ResMut<Assets<TextureAtlas>>, mut game_state: ResMut<GameState>, + textures: &Res<Assets<Texture>>, ) { - let texture_handle = asset_server.load("tilesets/0x72_DungeonTilesetII_v1.3.png"); - let texture_atlas = TextureAtlas::from_grid(texture_handle, Vec2::new(16.0, 16.0), 32, 32); + let texture_handle = game_state.asset_map.get("DungeonTileset").unwrap(); + let texture: &Texture = textures.get(texture_handle.id).unwrap(); + let cols = texture.size.width / 16; + let rows = texture.size.height / 16; + let texture_atlas = TextureAtlas::from_grid( + texture_handle.clone(), + Vec2::new(16.0, 16.0), + cols as usize, + rows as usize, + ); let texture_atlas_handle = texture_atlases.add(texture_atlas); // Spawn player diff --git a/src/plugins/world.rs b/src/plugins/world.rs @@ -1,6 +1,7 @@ use crate::entities::markers::Wall; use crate::plugins::player::PLAYER_START; -use crate::GameState; +use crate::{AssetsLoading, GameState}; +use bevy::asset::LoadState; use bevy::prelude::*; use noise::{NoiseFn, OpenSimplex, Seedable}; use rand::Rng; @@ -88,16 +89,25 @@ pub const SPRITE_HEIGHT: f32 = 16.0; fn setup_wall( grid_location: GridLocation, commands: &mut Commands, - asset_server: &Res<AssetServer>, + game_state: &ResMut<GameState>, texture_atlases: &mut ResMut<Assets<TextureAtlas>>, + textures: &Res<Assets<Texture>>, ) { - let texture_handle = asset_server.load("tilesets/SunnyLand_by_Ansimuz-extended.png"); - let texture_atlas = TextureAtlas::from_grid(texture_handle, Vec2::new(16.0, 16.0), 23, 21); + let texture_handle = game_state.asset_map.get("Sunnyland").unwrap(); + let texture: &Texture = textures.get(texture_handle.id).unwrap(); + let cols = texture.size.width / 16; + let rows = texture.size.height / 16; + let texture_atlas = TextureAtlas::from_grid( + texture_handle.clone(), + Vec2::new(17.0, 17.0), + cols as usize, + rows as usize, + ); let texture_atlas_handle = texture_atlases.add(texture_atlas); commands .spawn(SpriteSheetBundle { sprite: TextureAtlasSprite { - index: 6, + index: 48, ..Default::default() }, transform: Transform::from_translation(Vec3::new( @@ -115,8 +125,10 @@ fn setup_wall( fn draw( commands: &mut Commands, mut game_state: ResMut<GameState>, - asset_server: Res<AssetServer>, mut texture_atlases: ResMut<Assets<TextureAtlas>>, + server: Res<AssetServer>, + loading: Res<AssetsLoading>, + textures: Res<Assets<Texture>>, ) { if game_state.world_state.map_loaded && game_state.world_state.level == game_state.world_state.requested_level @@ -124,6 +136,23 @@ fn draw( return; } + let mut ready = true; + for handle in loading.0.iter() { + match server.get_load_state(handle) { + LoadState::Failed => { + ready = false; + } + LoadState::Loaded => {} + _ => { + ready = false; + } + } + } + + if !ready { + return; + } + if game_state.world_state.seed.is_none() { let mut rng = rand::thread_rng(); game_state.world_state.seed = Some(rng.gen()); @@ -149,7 +178,13 @@ fn draw( let noise_value = f * 16.0 + (16.0 / 2.0); if noise_value > 4.8 { - setup_wall(coord, commands, &asset_server, &mut texture_atlases); + setup_wall( + coord, + commands, + &game_state, + &mut texture_atlases, + &textures, + ); } } }