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
+76 -51
View File
@@ -1,9 +1,6 @@
use crate::item::Item;
use crate::{constants::*, game};
use bevy::math::vec2;
use crate::game;
use bevy::prelude::*;
use std::collections::HashMap;
use std::process::exit;
#[derive(Component)]
#[require(Sprite)]
@@ -58,65 +55,93 @@ pub struct DoorTile {
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>>,
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() {
*visibility = Visibility::Hidden;
// Build spatial lookup
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 {
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;
query
.par_iter_mut()
.for_each(|(mut visibility, transform, _)| {
*visibility = Visibility::Hidden;
// Early exit for above camera layer
if transform.translation.z > z_index.0 {
return;
}
}
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; // 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,
);
let pos = (
transform.translation.x.round() as i32,
transform.translation.y.round() as i32,
transform.translation.z.round() as i32,
);
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;
// Check for any opaque tiles above the current tile
for z_offset in 1..=100 {
// 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
if above_pos.2 <= z_index.0 as i32 {
// get any tiles
if let Some(neighbor_tile) = tile_map.get(&above_pos) {
// If there's an opaque tile above, hide the current tile
if neighbor_tile.opaque {
return; // No need to check further; the tile should remain hidden
}
}
}
}
}
}
// 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(