1
\$\begingroup\$

I'm still new to programming, and I was wondering if there is a way to make an irregular shape that displays how far a unit can move through the map taking in account pathing around obstacles. For example, as shown in the overworld of Total War:

Movement Being displayed in ground

I do not want to brute force it by checking every pixel that is in range as that's probably too slow to do in the game maker engine.

The pathing uses the mp_grid of game maker which I heard is A* (but I don't really know what that means or how it affects what I want to accomplish).

Is there a way to get a similar thing in a 2D space, but not necessarily as precise?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Is your challenge in determining which pixels / tiles the character can reach, or visually distinguishing that border on the screen? \$\endgroup\$
    – DMGregory
    Feb 10, 2018 at 4:12
  • \$\begingroup\$ I wish to distinguish them, because i can already limit the reach by comparing the lenght of the path to the maximum movement range, is only for quality of life, so the player doesnt need to guess where is the furthest point he/she can move to \$\endgroup\$
    – Dren
    Feb 10, 2018 at 4:48

1 Answer 1

1
\$\begingroup\$

After plenty of trial an error i came to get to the closest i could get to the desired result. I did indeed bruteforce it by checking the area around the player object whenever it entered the "Movement Phase", but i tried to optimize it to the best of my ability creating something that emulates the movement display of Total War, in a more rudamentary and imprecise way.

Comparison between Total War Movement vs Results

Maybe because Total War may have a more powerful engine and/or much more optimized algorithms, but this is the best i could get (because making it more precise may require a better engine or more math knowledge)

Here is the code i use to get the cordinates in order to draw the primitive.

//Basically this code works by checking the length of the path every 5 degrees
//And then checks from the max length of the radious inwards, and comparing
//the length of the path with the maximum movement range, if the length of
//the path is lower than the max range, then the cordinates are stored in two
//arrays (one for x, the other for y), else it will start decreasing the movement
//x and y goal cordinates of the path until the path lenght is equal or lower
//than the max range.(it cuts a lot of calculations by simply substracting
//the diference between the path length and the max range from the search radious
//This created some problems if the path was too long (because it will substrac to
//from the radious) so i conditioned it to only do that if the result of the substraction
//didn't made the the shorter than the max range + a threshold.
//so here are the variables


//m = the maximum range (usually called from the object that holds the stats
//search_maxrange = is basically m but easier to call
//search_x = Gets the cordinate X from the furthes point in the radious
//search_y = same but for Y
//origin_x = the point of origin of the radious origin_y = same but for Y
//border_x = array that stores the furthes point the path can get without being longer than max range
//border_y = same but for Y
//distance_lookout = stores the substranction of the difference between max range and 
//path length to the radious(used to check if the search radious inst being cut too much
//if not distance_lookout is used as the starting point of the search
//search_extended = is the search radious from where start looking if the path is
//longer than max range
// search_x_extended && search_y_extended = have the same porpouse as search_y
// and search_x, but for the extended search

{
var i;
distance_path = path_add();
for(i = 0; i < 72; i += 1)
{
search_maxrange = m;
search_x = origin_x + lengthdir_x(search_maxd,i*5)
search_y =  origin_y + lengthdir_y(search_maxd,i*5); 
mp_grid_path(grid,distance_path,origin_x,origin_y,origin_x + lengthdir_x(search_maxrange,i*5),origin_y + lengthdir_y(search_maxrange,i*5),true);
if path_get_length(distance_path) <= point_distance(origin_x,origin_y,search_x,search_y)
{
border_x[i] = search_x;
border_y[i] = search_y;
if border_x[i] < 0
{
    border_x[i] = 0;
}
if border_y[i] < 0
{
    border_y[i] = 0;
}
if border_x[i] > room_width
{
    border_x[i] = room_width;
}
if border_y[i] > room_height
{
    border_y[i] = room_height;
}
}
if path_get_length(distance_path) > search_maxrange
{
distance_lookout = (path_get_length(dpath) - (path_get_length(dpath) - search_maxd))
distance_lookout_path = path_add();
mp_grid_path(global.grid,dlpath,origin_x,origin_y,origin_x + lengthdir_x(distance_lookout,i*5),origin_y + lengthdir_y(distance_lookout,i*5),true)
if path_get_length(distance_lookout_path) < search_maxrange - 200
{
   search_extended = search_maxrange; 
}
if path_get_length(distance_lookout_path) > search_maxrange - 25
{
    search_extended = distance_lookout;
}
var c;
for (c = search_extended;c > 0;c -= 10 )
{        
    search_x_extended = origin_x + lengthdir_x(c,i*5);
    search_y_extended = origin_y + lengthdir_y(c,i*5);
    mp_grid_path(global.grid,distance_path,origin_x,origin_y,search_x_extended,search_y_extended,true);
    if path_get_length(distance_path) <= search_maxrange
    {
        border_x[i] = search_x_extended;
        border_y[i] = search_y_extended;
        if border_x[i] < 0
        {
            border_x[i] = 0;
        }
        if border_y[i] < 0
        {
            border_y[i] = 0;
        }
        if border_x[i] > room_width
        {
            border_x[i] = room_width;
        }
        if border_y[i] > room_height
        {
            border_y[i] = room_height;
        }
        break
    }
}
}
}
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .