L
lindens
Guest
I've been developing a flow field for some time now and i'm running out of optimization ideas. Currently, it's just too slow for use in an actual game. I am using buffers, accessors, and making sure my scripts are as lightweight as possible. I already know about separating the map into several heat-maps but i want to be sure that generating the heat-map (in general) is as efficient as possible.
The data structures i use for the generation:
Initially i was using ds_grids instead of the buffer but apparently buffers are faster so i had to try it.
I only generate the entire flowfield when the player moves to another location in the grid.
I start by clearing the heat-map to zeroes, ignoring walls, which is actually very fast.
Then i make the heat-map using the breadth first search algorithm:
I will post my flow-field script if i get some replies. I just need someone to tell me if i'm doing something wrong yet
Ask if anything is unclear, or you would like to see a screenshot of my current implementation
I have referred to these many times to aid me if anyone is interested:
Goal-Based Vector Field Pathfinding
Flow Field Pathfinding
Amazing PDF on the subject (I will be attempting to implement some concepts from here)
The data structures i use for the generation:
Code:
grid_width = room_width div cell_size;
grid_height = room_height div cell_size;
buffer_size = grid_width * grid_height; // 680 cells
heatmap = buffer_create(buffer_size, buffer_fast, 1); // used as a 1D array holding heatmap cell costs
heatmap_q = ds_queue_create(); // used by the heatmap for breadth first search algo
flowfield = buffer_create(buffer_size, buffer_fast, 1); // used as a 1D array holding flowfield directions
Initially i was using ds_grids instead of the buffer but apparently buffers are faster so i had to try it.
I only generate the entire flowfield when the player moves to another location in the grid.
I start by clearing the heat-map to zeroes, ignoring walls, which is actually very fast.
Then i make the heat-map using the breadth first search algorithm:
Code:
/// Calculates the heatmap using breadth first search algorithm
var target = argument0; // the center, or 0 cost position, of the heatmap
ds_queue_enqueue(heatmap_q, target);
while (ds_queue_size(heatmap_q) > 0) {
var c_cell = ds_queue_dequeue(heatmap_q); // dequeue the next cell, make it the current cell
var c_index = (c_cell[@ 1] * grid_width) + c_cell[@ 0]; // convert 2d coordinate to index for buffer
var c_cell_cost = buffer_peek(heatmap, c_index, buffer_u8); // get the current cell's cost from the target
var nb_list = get_neighbours(c_cell[@ 0], c_cell[@ 1]); // get adjacent cell coordinates (top, bot, left, right)
// iterate through the neighbouring cells
for (var i = 0; i <= 3; i++) {
// convert the 2D neighbour coordinate into an index for buffer
var nb_index = (nb_list[@ i, 1] * grid_width) + nb_list[@ i, 0];
// if the neighbour's cell cost is 0 (meaning not a wall and not already assigned a value)
if (buffer_peek(heatmap, nb_index, buffer_u8) == 0) {
// set the current neighbour's cell to the current cell's cost + 1
buffer_poke(heatmap, nb_index, buffer_u8, c_cell_cost + 1);
// put the current neighbour's position (x, y) into the heatmap queue
ds_queue_enqueue(heatmap_q, vec(nb_list[@ i, 0], nb_list[@ i, 1]));
}
}
}
// set target's position to 0 since it gets set to 2 for some reason
// (does not affect functionality, maybe performance very slightly)
var target_index = (target[@ 1] * grid_width) + target[@ 0];
buffer_poke(heatmap, target_index, buffer_u8, 0);
I will post my flow-field script if i get some replies. I just need someone to tell me if i'm doing something wrong yet
Ask if anything is unclear, or you would like to see a screenshot of my current implementation
I have referred to these many times to aid me if anyone is interested:
Goal-Based Vector Field Pathfinding
Flow Field Pathfinding
Amazing PDF on the subject (I will be attempting to implement some concepts from here)