0

Example image: http://ericsartor.ca/Untitled2.gif

I'm making a game based on a grid system. For the battle system, I'm trying to figure out if a shot is blocked by checking all the squares in it's path to see if they are considered "obstacles". I'd need to be able to provide a start and end x,y coordinate, then loop through all the squares that the line between those points would pass through, as in the image. The formula would need to return x,y coordinates for each square in the path. I could iterate over it multiple times if necessary. I've been trying really hard to figure it out on my own, but I can't identify a clear pattern or consistency that I could use to make a formula. Could someone help? Thanks :)

1 Answers1

0

I believe I have a solution for you. Suppose the grid is defined by all lines parallel to the $y$-axis through the points $\{x_k = a + k\Delta x\,:\,k \in \mathbb{Z}\}$ and all lines parallel to the $x$-axis through the points $\{y_j = b + j\Delta y\,:\,j\in\mathbb{Z}\}$. Further suppose the line extends from $(x_s,y_s)$ to $(x_e,y_e)$. The following pseudocode outlines the algorithm. At its conclusion the array $P$ contains a list of index pairs $(k,j)$ that index the bottom left corner of the rectangle with vertices $(x_k,y_j)$, $(x_k,y_j + \Delta y)$, $(x_k + \Delta x, y_j)$, $(x_k+\Delta x,y_j + \Delta y)$ that contains a portion of the line.

rtol = macheps
atol = 1e-14
k = floor((xs - a)/dx)
j = floor((ys - b)/dy)
ke = floor((xe - a)/dx)
je = floor((ye - b)/dy)
x = a + k*dx
y = a + j*dy
tcurr = 0
Add the pair (k,j) to an empty array P
while (k does not equal ke or j does not equal je) do 
    tmin = 2
    if (xe does not equal xs) then
        tol = rtol*|x| + atol
        t = (x + dx + tol - xs)/(xe - xs)
        if (tcurr < t and t <= 1) then
            tmin = min(tmin, t)
        end
        t = (x - xs - tol)/(xe - xs)
        if (tcurr < t and t <= 1) then
            tmin = min(tmin, t)
        end
    end
    if (ye does not equal ys) then
        tol = rtol*|y| + atol
        t = (y + dy + tol - ys)/(ye - ys)
        if (tcurr < t and t <= 1) then
            tmin = min(tmin, t)
        end
        t = (y - ys - tol)/(ye - ys)
        if (tcurr < t and t <= 1) then
            tmin = min(tmin, t)
        end
    end
    if (tmin is 2) then // should only be possible at the end of the line
        Add the pair (ke,je) to the array P
        break from the loop
    end
    tcurr = tmin
    k = floor((xs + tmin*(xe - xs) - a)/dx)
    j = floor((ys + tmin*(ye - ys) - b)/dy)
    Add the pair (k,j) to the array P
    x = a + k*dx
    y = b + j*dy
end

This algorithm may have to be tweaked depending on how you want to handle edge cases such as when the line passes through grid points.

K. Miller
  • 4,688
  • So I've been going through this, as I am not a mathematician, and I think I understand most of it, with help from google. But I'm just confused as to how the variables a and b are defined in the psuedocode, and I don't know where the k and j come from in your equations in the top part. – Eric David Sartor Oct 20 '16 at 18:34
  • The variables $a$ and $b$ simply define how the grid is shifted relative to the $x$- and $y$-axis. Now that I think of it, they are probably not necessary, so you can just set them to zero. – K. Miller Oct 20 '16 at 19:00
  • Just wondering how to define macheps. Looking it up online said it was Machine Epsilon and is essentially just rounding a number up or down (based on wikipedia) which doesn't seem to help when we don't have values to plug into it. Thank you for all your help! – Eric David Sartor Oct 20 '16 at 20:08
  • The programming language you are using should have a function that returns machine epsilon for the specific variable type you are using. – K. Miller Oct 20 '16 at 21:29
  • So I've got a macheps value for JavaScript (Number.MIN_VALUE). I've completely written out the code for this formula, but it isn't working. I keep getting an array back that it [[0, 0], [1, 1]] when inputting the start as [0, 0] and the end as [4, 5]. I've uploaded it to my site, http://www.ericsartor.ca/line.htm . Could you maybe go over the code I wrote and confirm it makes sense? You can also test the function by going to the console (F12) and typing "line(xs, ys, xe, ye)" to run it. – Eric David Sartor Oct 20 '16 at 21:49
  • I should mention to see the source code, you can right click and hit View Source. I've copied your formula verbatim, other than the necessary JavaScript functions. – Eric David Sartor Oct 20 '16 at 21:52
  • Please use Number.EPSILON instead. Number.MIN_VALUE is the minimum representable positive numeric value. Also, there is an issue with the link you sent me to your site. – K. Miller Oct 20 '16 at 23:19