Recently, I’ve been asked twice about how to check if there’s something obstructing the path from (x1;y1) to (x2;y2). Here I’ll provide two implementations equally useful – to check if there’s something obstructing the way for a player (wall or obstale) and to check if there’s something obstructing the way for a bullet (wall).

First, let’s use our handy function for moving objects forward (refer to this post). As will be demonstrated next, it’s not only used for that.

So, we inserted the function into the code – now let’s do the functions that check for obstructions.

[lua]

function checkfreepath(x1,y1,x2,y2)

local rot=-math.deg(math.atan2(x1-x2,y1-y2))

local cx,cy=x1,y1

while math.floor(cx/32)<=math.floor(x2/32) and math.floor(cy/32)<=math.floor(y2/32) do

if not tile(math.floor(cx/32),math.floor(cy/32),’walkable’) then

return false

end

cx,cy=angledir(rot,cx,cy,32)

end

return true

end

[/lua]

The function **checkfreepath** checks if the path for a player is free. It takes in four arguments – **x1** and **y1** are the coordinates of the initial position, and **x2** and **y2** are the coordinates of the terminal position.

It functions following this algorithm:

- Find the angle between the two positions
- Declare local variables for current X and Y
- Run a while loop to execute code while the current X and Y being checked aren’t beyond where we want it to check
- Check if the tile being checked is walkable – if it’s not, we end the function and return
**false** - Move the current position checked by 32 pixels (1 tile) forward
- If the function hasn’t ended already – meaning the path is free – return
**true**

Pros and cons:

- Pro: the while loop checks for floored positions divided by 32 and the angledir function moves the current position by 32 to increase efficiency
- Con: the function accepts pixels as the coordinate measurement – with tiles supplied the function will not work

Knowing the big turndown of our function, we could make it versatile, adding a fifth argument being the mode of the function. The code would look like so:

[lua highlight=”2,3,6,7,10″]

function checkfreepath(x1,y1,x2,y2,tiles)

local f=1

if tiles then f=32 end

local rot=-math.deg(math.atan2(x1-x2,y1-y2))

local cx,cy=x1,y1

while math.floor(cx/f)<=math.floor(x2/f) and math.floor(cy/f)<=math.floor(y2/f) do

if not tile(math.floor(cx/f),math.floor(cy/f),’walkable’) then

return false

end

cx,cy=angledir(rot,cx,cy,f)

end

return true

end

[/lua]

As you can see, there are new lines as well as some minor changes on the highlighted lines. The factor now isn’t 32 – it’s **f**, which is a local variable we declared on line 2. On line 3, we check if tiles is specified – if the tiles argument is anything except nil and false, the factor automatically sets to 1, which means the measurement is tiles. Otherwise, the factor is set to 32, and the measurement becomes pixels.

Good luck!

This really could be improved.

Take the following (untested) code:

http://www.cs2dinfo.com.ar/pastebin/index.php/view/45218860

It drastically reduces the number of iterations

(x1-x2)^2+(y1-y2)^2)^0.5 iterations vs math.max(x1-x2, y1-y2) iterations

Remember that the hypotenuse is always greater than any of the cathetus.

Moreover, it avoids using expensive functions such as sin() and cos()

Of course, this method could have failed in cases where the path would be a vertical line, so I made it able to “invert” itself in those cases. When the vertical vector would be bigger than the horizontal one it should invert too to avoid missing any pixels that could be inside a tile.