Small tweaks and cleanup to flow field.

This commit is contained in:
2026-08-03 06:41:31 +02:00
parent c1f481dd82
commit 424f2ccbf6
+52 -3
View File
@@ -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..<active_enemies {
e := enemies[idx]
enemy_rect := get_enemy_collider(e, e.position)
@@ -222,6 +221,9 @@ draw_map :: proc(current_map: Game_Map) {
}
}
// ----------------------------------------------------------
// FLOW FIELD IMPL
// ----------------------------------------------------------
reset_cost_array :: proc(cost_arr: ^[400]int) {
for val, idx in cost_arr {
cost_arr[idx] = -1
@@ -253,6 +255,25 @@ compute_flow_field :: proc(game_map: ^Game_Map, player_pos: rl.Vector2) {
nx := current.x + loop_x
ny := current.y + loop_y
// diagonal — check flanking orthogonal tiles before allowing expansion
if loop_x != 0 && loop_y != 0 {
flank_a := Grid_Pos{current.x + loop_x, current.y}
flank_b := Grid_Pos{current.x, current.y + loop_y}
// @TODO VISUALIZE + UNDERSTAND THIS CONCEPTUALLY
if flank_a.x >= 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)}