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,19 +1,44 @@
|
||||
use crate::config::GameConfig;
|
||||
use crate::constants::ITILE_SIZE;
|
||||
use crate::constants::TILE_SIZE;
|
||||
use crate::constants::*;
|
||||
use crate::entities::shared_components::Ambulatory;
|
||||
use crate::game::SpawnDelay;
|
||||
use crate::world::tiles::visibility::TileOcclusionEvent;
|
||||
use crate::world::tiles::{TileChangedEvent, TileMap};
|
||||
use crate::world::VisibleGameEntity;
|
||||
use bevy::prelude::*;
|
||||
use bevy_rand::prelude::*;
|
||||
use rand::RngExt;
|
||||
|
||||
/// How often (in seconds) a rabbit digs.
|
||||
/// 5 seconds at normal speed — slow enough to observe, fast enough to test.
|
||||
pub const DIG_INTERVAL_SECS: f32 = 5.0;
|
||||
|
||||
/// Tracks time until next dig action. Debug component — rabbits dig to demonstrate
|
||||
/// the TileChangedEvent + path invalidation pipeline. Remove or replace when
|
||||
/// real digging mechanics are implemented.
|
||||
#[derive(Component)]
|
||||
pub struct RabbitDigTimer {
|
||||
/// Seconds remaining until next dig. Reset to DIG_INTERVAL_SECS after each dig.
|
||||
pub secs_remaining: f32,
|
||||
}
|
||||
|
||||
impl Default for RabbitDigTimer {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
secs_remaining: DIG_INTERVAL_SECS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct Rabbit {
|
||||
ambulatory: Ambulatory,
|
||||
sprite: Sprite,
|
||||
transform: Transform,
|
||||
visibility: Visibility,
|
||||
dig_timer: RabbitDigTimer,
|
||||
}
|
||||
|
||||
impl Rabbit {
|
||||
@@ -36,6 +61,7 @@ impl Rabbit {
|
||||
},
|
||||
transform: Transform::from_translation(position).with_scale(Vec3::splat(PIXEL_RATIO)),
|
||||
visibility: Visibility::Hidden,
|
||||
dig_timer: RabbitDigTimer::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,3 +103,34 @@ pub fn spawn_rabbits(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Debug system: rabbits periodically dig the floor tile beneath them.
|
||||
///
|
||||
/// Removes the FloorTileData at the tile directly below the rabbit's current
|
||||
/// z-level. Also clears the corresponding ChunkData bits via TileMap::remove_floor.
|
||||
/// Fires TileChangedEvent so path invalidation reacts automatically.
|
||||
pub fn rabbit_dig_system(
|
||||
mut query: Query<(&Transform, &mut RabbitDigTimer)>,
|
||||
mut tilemap: ResMut<TileMap>,
|
||||
mut tile_changed: MessageWriter<TileChangedEvent>,
|
||||
mut occlusion: MessageWriter<TileOcclusionEvent>,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
for (transform, mut dig_timer) in query.iter_mut() {
|
||||
dig_timer.secs_remaining -= time.delta_secs();
|
||||
if dig_timer.secs_remaining > 0.0 {
|
||||
continue;
|
||||
}
|
||||
dig_timer.secs_remaining = DIG_INTERVAL_SECS;
|
||||
|
||||
let entity_pos = transform.translation.as_ivec3();
|
||||
let below_pos = IVec3::new(entity_pos.x, entity_pos.y, entity_pos.z - ITILE_SIZE);
|
||||
|
||||
if tilemap.remove_floor(&below_pos).is_some() {
|
||||
tile_changed.write(TileChangedEvent { pos: below_pos });
|
||||
occlusion.write(TileOcclusionEvent {
|
||||
tile_position: below_pos,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user