2
\$\begingroup\$

I need a little help with a formula to calculate the attack range for my turn-based strat game. Since it's a hexagon grid, I'm having trouble coming up with a formula that would pick the character range variable and calculate if an enemy object is in range. I'm using Game Maker Studio 2.3. My old script used to check like this:

var unity_attack_range = attacker.RNG;

var hex_dist = 90 * unity_attack_range;
with(defender)
{
    if (point_distance(defender.x, defender.y, attacker.x, attacker.y) <= hex_dist)
    {
        //attack code stuff
    }
}

As you can see, it multiplies the attacker range variable by 90 (hexagon width/2), and then it would just point the distance between the attacker and, if inside it, then you can attack. However, I noticed it makes a circle-shaped check after the attacker with the current formula, and it will include enemies from outside the supposed range.

The hexagon shape is 180 x 120, and the distance between each hexagon center is 90 in both axis.

I don't think it will be worth entering all positions to check, since for range = 5, it would be necessary 90 positions to check manually. I need ideas on how to make it work with maths, like Civ 6 does. Any ideas? Also, thanks for the attention!grid visualization on how supposed to work

\$\endgroup\$
1
  • \$\begingroup\$ This resource should help Hexagonal Grids. Its the definitive guide on hexagonal grids IMO. Be sure to check out the section on distances. \$\endgroup\$ May 17 at 17:51
1
\$\begingroup\$

You can achieve the desired result (if I interpreted your picture correctly) by replacing your point_distance function with something like this.

The function determines the number of steps that are required to go from hexagon (x1,y1) to hexagon (x2,y2). This works by first determining the number of diagonal steps (which decrease the X and Y distance simultaneously); then it computes the number of remaining horizontal or vertical steps and adds them to the total.

It expects coordinates to be in unit coordinates, like you marked them on your picture; so you should either use cell grid indices directly, which is preferred, or divide your coordinates by 90.

int hexagon_distance(int x1, int y1, int x2, int y2) {
    int x_distance = abs(x1 - x2);
    int y_distance = abs(y1 - y2);
    
    int diagonal_steps = min(x_distance, y_distance);
    
    int remaining_x_distance = x_distance - diagonal_steps;
    int remaining_y_distance = y_distance - diagonal_steps;
    
    if (remaining_x_distance > 0) {
        return (remaining_x_distance / 2) + diagonal_steps;
    } else {
        return remaining_y_distance + diagonal_steps;
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Hello! Thanks for your answer! I've been trying to put your code to work in my project, however, I'm having some difficults to understand where it gets the character range variable and how it checks if the selected enemy is within this range. Also, hexagon_distance is a variable with four values inside it? Sorry, I'm basically a newbie in coding, but again, thanks for your attention! \$\endgroup\$ May 17 at 1:07
  • \$\begingroup\$ hexagon_distance is a function, you give it the positions of your attacker and defender and it gives you back the distance between them - that is, the number of hexagons on the shortest path between attacker and defender. ("Distance" doesn't always have to be the euclidean distance, it can be defined differently too.) You can then compare the returned distance against the maximum distance, just like you did with point_distance. You will also have to translate the code into whatever programming language you're using because what I wrote is in C++. \$\endgroup\$ May 17 at 1:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.