188 lines
5.1 KiB
Rust
188 lines
5.1 KiB
Rust
use crate::item::Item;
|
|
use crate::game;
|
|
use bevy::prelude::*;
|
|
|
|
#[derive(Component)]
|
|
#[require(Sprite)]
|
|
pub struct Tile {
|
|
pub id: u32,
|
|
pub opaque: bool,
|
|
}
|
|
|
|
impl Default for Tile {
|
|
fn default() -> Self {
|
|
Self {
|
|
id: 1,
|
|
opaque: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Component)]
|
|
#[require(Tile)]
|
|
pub struct FloorTile {
|
|
pub walkable: bool,
|
|
pub astar_weight: u8,
|
|
}
|
|
|
|
impl Default for FloorTile {
|
|
fn default() -> Self {
|
|
Self {
|
|
walkable: true,
|
|
astar_weight: 1,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Component)]
|
|
pub struct WallTile {
|
|
pub tile: Tile,
|
|
pub solid: bool,
|
|
pub embrasure: bool, // Arrowslit, crenelle, grate, cage etc
|
|
}
|
|
|
|
#[derive(Component)]
|
|
pub struct WaterTile {
|
|
pub tile: Tile,
|
|
pub swimmable: bool,
|
|
pub astarmultiplier: f32,
|
|
}
|
|
|
|
#[derive(Component)]
|
|
pub struct DoorTile {
|
|
pub tile: Tile,
|
|
pub open: bool,
|
|
pub locked: bool,
|
|
}
|
|
|
|
// 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>,
|
|
) {
|
|
use std::collections::HashMap;
|
|
|
|
// 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();
|
|
|
|
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;
|
|
}
|
|
|
|
let pos = (
|
|
transform.translation.x.round() as i32,
|
|
transform.translation.y.round() as i32,
|
|
transform.translation.z.round() as i32,
|
|
);
|
|
|
|
// 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(
|
|
time: Res<Time>,
|
|
mut query_tile: Query<(Entity, &Children, &mut TileState), With<Tile>>,
|
|
mut query_item: Query<(&mut Visibility, &Item)>,
|
|
) {
|
|
for (_, children, mut state) in query_tile.iter_mut() {
|
|
state.timer.tick(time.delta());
|
|
if !state.timer.finished() {
|
|
continue;
|
|
}
|
|
|
|
let mut visible_index: Option<usize> = None;
|
|
|
|
for (i, &child) in children.iter().enumerate() {
|
|
if let Ok((mut visibility, _)) = query_item.get_mut(child) {
|
|
if matches!(*visibility, Visibility::Visible) {
|
|
visible_index = Some(i);
|
|
*visibility = Visibility::Hidden;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
let next_index = if let Some(current_index) = visible_index {
|
|
(current_index + 1) % children.len()
|
|
} else {
|
|
0
|
|
};
|
|
|
|
if let Some(&next_child) = children.get(next_index) {
|
|
if let Ok((mut visibility, _)) = query_item.get_mut(next_child) {
|
|
*visibility = Visibility::Visible;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Component)]
|
|
pub struct TileState {
|
|
pub timer: Timer,
|
|
}
|