diff --git a/Cargo.lock b/Cargo.lock index c6c8e07..6531503 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2528,7 +2528,7 @@ dependencies = [ [[package]] name = "expedition_demo" -version = "0.4.0" +version = "0.3.0" dependencies = [ "bevy", "bevy_common_assets", diff --git a/Cargo.toml b/Cargo.toml index 377927a..e3ab1e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["codegen-backend"] [package] name = "expedition_demo" -version = "0.4.0" +version = "0.3.0" edition = "2024" [dependencies] @@ -10,15 +10,12 @@ bevy = { version = "0.18.0", features = ["bevy_remote", "debug", "experimental_b bevy_common_assets = { version = "0.15.0", features = ["toml"] } bevy_input = { version = "0.18.0", features = ["serde", "serialize"] } bevy_light_2d = "0.9.0" -bevy_rapier2d = { version = "0.33.0" } +bevy_rapier2d = { version = "0.33.0", features = ["rapier-debug-render"] } clap = { version = "4.6.0", features = ["derive"] } leafwing-input-manager = "0.20.0" serde = { version = "1.0.228", features = ["derive"] } toml = "1.0.3" -[features] -colliders = ["bevy_rapier2d/rapier-debug-render"] - [profile.dev] opt-level = 1 codegen-backend = "cranelift" diff --git a/src/layout/asset/mod.rs b/src/layout/asset/mod.rs index 4b2c66a..09fb80a 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(&textures, tiles)); + parent.spawn(tilemap_bundle(&asset_server, 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(&textures, *lock_facing_left)); + door.with_child(padlock_bundle(&asset_server, *lock_facing_left)); } } @@ -78,7 +78,7 @@ pub fn load_level ( if i == *floors - 1 { up = None; } - parent.spawn(stairs_bundle(&textures, pos, up, down)); + parent.spawn(stairs_bundle(&asset_server, 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(&textures, pos, *intensity, meters(*radius))); + parent.spawn(lamp_bundle(&asset_server, pos, *intensity, meters(*radius))); } }); } diff --git a/src/layout/container.rs b/src/layout/container.rs index 953358a..e334a02 100644 --- a/src/layout/container.rs +++ b/src/layout/container.rs @@ -7,7 +7,7 @@ use crate::{ inventory::{ ActiveInventory, Inventory, - }, + } }; use super::*; @@ -40,8 +40,18 @@ pub fn container_bundle( position: Vec2, inventory_size: UVec2, ) -> impl Bundle { - let sprite = textures.container.sprite("main"); - let highlight_sprite = textures.container.sprite("highlight"); + 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); ( 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 7f436ee..ba10e0e 100644 --- a/src/layout/door.rs +++ b/src/layout/door.rs @@ -83,15 +83,20 @@ pub fn door_collider_bundle() -> impl Bundle { ) } -fn door_sprites(texture: &AtlasLayoutTexture, flip_x: bool) -> (Sprite, Sprite) { +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"]); let sprite = Sprite { - flip_x, - ..texture.sprite("main") - }; - let highlight_sprite = Sprite { - flip_x, - ..texture.sprite("highlight") + image: texture.image.clone(), + flip_x: facing_left, + texture_atlas: Some(texture_atlas), + ..default() }; + let mut highlight_sprite = sprite.clone(); + highlight_sprite.texture_atlas = Some(hl_texture_atlas); (sprite, highlight_sprite) } @@ -102,7 +107,6 @@ 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 f14380b..a2fa077 100644 --- a/src/layout/light.rs +++ b/src/layout/light.rs @@ -1,26 +1,26 @@ use bevy::prelude::*; use bevy_light_2d::prelude::*; -use crate::{layout::LayoutTextures, meters}; +use crate::meters; + +const LAMP_IMAGE_PATH: &'static str = "sprites/level/lamp.png"; #[derive(Component, Clone, Copy, Default, Reflect, Debug, PartialEq, Eq)] #[reflect(Component, Clone, Default, Debug, PartialEq)] #[require(Transform)] pub struct Lamp; -pub fn lamp_bundle(textures: &Res, pos: Vec2, intensity: f32, radius: f32) -> impl Bundle { +pub fn lamp_bundle(asset_server: &Res, pos: Vec2, intensity: f32, radius: f32) -> impl Bundle { + let image = asset_server.load(LAMP_IMAGE_PATH); ( + SpotLight2d { + intensity, + radius, + source_width: meters(0.5), + cast_shadows: true, + ..default() + }, Transform::from_xyz(pos.x, pos.y, 0.), - Sprite::from_image(textures.light.0.clone()), - children![( - SpotLight2d { - intensity, - radius, - source_width: meters(0.5), - cast_shadows: true, - ..default() - }, - Transform::from_xyz(0., 1., 0.), - )], + Sprite::from_image(image), ) } diff --git a/src/layout/lock.rs b/src/layout/lock.rs index 23de591..a26a51c 100644 --- a/src/layout/lock.rs +++ b/src/layout/lock.rs @@ -10,6 +10,8 @@ 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)] @@ -49,29 +51,21 @@ pub fn on_padlock_interaction( commands.entity(lockpick_id).despawn(); } -pub fn padlock_bundle(textures: &Res, facing_left: bool) -> impl Bundle { +pub fn padlock_bundle(asset_server: &Res, facing_left: bool) -> impl Bundle { + let image = asset_server.load(PADLOCK_IMAGE_PATH); let sign = if facing_left { -1. } else { 1. }; ( Padlock, Sprite { - flip_x: !facing_left, - ..textures.lock.sprite("main") + image, + flip_x: facing_left, + ..default() }, Transform::from_xyz(meters(sign * 0.125), meters(0.), 0.), - 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, - )), + Children::spawn_one(( + Transform::from_xyz(meters(sign * 0.1875), 0., 0.), + Collider::cuboid(meters(0.1875), meters(1.)), + Sensor, )), ) } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 4880c73..f2cd0a5 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -59,21 +59,6 @@ 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 6e6441c..5590985 100644 --- a/src/layout/stairs.rs +++ b/src/layout/stairs.rs @@ -5,6 +5,8 @@ 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)] @@ -61,13 +63,13 @@ pub fn on_stairs_interact( } pub fn stairs_bundle( - textures: &Res, + asset_server: &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, @@ -82,16 +84,9 @@ 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(( - stairs.sprite("main"), + Sprite::from_image(image), Transform::from_xyz(0., meters(1.5), 0.), )); } @@ -101,13 +96,6 @@ 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 505b16f..f61b6e8 100644 --- a/src/layout/systems.rs +++ b/src/layout/systems.rs @@ -1,5 +1,6 @@ use bevy::{ - ecs::query::QueryFilter, image::{ImageArrayLayout, ImageLoaderSettings}, prelude::* + ecs::query::QueryFilter, + prelude::*, }; use bevy_rapier2d::prelude::*; @@ -101,14 +102,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( - "highlight".to_owned(), + "highlighted".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) @@ -121,68 +122,19 @@ pub fn load_layout_textures( ) { // Container let image = asset_server.load("sprites/interactive/container.png"); - let mut indices = HashMap::with_capacity(2); + let mut indices = HashMap::new(); 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::with_capacity(2); + let mut indices = HashMap::new(); 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::with_capacity(2); + let mut indices = HashMap::new(); 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 67c2f09..aa1da05 100644 --- a/src/layout/tilemap.rs +++ b/src/layout/tilemap.rs @@ -1,4 +1,8 @@ use bevy::{ + image::{ + ImageArrayLayout, + ImageLoaderSettings, + }, prelude::*, sprite_render::{ TileData, @@ -9,8 +13,9 @@ use bevy::{ use bevy_light_2d::prelude::*; use bevy_rapier2d::prelude::*; -use crate::{layout::LayoutTextures, meters}; +use crate::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)] @@ -18,7 +23,7 @@ const TILE_DISPLAY_SIZE: UVec2 = UVec2::splat(meters(1.) as u32); pub struct Tilemap; pub fn tilemap_bundle( - textures: &Res, + asset_server: &Res, tiles: Vec<(u16, URect)>, ) -> impl Bundle { let mut size = uvec2(0, 0); @@ -36,7 +41,12 @@ pub fn tilemap_bundle( TilemapChunk { chunk_size: size, tile_display_size: TILE_DISPLAY_SIZE, - tileset: textures.tilemap.0.clone(), + tileset: asset_server.load_with_settings( + TILEMAP_PATH, + |settings: &mut ImageLoaderSettings| { + settings.array_layout = Some(ImageArrayLayout::RowCount { rows: 3 }) + }, + ), ..default() }, Transform::from_xyz( diff --git a/src/lib.rs b/src/lib.rs index c087d58..6a008ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,6 @@ impl Plugin for ExpeditionPlugin { }, }; app.add_plugins(( - #[cfg(feature = "colliders")] RapierDebugRenderPlugin::default(), RapierPhysicsPlugin::<()>::default() .with_custom_initialization(rapier_init),