fix(pathfinding): correct BinaryHeap ordering and movement threshold
- Fix PathNode and ChunkPathNode Ord impl to use correct min-heap ordering (self.f_score.cmp vs other.f_score.cmp) - was causing zig-zag paths - Fix movement threshold formula to use tile_weight directly (walk_speed * tile_weight / 50) instead of inverted multiplier - Update comments to reflect 'higher = slower to traverse' semantics
This commit is contained in:
@@ -155,10 +155,9 @@ struct PathNode {
|
|||||||
|
|
||||||
impl Ord for PathNode {
|
impl Ord for PathNode {
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
other
|
self.f_score
|
||||||
.f_score
|
.cmp(&other.f_score)
|
||||||
.cmp(&self.f_score)
|
.then_with(|| self.g_score.cmp(&other.g_score))
|
||||||
.then_with(|| other.g_score.cmp(&self.g_score))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,8 +507,7 @@ pub fn movement(mut query: Query<(&mut Ambulatory, &mut Transform)>, tilemap: Re
|
|||||||
|
|
||||||
if ambulatory.walk_speed > 0. {
|
if ambulatory.walk_speed > 0. {
|
||||||
let tile_weight = get_tile_weight(&tilemap, current_pos.as_ivec3());
|
let tile_weight = get_tile_weight(&tilemap, current_pos.as_ivec3());
|
||||||
let speed_multiplier = (tile_weight as f32) / 50.0;
|
let threshold = (ambulatory.walk_speed as i32 * tile_weight as i32 / 50) as u32;
|
||||||
let threshold = (ambulatory.walk_speed * speed_multiplier) as u32;
|
|
||||||
|
|
||||||
if ambulatory.step_recovery <= threshold {
|
if ambulatory.step_recovery <= threshold {
|
||||||
ambulatory.step_recovery += 1;
|
ambulatory.step_recovery += 1;
|
||||||
@@ -557,7 +555,7 @@ fn is_standable_tile(tilemap: &TileMap, pos: IVec3) -> bool {
|
|||||||
tilemap.is_standable(pos)
|
tilemap.is_standable(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the A* weight for a tile position. Lower is better (faster to traverse).
|
/// Get the A* weight for a tile position. Higher = slower to traverse.
|
||||||
/// Returns 100 (default) if tile not found.
|
/// Returns 100 (default) if tile not found.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_tile_weight(tilemap: &TileMap, pos: IVec3) -> u8 {
|
fn get_tile_weight(tilemap: &TileMap, pos: IVec3) -> u8 {
|
||||||
@@ -566,7 +564,7 @@ fn get_tile_weight(tilemap: &TileMap, pos: IVec3) -> u8 {
|
|||||||
|
|
||||||
/// Calculate movement cost including tile weight.
|
/// Calculate movement cost including tile weight.
|
||||||
/// Base costs: cardinal=10, diagonal=14, vertical~50.
|
/// Base costs: cardinal=10, diagonal=14, vertical~50.
|
||||||
/// Tile weight adds: (weight - 50) / 5 to make heavier tiles more costly.
|
/// Tile weight adds: (weight - 50) / 5 to make higher-weight tiles more costly.
|
||||||
fn calculate_movement_cost(move_dir: IVec3, tile_weight: u8) -> i32 {
|
fn calculate_movement_cost(move_dir: IVec3, tile_weight: u8) -> i32 {
|
||||||
let base_cost = match (
|
let base_cost = match (
|
||||||
move_dir.x.abs() / ITILE_SIZE,
|
move_dir.x.abs() / ITILE_SIZE,
|
||||||
@@ -851,10 +849,9 @@ impl PartialEq for ChunkPathNode {
|
|||||||
|
|
||||||
impl Ord for ChunkPathNode {
|
impl Ord for ChunkPathNode {
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
other
|
self.f_score
|
||||||
.f_score
|
.cmp(&other.f_score)
|
||||||
.cmp(&self.f_score)
|
.then_with(|| self.g_score.cmp(&other.g_score))
|
||||||
.then_with(|| other.g_score.cmp(&self.g_score))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user