Small tweaks and cleanup to flow field.
This commit is contained in:
+52
-3
@@ -185,7 +185,6 @@ check_map_collision :: proc(rect: rl.Rectangle, game_map: Game_Map) -> bool {
|
|||||||
|
|
||||||
// true when collision found
|
// true when collision found
|
||||||
check_enemy_collision :: proc(rect_a: rl.Rectangle, active_enemies: int, enemies: ^[MAX_ENEMIES]Enemy) -> bool {
|
check_enemy_collision :: proc(rect_a: rl.Rectangle, active_enemies: int, enemies: ^[MAX_ENEMIES]Enemy) -> bool {
|
||||||
|
|
||||||
for idx in 0..<active_enemies {
|
for idx in 0..<active_enemies {
|
||||||
e := enemies[idx]
|
e := enemies[idx]
|
||||||
enemy_rect := get_enemy_collider(e, e.position)
|
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) {
|
reset_cost_array :: proc(cost_arr: ^[400]int) {
|
||||||
for val, idx in cost_arr {
|
for val, idx in cost_arr {
|
||||||
cost_arr[idx] = -1
|
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
|
nx := current.x + loop_x
|
||||||
ny := current.y + loop_y
|
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)
|
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) {
|
compute_flow_directions :: proc(game_map: ^Game_Map) {
|
||||||
// walk every tile, look at neighbor costs in cost_field,
|
// walk every tile, look at neighbor costs in cost_field,
|
||||||
// write a direction vector into direction_field[index]
|
// 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
|
row := index / game_map.width
|
||||||
column := 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
|
// skip unreachable tiles
|
||||||
if game_map.cost_field[current_index] == -1 do continue
|
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)
|
cost_index := grid_to_index(ncolumn, nrow, game_map.width)
|
||||||
neighbor_cost := game_map.cost_field[cost_index]
|
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 {
|
if neighbor_cost != -1 && neighbor_cost < lowest_cost {
|
||||||
lowest_cost = neighbor_cost
|
lowest_cost = neighbor_cost
|
||||||
b = rl.Vector2{f32(ncolumn), f32(nrow)}
|
b = rl.Vector2{f32(ncolumn), f32(nrow)}
|
||||||
|
|||||||
Reference in New Issue
Block a user