From 424f2ccbf620ab993486d51fdb48c6c300d8fc1b Mon Sep 17 00:00:00 2001 From: Jason Hilder Date: Mon, 3 Aug 2026 06:41:31 +0200 Subject: [PATCH] Small tweaks and cleanup to flow field. --- src/map.odin | 55 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/map.odin b/src/map.odin index 94a865b..a67f9c7 100644 --- a/src/map.odin +++ b/src/map.odin @@ -185,7 +185,6 @@ check_map_collision :: proc(rect: rl.Rectangle, game_map: Game_Map) -> bool { // true when collision found check_enemy_collision :: proc(rect_a: rl.Rectangle, active_enemies: int, enemies: ^[MAX_ENEMIES]Enemy) -> bool { - for idx in 0..= 0 && flank_a.x < game_map.width && flank_a.y >= 0 && flank_a.y < game_map.height && + flank_b.x >= 0 && flank_b.x < game_map.width && flank_b.y >= 0 && flank_b.y < game_map.height { + flank_a_idx := grid_to_index(flank_a.x, flank_a.y, game_map.width) + flank_b_idx := grid_to_index(flank_b.x, flank_b.y, game_map.width) + flank_a_tile := Tile_Type(game_map.data[flank_a_idx]) + flank_b_tile := Tile_Type(game_map.data[flank_b_idx]) + if tile_defs[flank_a_tile].solid || tile_defs[flank_b_tile].solid { + continue // corner-cutting diagonal, don't expand BFS through it + } + } + } + get_neighbor_cost({nx, ny}, &flow_field_queue, game_map, current_cost) } } @@ -277,10 +298,11 @@ get_neighbor_cost :: proc(grid_pos: Grid_Pos, queue: ^[dynamic]Grid_Pos, game_ma compute_flow_directions :: proc(game_map: ^Game_Map) { // walk every tile, look at neighbor costs in cost_field, // write a direction vector into direction_field[index] - for value, index in game_map.data { + for _, index in game_map.data { row := index / game_map.width column := index % game_map.width - current_index := grid_to_index(column, row, game_map.width) + // current_index := grid_to_index(column, row, game_map.width) + current_index := index // skip unreachable tiles if game_map.cost_field[current_index] == -1 do continue @@ -306,6 +328,33 @@ compute_flow_directions :: proc(game_map: ^Game_Map) { cost_index := grid_to_index(ncolumn, nrow, game_map.width) neighbor_cost := game_map.cost_field[cost_index] + // we have the lowest neighbor at this point. + // Check if its diagonal first + // compare the neighbor to the current tile to check the diff, it will tell if diagonal + // Diagonal moves cut through a "corner" formed by two orthogonal tiles. + // Before allowing one, check both flank tiles (the up/down one + the left/right one). + // If either is solid, the diagonal is blocked — even if the target tile itself is open. + if ncolumn - column != 0 && nrow - row != 0 { + // no axis is 0 so we have an angle + // diagonal — check the two flanking orthogonal neighbors + flank_a_col := column + (ncolumn - column) // same x-offset, y unchanged + flank_a_row := row + flank_b_col := column + flank_b_row := row + (nrow - row) // same y-offset, x unchanged + + flank_a_idx := grid_to_index(flank_a_col, flank_a_row, game_map.width) + flank_b_idx := grid_to_index(flank_b_col, flank_b_row, game_map.width) + + flank_a_tile := Tile_Type(game_map.data[flank_a_idx]) + flank_b_tile := Tile_Type(game_map.data[flank_b_idx]) + + if tile_defs[flank_a_tile].solid || tile_defs[flank_b_tile].solid { + // corner-cutting diagonal, disqualify — skip to next neighbor in the loop + continue + } + + } + if neighbor_cost != -1 && neighbor_cost < lowest_cost { lowest_cost = neighbor_cost b = rl.Vector2{f32(ncolumn), f32(nrow)}