diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3499889 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,45 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'dorf'", + "cargo": { + "args": [ + "build", + "--bin=dorf", + "--package=dorf" + ], + "filter": { + "name": "dorf", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'dorf'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=dorf", + "--package=dorf" + ], + "filter": { + "name": "dorf", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 9ae15c9..aacab8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ opt-level = 3 # Enable only a small amount of optimization in debug mode [profile.dev] opt-level = 1 +debug = true [profile.release] lto = true diff --git a/assets/bedrock.png b/assets/bedrock.png new file mode 100644 index 0000000..57ab404 Binary files /dev/null and b/assets/bedrock.png differ diff --git a/src/game.rs b/src/game.rs index bc37ca5..5daf154 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,12 +1,12 @@ use crate::citizen::Citizen; +use crate::constants::*; use crate::item::{Item, ItemBundle}; use crate::tiles::TilePrefab; -use crate::constants::*; use bevy::prelude::*; -use rand::prelude::*; use noise::{NoiseFn, Perlin}; +use rand::prelude::*; -pub const Z_INDEX:f32 = 0.; +pub const Z_INDEX: f32 = 0.; pub fn setup_level(mut commands: Commands, asset_server: Res) { setup_tilemap(&mut commands, &asset_server); @@ -26,21 +26,13 @@ pub fn setup_level(mut commands: Commands, asset_server: Res) { fn setup_tilemap(commands: &mut Commands, asset_server: &Res) { let perlin = Perlin::new(0); - for x in -20..20 { - for y in -20..20 { - for z in -2..10 { - let position = Vec3::new( - x as f32 * TILE_SIZE, - y as f32 * TILE_SIZE, - -z as f32, - ); + for x in -15..15 { + for y in -15..15 { + for z in -2..15 { + let position = Vec3::new(x as f32 * TILE_SIZE, y as f32 * TILE_SIZE, -z as f32); // Generate Perlin noise value - let noise_value = perlin.get([ - x as f64 * 0.1, - y as f64 * 0.1, - z as f64 * 0.1, - ]); + let noise_value = perlin.get([x as f64 * 0.1, y as f64 * 0.1, z as f64 * 0.1]); let mut items: Vec = vec![]; if noise_value < -0.4 { @@ -73,4 +65,10 @@ fn setup_tilemap(commands: &mut Commands, asset_server: &Res) { } } } + for x in -15..15 { + for y in -15..15 { + let position = Vec3::new(x as f32 * TILE_SIZE, y as f32 * TILE_SIZE, -14.); + commands.spawn(TilePrefab::bedrock(position, asset_server)); + } + } } diff --git a/src/main.rs b/src/main.rs index 1aba68d..6d98fd5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ fn main() { ) .insert_resource(ClearColor(Color::srgb(0.0, 0.0, 0.0))) .add_systems(Startup, (game::setup_level, camera::spawn_panning_camera)) - .add_systems(PostStartup, tile::tile_sprite_visibility_update) + .add_systems(PostStartup, tile::tile_sprite_occlusion_update) .add_systems(Startup, cursor::setup_curor) .add_systems( FixedUpdate, diff --git a/src/tile.rs b/src/tile.rs index 110df9f..58d9e0b 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,16 +1,23 @@ use crate::item::Item; use crate::{constants::*, game}; +use bevy::math::vec2; use bevy::prelude::*; +use std::collections::HashMap; +use std::process::exit; #[derive(Component)] #[require(Sprite)] pub struct Tile { pub id: u32, + pub opaque: bool, } impl Default for Tile { fn default() -> Self { - Self { id: 1 } + Self { + id: 1, + opaque: true, + } } } @@ -51,22 +58,32 @@ pub struct DoorTile { pub locked: bool, } -pub fn tile_sprite_visibility_update( - mut query: Query<(&mut Visibility, &Transform), With>, +pub fn tile_sprite_occlusion_update( + mut query: Query<(&mut Visibility, &Transform, &Tile), With>, tile_query: Query<(&Transform, &Tile)>, ) { - for (mut visibility, transform) in query.iter_mut() { + let mut z_map: HashMap<(i32, i32), i32> = HashMap::new(); + + for (mut visibility, transform, tile) in query.iter_mut() { *visibility = Visibility::Hidden; if transform.translation.z > game::Z_INDEX { continue; } + if let Some(z_val) = z_map.get(&( + transform.translation.x.round() as i32, + transform.translation.y.round() as i32, + )) { + if *z_val >= transform.translation.z as i32 { + continue; + } + } for x_offset in -1..=1 { for y_offset in -1..=1 { - for z_offset in -1..=0 { + for z_offset in -1..=1 { if x_offset == 0 && y_offset == 0 && z_offset == 0 { - continue; // Skip the current tile + continue; // don't check against itself } let neighbor_position = transform.translation + Vec3::new( @@ -75,13 +92,24 @@ pub fn tile_sprite_visibility_update( z_offset as f32 * TILE_SIZE, ); - if let Some((neighbor_transform, neighbor_tile)) = + if let Some((_, neighbor_tile)) = tile_query.iter().find(|(neighbor_transform, _)| { neighbor_transform.translation == neighbor_position }) { + // id == 0 is sky. So if bordering a sky tile (i.e. not deep underground) if neighbor_tile.id == 0 { *visibility = Visibility::Visible; + // if opaque, do not look deeper on this X,Y + if tile.opaque { + z_map.insert( + ( + transform.translation.x.round() as i32, + transform.translation.y.round() as i32, + ), + transform.translation.z.round() as i32, + ); + } break; } } diff --git a/src/tiles.rs b/src/tiles.rs index 3aab658..c6ed97b 100644 --- a/src/tiles.rs +++ b/src/tiles.rs @@ -1,6 +1,6 @@ -use bevy::prelude::*; -use crate::tile::{Tile, TileState}; use crate::constants::*; +use crate::tile::{Tile, TileState}; +use bevy::prelude::*; #[derive(Bundle)] pub struct TilePrefab { @@ -18,7 +18,10 @@ impl TilePrefab { image: asset_server.load("dirt.png"), ..Default::default() }, - tile: Tile {id:1}, + tile: Tile { + id: 1, + opaque: true, + }, tile_state: TileState { timer: Timer::from_seconds(1.0, TimerMode::Repeating), }, @@ -32,7 +35,10 @@ impl TilePrefab { image: asset_server.load("grass.png"), ..Default::default() }, - tile: Tile {id:2}, + tile: Tile { + id: 2, + opaque: true, + }, tile_state: TileState { timer: Timer::from_seconds(1.0, TimerMode::Repeating), }, @@ -46,7 +52,10 @@ impl TilePrefab { image: asset_server.load("rock.png"), ..Default::default() }, - tile: Tile {id:3}, + tile: Tile { + id: 3, + opaque: true, + }, tile_state: TileState { timer: Timer::from_seconds(1.0, TimerMode::Repeating), }, @@ -59,10 +68,29 @@ impl TilePrefab { image: asset_server.load("sky.png"), ..Default::default() }, - tile: Tile {id:0}, + tile: Tile { + id: 0, + opaque: false, + }, tile_state: TileState { timer: Timer::from_seconds(1.0, TimerMode::Repeating), }, } } -} \ No newline at end of file + pub fn bedrock(position: Vec3, asset_server: &Res) -> Self { + TilePrefab { + transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)), + sprite: Sprite { + image: asset_server.load("bedrock.png"), + ..Default::default() + }, + tile: Tile { + id: 4, + opaque: true, + }, + tile_state: TileState { + timer: Timer::from_seconds(1.0, TimerMode::Repeating), + }, + } + } +}