occlusion part 2

This commit is contained in:
StephenAdamson
2024-12-17 21:10:21 +00:00
parent 80afd547e5
commit caacf4e072
6 changed files with 103 additions and 58 deletions
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

+5 -4
View File
@@ -6,7 +6,8 @@ use bevy::prelude::*;
use noise::{NoiseFn, Perlin}; use noise::{NoiseFn, Perlin};
use rand::prelude::*; use rand::prelude::*;
pub const Z_INDEX: f32 = 0.; #[derive(Resource)]
pub struct ZIndex(pub f32);
pub fn setup_level(mut commands: Commands, asset_server: Res<AssetServer>) { pub fn setup_level(mut commands: Commands, asset_server: Res<AssetServer>) {
setup_tilemap(&mut commands, &asset_server); setup_tilemap(&mut commands, &asset_server);
@@ -26,9 +27,9 @@ pub fn setup_level(mut commands: Commands, asset_server: Res<AssetServer>) {
fn setup_tilemap(commands: &mut Commands, asset_server: &Res<AssetServer>) { fn setup_tilemap(commands: &mut Commands, asset_server: &Res<AssetServer>) {
let perlin = Perlin::new(0); let perlin = Perlin::new(0);
for x in -15..15 { for x in -50..50 {
for y in -15..15 { for y in -50..50 {
for z in -2..15 { for z in -5..40 {
let position = Vec3::new(x as f32 * TILE_SIZE, y as f32 * TILE_SIZE, -z as f32); let position = Vec3::new(x as f32 * TILE_SIZE, y as f32 * TILE_SIZE, -z as f32);
// Generate Perlin noise value // Generate Perlin noise value
+5 -3
View File
@@ -1,16 +1,17 @@
use bevy::prelude::*; use bevy::prelude::*;
mod constants;
mod camera; mod camera;
mod citizen; mod citizen;
mod constants;
mod cursor;
mod game; mod game;
mod item; mod item;
mod tile; mod tile;
mod tiles; mod tiles;
mod cursor;
fn main() { fn main() {
App::new() App::new()
.insert_resource(game::ZIndex(-5.0))
.add_plugins( .add_plugins(
DefaultPlugins DefaultPlugins
.set(WindowPlugin { .set(WindowPlugin {
@@ -24,7 +25,7 @@ fn main() {
) )
.insert_resource(ClearColor(Color::srgb(0.0, 0.0, 0.0))) .insert_resource(ClearColor(Color::srgb(0.0, 0.0, 0.0)))
.add_systems(Startup, (game::setup_level, camera::spawn_panning_camera)) .add_systems(Startup, (game::setup_level, camera::spawn_panning_camera))
.add_systems(PostStartup, tile::tile_sprite_occlusion_update) .add_systems(PostStartup, tile::tile_sprite_occlusion)
.add_systems(Startup, cursor::setup_curor) .add_systems(Startup, cursor::setup_curor)
.add_systems( .add_systems(
FixedUpdate, FixedUpdate,
@@ -32,6 +33,7 @@ fn main() {
camera::camera_movement, camera::camera_movement,
citizen::citizen_movement, citizen::citizen_movement,
tile::tile_item_sprite_update, tile::tile_item_sprite_update,
// tile::camera_z_movement.chain(tile::tile_sprite_occlusion),
), ),
) )
.add_systems(FixedUpdate, cursor::move_cursor) .add_systems(FixedUpdate, cursor::move_cursor)
+76 -51
View File
@@ -1,9 +1,6 @@
use crate::item::Item; use crate::item::Item;
use crate::{constants::*, game}; use crate::game;
use bevy::math::vec2;
use bevy::prelude::*; use bevy::prelude::*;
use std::collections::HashMap;
use std::process::exit;
#[derive(Component)] #[derive(Component)]
#[require(Sprite)] #[require(Sprite)]
@@ -58,65 +55,93 @@ pub struct DoorTile {
pub locked: bool, pub locked: bool,
} }
pub fn tile_sprite_occlusion_update( // pub fn camera_z_movement(
// keyboard_input: Res<ButtonInput<KeyCode>>,
// mut z_index: ResMut<game::ZIndex>,
// ) {
// if keyboard_input.pressed(KeyCode::ShiftLeft) {
// z_index.0 -= 1.0;
// }
// if keyboard_input.pressed(KeyCode::ShiftRight) {
// z_index.0 += 1.0;
// }
// }
pub fn tile_sprite_occlusion(
mut query: Query<(&mut Visibility, &Transform, &Tile), With<Tile>>, mut query: Query<(&mut Visibility, &Transform, &Tile), With<Tile>>,
tile_query: Query<(&Transform, &Tile)>, tile_query: Query<(&Transform, &Tile)>,
z_index: ResMut<game::ZIndex>,
) { ) {
let mut z_map: HashMap<(i32, i32), i32> = HashMap::new(); use std::collections::HashMap;
for (mut visibility, transform, tile) in query.iter_mut() { // Build spatial lookup
*visibility = Visibility::Hidden; let tile_map: HashMap<(i32, i32, i32), &Tile> = tile_query
.iter()
.map(|(transform, tile)| {
(
(
transform.translation.x.round() as i32,
transform.translation.y.round() as i32,
transform.translation.z.round() as i32,
),
tile,
)
})
.collect();
if transform.translation.z > game::Z_INDEX { query
continue; .par_iter_mut()
} .for_each(|(mut visibility, transform, _)| {
if let Some(z_val) = z_map.get(&( *visibility = Visibility::Hidden;
transform.translation.x.round() as i32,
transform.translation.y.round() as i32, // Early exit for above camera layer
)) { if transform.translation.z > z_index.0 {
if *z_val >= transform.translation.z as i32 { return;
continue;
} }
}
for x_offset in -1..=1 { let pos = (
for y_offset in -1..=1 { transform.translation.x.round() as i32,
for z_offset in -1..=1 { transform.translation.y.round() as i32,
if x_offset == 0 && y_offset == 0 && z_offset == 0 { transform.translation.z.round() as i32,
continue; // don't check against itself );
}
let neighbor_position = transform.translation
+ Vec3::new(
x_offset as f32 * TILE_SIZE,
y_offset as f32 * TILE_SIZE,
z_offset as f32 * TILE_SIZE,
);
if let Some((_, neighbor_tile)) = // Check for any opaque tiles above the current tile
tile_query.iter().find(|(neighbor_transform, _)| { for z_offset in 1..=100 {
neighbor_transform.translation == neighbor_position // Adjust the max height of the check if needed
}) let above_pos = (pos.0, pos.1, pos.2 + z_offset);
{ // look up until camera height
// id == 0 is sky. So if bordering a sky tile (i.e. not deep underground) if above_pos.2 <= z_index.0 as i32 {
if neighbor_tile.id == 0 { // get any tiles
*visibility = Visibility::Visible; if let Some(neighbor_tile) = tile_map.get(&above_pos) {
// if opaque, do not look deeper on this X,Y // If there's an opaque tile above, hide the current tile
if tile.opaque { if neighbor_tile.opaque {
z_map.insert( return; // No need to check further; the tile should remain hidden
(
transform.translation.x.round() as i32,
transform.translation.y.round() as i32,
),
transform.translation.z.round() as i32,
);
}
break;
} }
} }
} }
} }
}
} // Check all neighbors around the tile
for x_offset in -1..=1 {
for y_offset in -1..=1 {
for z_offset in -1..=1 {
if x_offset == 0 && y_offset == 0 && z_offset == 0 {
continue;
}
let neighbor_pos = (pos.0 + x_offset, pos.1 + y_offset, pos.2 + z_offset);
if let Some(neighbor_tile) = tile_map.get(&neighbor_pos) {
// id == 0 is sky
if neighbor_tile.id == 0 {
*visibility = Visibility::Visible;
break;
}
}
}
}
}
});
} }
pub fn tile_item_sprite_update( pub fn tile_item_sprite_update(
+17
View File
@@ -93,4 +93,21 @@ impl TilePrefab {
}, },
} }
} }
pub fn underground(position: Vec3, asset_server: &Res<AssetServer>) -> Self {
TilePrefab {
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
sprite: Sprite {
image: asset_server.load("underground.png"),
..Default::default()
},
tile: Tile {
id: 5,
opaque: true,
},
tile_state: TileState {
timer: Timer::from_seconds(1.0, TimerMode::Repeating),
},
}
}
} }