diff --git a/assets/levels/level.toml b/assets/levels/level.toml new file mode 100644 index 0000000..39eaf4a --- /dev/null +++ b/assets/levels/level.toml @@ -0,0 +1,110 @@ +[[tiles.floors]] +x = 0 +y = 0 +w = 16 + +[[tiles.floors]] +x = 0 +y = 4 +w = 16 + +[[tiles.floors]] +x = 0 +y = 8 +w = 16 + +[[tiles.walls]] +x = 0 +y = 1 +h = 3 + +[[tiles.walls]] +x = 0 +y = 5 +h = 3 + +[[tiles.walls]] +x = 15 +y = 1 +h = 3 + +[[tiles.walls]] +x = 15 +y = 5 +h = 3 + +[[tiles.wall_connectors]] +x = 4 +y = 3 + +[[tiles.wall_connectors]] +x = 4 +y = 7 + +[[tiles.wall_connectors]] +x = 11 +y = 3 + +[[tiles.wall_connectors]] +x = 11 +y = 7 + +[interactive.player] +x = 1 +y = 1 + +[[interactive.doors]] +x = 4 +y = 1 +facing = "right" + +[[interactive.doors]] +x = 4 +y = 5 +facing = "right" +lock = "right" + +[[interactive.doors]] +x = 11 +y = 1 +facing = "left" +lock = "left" + +[[interactive.doors]] +x = 11 +y = 1 +facing = "left" + +[[interactive.stairs]] +x = 8 +y = 1 +floors = 2 + +[[interactive.containers]] +x = 2 +y = 1 + +[[interactive.containers]] +x = 14 +y = 1 + +[[interactive.containers]] +x = 2 +y = 5 +w = 4 +h = 4 + +[interactive.containers.items] +id = "lockpick" +x = 2 +y = 2 + +[[interactive.containers]] +x = 14 +y = 5 +w = 2 +h = 2 + +[interactive.containers.items] +id = "lockpick" +rotated = true diff --git a/assets/levels/level_alt.toml b/assets/levels/level_alt.toml new file mode 100644 index 0000000..04d4343 --- /dev/null +++ b/assets/levels/level_alt.toml @@ -0,0 +1,48 @@ +[tiles] +floors = [ + { x = 0, y = 0, w = 16 }, + { x = 0, y = 4, w = 16 }, + { x = 0, y = 8, w = 16 }, +] +walls = [ + { x = 0, y = 1, h = 3 }, + { x = 0, y = 5, h = 3 }, + { x = 15, y = 1, h = 3 }, + { x = 15, y = 5, h = 3 }, +] +wall_connectors = [ + { x = 4, y = 3 }, + { x = 4, y = 7 }, + { x = 11, y = 3 }, + { x = 11, y = 7 }, +] + +[interactive] +player = { x = 1, y = 1 } +doors = [ + { x = 4, y = 1, facing = "right" }, + { x = 4, y = 5, facing = "right", lock = "right" }, + { x = 11, y = 1, facing = "left", lock = "left" }, + { x = 11, y = 5, facing = "left" }, +] +stairs = [ + { x = 8, y = 1, floors = 2 }, +] +containers = [ + { x = 2, y = 1 }, + { x = 14, y = 1 }, + { + x = 2, y = 5, + w = 4, h = 4, + items = [ + { id = "lockpick", x = 2, y = 2 }, + ], + }, + { + x = 14, y = 5, + w = 2, h = 2, + items = [ + { id = "lockpick", rotated = true }, + ], + }, +] diff --git a/src/item/lockpick.rs b/src/item/lockpick.rs index 32cd95a..8cd8dea 100644 --- a/src/item/lockpick.rs +++ b/src/item/lockpick.rs @@ -9,10 +9,14 @@ const LOCKPICK_SPRITE: &'static str = "sprites/items/lockpick.png"; #[require(Item)] pub struct Lockpick; -pub fn lockpick_bundle(asset_server: &Res, position: UVec2) -> impl Bundle { +pub fn lockpick_bundle(asset_server: &Res, position: UVec2, rotated: bool) -> impl Bundle { let image = asset_server.load(LOCKPICK_SPRITE); + let mut item = Item::new(uvec2(1, 1), position); + if rotated { + item.rotate(); + } ( - Item::new(uvec2(1, 1), position), + item, ItemData { image, name: "Lockpick".into(), diff --git a/src/layout/asset.rs b/src/layout/asset.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/layout/asset.rs @@ -0,0 +1 @@ + diff --git a/src/layout/mod.rs b/src/layout/mod.rs index d298e8e..32f6e72 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,5 +1,6 @@ use bevy::prelude::*; +pub mod asset; pub mod container; pub mod door; pub mod lock; diff --git a/src/layout/systems.rs b/src/layout/systems.rs index d15af28..f09a6b5 100644 --- a/src/layout/systems.rs +++ b/src/layout/systems.rs @@ -78,80 +78,66 @@ pub fn setup_world( mut commands: Commands, asset_server: Res, ) { - // floor 1F - let mut tiles = (0..16).map(|x| { - (0, uvec2(x, 1)) - }).collect::>(); - - // floor/ceil 1-2F - tiles.extend((0..16).map(|x| { - (0, uvec2(x, 5)) - })); - - // ceil 2F - tiles.extend((0..16).map(|x| { - (0, uvec2(x, 9)) - })); + let tiles = [ + ( 0, ( 0, 0, 16, 1 )), // 1F floor + ( 0, ( 0, 4, 16, 1 )), // 1F ceiling / 2F floor + ( 0, ( 0, 8, 16, 1 )), // 2F ceiling + + ( 1, ( 0, 1, 1, 3 )), // 1F left wall + ( 1, ( 0, 5, 1, 3 )), // 2F left wall + ( 1, ( 15, 1, 1, 3 )), // 1F right wall + ( 1, ( 15, 5, 1, 3 )), // 2F right wall + + ( 2, ( 4, 3, 1, 1 )), // 1F left door connector + ( 2, ( 4, 7, 1, 1 )), // 2F left door connector + ( 2, ( 11, 3, 1, 1 )), // 1F right door connector + ( 2, ( 11, 7, 1, 1 )), // 2F right door connector + ].into_iter().map(|(id, (x, y, w, h))| { + (id, URect::from_corners(uvec2(x, y), uvec2(x + w - 1, y + h - 1))) + }).collect::>(); - // walls - tiles.extend([ - (0, 4), (0, 3), (0, 2), - (0, 8), (0, 7), (0, 6), - (15, 4), (15, 3), (15, 2), - (15, 8), (15, 7), (15, 6), - ].iter().map(|(x, y)| { - (1, uvec2(*x, *y)) - })); - - // wall connectors - tiles.extend([ - (4, 8), (4, 4), (11, 8), (11, 4), - ].iter().map(|(x, y)| { - (2, uvec2(*x, *y)) - })); - - commands.spawn(tilemap::tilemap_bundle(&asset_server, uvec2(16, 10), tiles)); + commands.spawn(tilemap::tilemap_bundle(&asset_server, tiles)); - commands.spawn(door::door_bundle(&asset_server, vec2(meters(-3.5), 0.), false)); - commands.spawn(door::door_bundle(&asset_server, vec2(meters(-3.5), meters(4.)), false)) + commands.spawn(player_bundle(&asset_server, vec2(meters(1.5), meters(1.)))); + + commands.spawn(door::door_bundle(&asset_server, vec2(meters(4.5), meters(1.)), false)); + commands.spawn(door::door_bundle(&asset_server, vec2(meters(4.5), meters(5.)), false)) .with_child(lock::padlock_bundle(&asset_server, false)); - commands.spawn(door::door_bundle(&asset_server, vec2(meters(3.5), 0.), true)) + commands.spawn(door::door_bundle(&asset_server, vec2(meters(11.5), meters(1.)), true)) .with_child(lock::padlock_bundle(&asset_server, true)); - commands.spawn(door::door_bundle(&asset_server, vec2(meters(3.5), meters(4.)), true)); + commands.spawn(door::door_bundle(&asset_server, vec2(meters(11.5), meters(5.)), true)); commands.spawn(stairs::stairs_bundle( &asset_server, - vec2(meters(0.), 0.), + vec2(meters(8.), meters(1.)), Some(vec2(meters(2.), meters(4.))), None, )); commands.spawn(stairs::stairs_bundle( &asset_server, - vec2(meters(0.), meters(4.)), + vec2(meters(8.), meters(5.)), None, Some(vec2(meters(-2.), meters(-4.))), )); commands.spawn(container::container_bundle( &asset_server, - vec2(meters(-6.), 0.), + vec2(meters(2.), meters(1.)), uvec2(1, 1), )); commands.spawn(container::container_bundle( &asset_server, - vec2(meters(-6.), meters(4.)), - uvec2(1, 1), - )).with_child(lockpick_bundle(&asset_server, UVec2::ZERO)); - commands.spawn(container::container_bundle( - &asset_server, - vec2(meters(6.), 0.), + vec2(meters(14.), meters(1.)), uvec2(1, 1), )); commands.spawn(container::container_bundle( &asset_server, - vec2(meters(6.), meters(4.)), - uvec2(1, 1), - )).with_child(lockpick_bundle(&asset_server, UVec2::ZERO)); - - commands.spawn(player_bundle(&asset_server, vec2(meters(-6.), meters(4.)))); + vec2(meters(2.), meters(5.)), + uvec2(4, 4), + )).with_child(lockpick_bundle(&asset_server, uvec2(2, 2), false)); + commands.spawn(container::container_bundle( + &asset_server, + vec2(meters(14.), meters(5.)), + uvec2(2, 2), + )).with_child(lockpick_bundle(&asset_server, UVec2::ZERO, true)); } diff --git a/src/layout/tilemap.rs b/src/layout/tilemap.rs index 7a9bd7d..1e81175 100644 --- a/src/layout/tilemap.rs +++ b/src/layout/tilemap.rs @@ -23,11 +23,15 @@ pub struct Tilemap; pub fn tilemap_bundle( asset_server: &Res, - size: UVec2, - tiles: Vec<(u16, UVec2)>, + tiles: Vec<(u16, URect)>, ) -> impl Bundle { + let mut size = uvec2(0, 0); + for tile in tiles.iter() { + size.x = size.x.max(tile.1.max.x + 1); + size.y = size.y.max(tile.1.max.y + 1); + } let tile_data: Vec> = (0..size.element_product()).map(|xy| { - if let Some((id, _)) = tiles.iter().find(|(_, pos)| pos.x == xy % size.x && pos.y == xy / size.x) { + if let Some((id, _)) = tiles.iter().find(|(_, rect)| rect.contains(uvec2(xy % size.x, xy / size.x))) { Some(TileData::from_tileset_index(*id)) } else { None } }).collect(); @@ -44,27 +48,26 @@ pub fn tilemap_bundle( ), ..default() }, - Transform::from_xyz(0., meters(0.5) * size.y as f32 - meters(3.), 0.), + Transform::from_xyz( + meters(0.5) * size.x as f32, + meters(0.5) * size.y as f32 - meters(1.), + 0., + ), TilemapChunkTileData(tile_data), - Children::spawn(SpawnIter(tiles.into_iter().map(move |(_, pos)| {( - // TODO: optimize colliders - Collider::cuboid(meters(0.5), meters(0.5)), + Children::spawn(SpawnIter(tiles.into_iter().map(move |(_, rect)| { + let mut rect = rect.as_rect(); + rect.max = vec2(rect.max.x + 1., rect.max.y + 1.); + + let (width, height) = (rect.width(), rect.height()); + let offset = rect.center(); + ( + Collider::cuboid(meters(width * 0.5), meters(height * 0.5)), Transform::from_xyz( - meters(0.5 + pos.x as f32 - (size.x as f32 * 0.5)), - meters(0.5 + pos.y as f32 - (size.y as f32 * 0.5)), + meters(offset.x - size.x as f32 * 0.5), + meters(offset.y - size.y as f32 * 0.5), 0., ), - )}) - )), - //Children::spawn(SpawnIter(colliders.into_iter() - // .map(move |(collider, pos)| {( - // collider.clone(), - // Transform::from_xyz( - // pos.x - meters(0.5) * size.x as f32, - // pos.y - meters(0.5) * size.y as f32, - // 0. - // ), - // )}) - //)), + )} + ))), ) }