feat: stage 2 collision, TileChangedEvent, path invalidation, rabbit digging
- Stage 2 collision: convoy skip when entities move same direction (dot>0.7), E/S yield rule for crossings, W/N right-of-way, head-on unchanged - TileChangedEvent (Message) + PathfindingDirtyChunks (Resource) in new tile_changed module - collect_pathfinding_dirty_chunks / invalidate_paths_on_tile_change / clear_pathfinding_dirty_chunks in PathfindingPlugin FixedUpdate chain - TileMap::remove_floor clears HashMap + ChunkData bitsets + tile_ids - RabbitDigTimer component: rabbits dig floor below every 5s, fires TileChangedEvent and TileOcclusionEvent for path invalidation + rendering
This commit is contained in:
@@ -1,44 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Component, Clone)]
|
||||
pub struct FloorTile {
|
||||
pub id: u32,
|
||||
pub opaque: bool,
|
||||
pub walkable: bool,
|
||||
pub astar_weight: u8,
|
||||
pub visible_range: [u32; 8],
|
||||
}
|
||||
|
||||
impl Default for FloorTile {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: 0,
|
||||
opaque: true,
|
||||
walkable: true,
|
||||
astar_weight: 0,
|
||||
visible_range: [0; 8],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Clone)]
|
||||
pub struct FixtureTile {
|
||||
pub id: u32,
|
||||
pub solid: bool,
|
||||
pub visible_range: [u32; 8],
|
||||
}
|
||||
|
||||
impl Default for FixtureTile {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: 0,
|
||||
solid: true,
|
||||
visible_range: [0; 8],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct TileState {
|
||||
pub timer: Timer,
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
pub mod benchmark;
|
||||
pub mod chunk_data;
|
||||
pub mod rendering;
|
||||
pub mod tile_changed;
|
||||
pub mod tilemap;
|
||||
pub mod tilemap_chunk;
|
||||
pub mod visibility;
|
||||
|
||||
pub use benchmark::*;
|
||||
pub use chunk_data::*;
|
||||
pub use tile_changed::*;
|
||||
pub use tilemap::*;
|
||||
pub use tilemap_chunk::*;
|
||||
pub use visibility::*;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//! Tile change events and pathfinding dirty chunk tracking.
|
||||
//!
|
||||
//! This module provides types for tracking tile modifications and
|
||||
//! invalidating pathfinding data when terrain changes.
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_platform::collections::HashSet;
|
||||
|
||||
#[derive(Message, Clone, Copy)]
|
||||
pub struct TileChangedEvent {
|
||||
pub pos: IVec3,
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct PathfindingDirtyChunks {
|
||||
pub chunks: HashSet<IVec2>,
|
||||
}
|
||||
@@ -198,6 +198,16 @@ impl TileMap {
|
||||
if let Some(chunk) = self.chunks.get_mut(&chunk_pos) {
|
||||
let (lx, ly, z) = ChunkData::world_to_local(pos);
|
||||
chunk.set_fixture_tile(lx, ly, z, tile.can_stand_in(), tile.can_stand_on());
|
||||
|
||||
// If fixture blocks entry, also clear the floor's stand_in bit at this position.
|
||||
// Air floor tiles exist at above-ground positions — without this, air's
|
||||
// can_stand_in=true would override the fixture block via the OR check.
|
||||
if !tile.can_stand_in() {
|
||||
let idx = ChunkData::pos_to_index(lx, ly, z);
|
||||
let word = idx / 32;
|
||||
let mask = !(1u32 << (idx % 32));
|
||||
chunk.stand_in_floor[word] &= mask;
|
||||
}
|
||||
}
|
||||
self.fixture_tiles.insert(pos, tile);
|
||||
}
|
||||
@@ -260,6 +270,24 @@ impl TileMap {
|
||||
removed
|
||||
}
|
||||
|
||||
/// Remove a floor tile, clearing the HashMap entry, ChunkData bitsets, and tile_ids.
|
||||
/// All three must be cleared — leaving ChunkData stale causes is_standable bugs,
|
||||
/// and leaving tile_ids non-zero causes the renderer to keep drawing the tile.
|
||||
pub fn remove_floor(&mut self, pos: &IVec3) -> Option<FloorTileData> {
|
||||
let removed = self.floor_tiles.remove(pos);
|
||||
let chunk_pos = world_to_chunk(*pos);
|
||||
if let Some(chunk) = self.chunks.get_mut(&chunk_pos) {
|
||||
let (lx, ly, z) = ChunkData::world_to_local(*pos);
|
||||
let idx = ChunkData::pos_to_index(lx, ly, z);
|
||||
let word = idx / 32;
|
||||
let clear_mask = !(1u32 << (idx % 32));
|
||||
chunk.stand_in_floor[word] &= clear_mask;
|
||||
chunk.stand_on_floor[word] &= clear_mask;
|
||||
chunk.tile_ids[idx] = 0;
|
||||
}
|
||||
removed
|
||||
}
|
||||
|
||||
/// Remove all tile data for a specific chunk from the TileMap.
|
||||
/// Iterates all positions in the chunk volume and removes from HashMaps.
|
||||
/// Used during chunk unloading to clean up tile data.
|
||||
|
||||
Reference in New Issue
Block a user