Files
dorf/src/tile.rs
T
2024-12-17 19:44:54 +00:00

163 lines
4.5 KiB
Rust

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,
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 tile_sprite_occlusion_update(
mut query: Query<(&mut Visibility, &Transform, &Tile), With<Tile>>,
tile_query: Query<(&Transform, &Tile)>,
) {
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..=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,
);
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;
}
}
}
}
}
}
}
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,
}