diff --git a/src/layout/asset/mod.rs b/src/layout/asset/mod.rs index 09fb80a..4b2c66a 100644 --- a/src/layout/asset/mod.rs +++ b/src/layout/asset/mod.rs @@ -57,14 +57,14 @@ pub fn load_level ( let player_pos = vec2(meters(level.interactive.player.x + 0.5), meters(level.interactive.player.y)); commands.spawn(Level).with_children(|parent| { - parent.spawn(tilemap_bundle(&asset_server, tiles)); + parent.spawn(tilemap_bundle(&textures, tiles)); parent.spawn(player_bundle(&asset_server, player_pos)); for DoorData { pos, facing_left, lock } in level.interactive.doors.iter() { let door_pos = vec2(meters(pos.x + 0.5), meters(pos.y)); let mut door = parent.spawn(door_bundle(&textures, door_pos, *facing_left)); if let Some(lock_facing_left) = lock { - door.with_child(padlock_bundle(&asset_server, *lock_facing_left)); + door.with_child(padlock_bundle(&textures, *lock_facing_left)); } } @@ -78,7 +78,7 @@ pub fn load_level ( if i == *floors - 1 { up = None; } - parent.spawn(stairs_bundle(&asset_server, pos, up, down)); + parent.spawn(stairs_bundle(&textures, pos, up, down)); pos.y += meters(4.); down = Some(vec2(meters(-2.), meters(-4.))); } @@ -100,7 +100,7 @@ pub fn load_level ( for LampData { pos, intensity, radius } in level.interactive.lamps.iter() { let pos = vec2(meters(pos.x), meters(pos.y - 0.5)); - parent.spawn(lamp_bundle(&asset_server, pos, *intensity, meters(*radius))); + parent.spawn(lamp_bundle(&textures, pos, *intensity, meters(*radius))); } }); } diff --git a/src/layout/container.rs b/src/layout/container.rs index e334a02..953358a 100644 --- a/src/layout/container.rs +++ b/src/layout/container.rs @@ -7,7 +7,7 @@ use crate::{ inventory::{ ActiveInventory, Inventory, - } + }, }; use super::*; @@ -40,18 +40,8 @@ pub fn container_bundle( position: Vec2, inventory_size: UVec2, ) -> impl Bundle { - let texture_atlas = TextureAtlas { - layout: textures.container.atlas.clone(), - index: textures.container.indices["main"], - }; - let hl_texture_atlas = texture_atlas.clone().with_index(textures.container.indices["highlighted"]); - let sprite = Sprite { - image: textures.container.image.clone(), - texture_atlas: Some(texture_atlas), - ..default() - }; - let mut highlight_sprite = sprite.clone(); - highlight_sprite.texture_atlas = Some(hl_texture_atlas); + let sprite = textures.container.sprite("main"); + let highlight_sprite = textures.container.sprite("highlight"); ( Container, Transform::from_xyz(position.x, position.y - meters(0.5), 0.), diff --git a/src/layout/door.rs b/src/layout/door.rs index ba10e0e..7f436ee 100644 --- a/src/layout/door.rs +++ b/src/layout/door.rs @@ -83,20 +83,15 @@ pub fn door_collider_bundle() -> impl Bundle { ) } -fn door_sprites(texture: &AtlasLayoutTexture, facing_left: bool) -> (Sprite, Sprite) { - let texture_atlas = TextureAtlas { - layout: texture.atlas.clone(), - index: texture.indices["main"], - }; - let hl_texture_atlas = texture_atlas.clone().with_index(texture.indices["highlighted"]); +fn door_sprites(texture: &AtlasLayoutTexture, flip_x: bool) -> (Sprite, Sprite) { let sprite = Sprite { - image: texture.image.clone(), - flip_x: facing_left, - texture_atlas: Some(texture_atlas), - ..default() + flip_x, + ..texture.sprite("main") + }; + let highlight_sprite = Sprite { + flip_x, + ..texture.sprite("highlight") }; - let mut highlight_sprite = sprite.clone(); - highlight_sprite.texture_atlas = Some(hl_texture_atlas); (sprite, highlight_sprite) } @@ -107,6 +102,7 @@ pub fn door_bundle(textures: &Res, position: Vec2, facing_left: Door(direction), Transform::from_xyz(position.x, position.y, 0.), Name::new(format!("Door ({}, {})", position.x, position.y)), + InheritedVisibility::VISIBLE, children![ door_collider_bundle(), ( diff --git a/src/layout/light.rs b/src/layout/light.rs index a2fa077..b4aee7d 100644 --- a/src/layout/light.rs +++ b/src/layout/light.rs @@ -1,17 +1,14 @@ use bevy::prelude::*; use bevy_light_2d::prelude::*; -use crate::meters; - -const LAMP_IMAGE_PATH: &'static str = "sprites/level/lamp.png"; +use crate::{layout::LayoutTextures, meters}; #[derive(Component, Clone, Copy, Default, Reflect, Debug, PartialEq, Eq)] #[reflect(Component, Clone, Default, Debug, PartialEq)] #[require(Transform)] pub struct Lamp; -pub fn lamp_bundle(asset_server: &Res, pos: Vec2, intensity: f32, radius: f32) -> impl Bundle { - let image = asset_server.load(LAMP_IMAGE_PATH); +pub fn lamp_bundle(textures: &Res, pos: Vec2, intensity: f32, radius: f32) -> impl Bundle { ( SpotLight2d { intensity, @@ -21,6 +18,11 @@ pub fn lamp_bundle(asset_server: &Res, pos: Vec2, intensity: f32, r ..default() }, Transform::from_xyz(pos.x, pos.y, 0.), - Sprite::from_image(image), + Sprite::from_image(textures.light.0.clone()), + children![ + ( + + ) + ], ) } diff --git a/src/layout/lock.rs b/src/layout/lock.rs index a26a51c..23de591 100644 --- a/src/layout/lock.rs +++ b/src/layout/lock.rs @@ -10,8 +10,6 @@ use crate::{ use super::*; -const PADLOCK_IMAGE_PATH: &'static str = "sprites/interactive/padlock.png"; - #[derive(Component, Debug, PartialEq, Eq, Default, Clone, Copy, Reflect)] #[reflect(Component, Debug, PartialEq, Default, Clone)] #[require(InteractiveObject)] @@ -51,21 +49,29 @@ pub fn on_padlock_interaction( commands.entity(lockpick_id).despawn(); } -pub fn padlock_bundle(asset_server: &Res, facing_left: bool) -> impl Bundle { - let image = asset_server.load(PADLOCK_IMAGE_PATH); +pub fn padlock_bundle(textures: &Res, facing_left: bool) -> impl Bundle { let sign = if facing_left { -1. } else { 1. }; ( Padlock, Sprite { - image, - flip_x: facing_left, - ..default() + flip_x: !facing_left, + ..textures.lock.sprite("main") }, Transform::from_xyz(meters(sign * 0.125), meters(0.), 0.), - Children::spawn_one(( - Transform::from_xyz(meters(sign * 0.1875), 0., 0.), - Collider::cuboid(meters(0.1875), meters(1.)), - Sensor, + InheritedVisibility::VISIBLE, + Children::spawn(( + Spawn(( + Transform::from_xyz(meters(sign * 0.1875), 0., 0.), + Collider::cuboid(meters(0.1875), meters(1.)), + Sensor, + )), + Spawn(( + Sprite { + flip_x: !facing_left, + ..textures.lock.sprite("highlight") + }, + Visibility::Hidden, + )), )), ) } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index f2cd0a5..4880c73 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -59,6 +59,21 @@ impl AtlasLayoutTexture { ) -> Self { Self { image, atlas, indices } } + + pub fn texture_atlas(&self, name: &str) -> TextureAtlas { + TextureAtlas { + layout: self.atlas.clone(), + index: self.indices[name], + } + } + + pub fn sprite(&self, name: &str) -> Sprite { + Sprite { + image: self.image.clone(), + texture_atlas: Some(self.texture_atlas(name)), + ..default() + } + } } #[derive(Resource, Reflect, Clone, PartialEq, Eq, Debug, Default)] diff --git a/src/layout/stairs.rs b/src/layout/stairs.rs index 5590985..6e6441c 100644 --- a/src/layout/stairs.rs +++ b/src/layout/stairs.rs @@ -5,8 +5,6 @@ use crate::{meters, player::Player}; use super::*; -const STAIRS_SPRITE_PATH: &'static str = "sprites/interactive/stairs.png"; - #[derive(Component, Debug, PartialEq, Eq, Default, Clone, Copy, Reflect)] #[reflect(Component, Debug, PartialEq, Default, Clone)] #[require(InteractiveObject, Collider, Sensor)] @@ -63,13 +61,13 @@ pub fn on_stairs_interact( } pub fn stairs_bundle( - asset_server: &Res, + textures: &Res, position: Vec2, up_position: Option, down_position: Option, ) -> impl Bundle { - let image = asset_server.load(STAIRS_SPRITE_PATH); let (has_up, has_down) = (up_position.is_some(), down_position.is_some()); + let stairs = textures.stairs.clone(); ( Stairs { up: up_position, @@ -84,9 +82,16 @@ pub fn stairs_bundle( StairCollider::Up, Collider::cuboid(meters(1.), meters(1.)), Transform::from_xyz(meters(-1.), 0., 0.), + InheritedVisibility::VISIBLE, + Children::spawn( + Spawn(( + stairs.sprite("up"), + Visibility::Hidden, + )), + ), )); parent.spawn(( - Sprite::from_image(image), + stairs.sprite("main"), Transform::from_xyz(0., meters(1.5), 0.), )); } @@ -96,6 +101,13 @@ pub fn stairs_bundle( StairCollider::Down, Collider::cuboid(meters(1.), meters(1.)), Transform::from_xyz(meters(1.), 0., 0.), + InheritedVisibility::VISIBLE, + Children::spawn( + Spawn(( + stairs.sprite("down"), + Visibility::Hidden, + )), + ), )); } }), diff --git a/src/layout/systems.rs b/src/layout/systems.rs index f61b6e8..505b16f 100644 --- a/src/layout/systems.rs +++ b/src/layout/systems.rs @@ -1,6 +1,5 @@ use bevy::{ - ecs::query::QueryFilter, - prelude::*, + ecs::query::QueryFilter, image::{ImageArrayLayout, ImageLoaderSettings}, prelude::* }; use bevy_rapier2d::prelude::*; @@ -102,14 +101,14 @@ fn double_atlas( "main".to_owned(), atlas.add_texture(URect::from_corners( uvec2(0, 0), - uvec2(single_size.x, single_size.y) + uvec2(single_size.x, single_size.y), )), ); indices.insert( - "highlighted".to_owned(), + "highlight".to_owned(), atlas.add_texture(URect::from_corners( uvec2(single_size.x, 0), - uvec2(single_size.x * 2, single_size.y) + uvec2(single_size.x * 2, single_size.y), )), ); atlases.add(atlas) @@ -122,19 +121,68 @@ pub fn load_layout_textures( ) { // Container let image = asset_server.load("sprites/interactive/container.png"); - let mut indices = HashMap::new(); + let mut indices = HashMap::with_capacity(2); let atlas = double_atlas(&mut atlases, &mut indices, uvec2(32, 16)); textures.container = AtlasLayoutTexture::new(image, atlas, indices); // Closed door let image = asset_server.load("sprites/interactive/door_closed.png"); - let mut indices = HashMap::new(); + let mut indices = HashMap::with_capacity(2); let atlas = double_atlas(&mut atlases, &mut indices, uvec2(4, 32)); textures.door_closed = AtlasLayoutTexture::new(image, atlas, indices); // Opened door let image = asset_server.load("sprites/interactive/door_opened.png"); - let mut indices = HashMap::new(); + let mut indices = HashMap::with_capacity(2); let atlas = double_atlas(&mut atlases, &mut indices, uvec2(16, 32)); textures.door_opened = AtlasLayoutTexture::new(image, atlas, indices); + + // Light + let image = asset_server.load("sprites/level/lamp.png"); + textures.light = SingleLayoutTexture(image); + + // Padlock + let image = asset_server.load("sprites/interactive/padlock.png"); + let mut indices = HashMap::with_capacity(2); + let atlas = double_atlas(&mut atlases, &mut indices, uvec2(2, 4)); + textures.lock = AtlasLayoutTexture::new(image, atlas, indices); + + // Stairs + let image = asset_server.load("sprites/interactive/stairs.png"); + let mut indices = HashMap::with_capacity(3); + let atlas = { + let mut atlas = TextureAtlasLayout::new_empty(uvec2(72, 80)); + indices.insert( + "main".to_owned(), + atlas.add_texture(URect::from_corners( + uvec2(0, 0), + uvec2(64, 80), + )), + ); + indices.insert( + "up".to_owned(), + atlas.add_texture(URect::from_corners( + uvec2(64, 0), + uvec2(72, 8), + )), + ); + indices.insert( + "down".to_owned(), + atlas.add_texture(URect::from_corners( + uvec2(64, 8), + uvec2(72, 16), + )), + ); + atlases.add(atlas) + }; + textures.stairs = AtlasLayoutTexture::new(image, atlas, indices); + + // Tilemap + let image = asset_server.load_with_settings( + "sprites/level/tilemap.png", + |settings: &mut ImageLoaderSettings| { + settings.array_layout = Some(ImageArrayLayout::RowCount { rows: 3 }) + } + ); + textures.tilemap = SingleLayoutTexture(image); } diff --git a/src/layout/tilemap.rs b/src/layout/tilemap.rs index aa1da05..67c2f09 100644 --- a/src/layout/tilemap.rs +++ b/src/layout/tilemap.rs @@ -1,8 +1,4 @@ use bevy::{ - image::{ - ImageArrayLayout, - ImageLoaderSettings, - }, prelude::*, sprite_render::{ TileData, @@ -13,9 +9,8 @@ use bevy::{ use bevy_light_2d::prelude::*; use bevy_rapier2d::prelude::*; -use crate::meters; +use crate::{layout::LayoutTextures, meters}; -const TILEMAP_PATH: &'static str = "sprites/level/tilemap.png"; const TILE_DISPLAY_SIZE: UVec2 = UVec2::splat(meters(1.) as u32); #[derive(Component, Debug, PartialEq, Eq, Default, Clone, Copy, Reflect)] @@ -23,7 +18,7 @@ const TILE_DISPLAY_SIZE: UVec2 = UVec2::splat(meters(1.) as u32); pub struct Tilemap; pub fn tilemap_bundle( - asset_server: &Res, + textures: &Res, tiles: Vec<(u16, URect)>, ) -> impl Bundle { let mut size = uvec2(0, 0); @@ -41,12 +36,7 @@ pub fn tilemap_bundle( TilemapChunk { chunk_size: size, tile_display_size: TILE_DISPLAY_SIZE, - tileset: asset_server.load_with_settings( - TILEMAP_PATH, - |settings: &mut ImageLoaderSettings| { - settings.array_layout = Some(ImageArrayLayout::RowCount { rows: 3 }) - }, - ), + tileset: textures.tilemap.0.clone(), ..default() }, Transform::from_xyz(