Difference between revisions of "LUA 2d Line of sight"

From RogueBasin
Jump to navigation Jump to search
(added LUA 2d LOS code article)
 
 
(8 intermediate revisions by one other user not shown)
Line 2: Line 2:


http://www.gamedev.net/reference/articles/article1275.asp code by Tom Ootjers
http://www.gamedev.net/reference/articles/article1275.asp code by Tom Ootjers
It returns true if x1,y1 can "see" x2,y2 without "blockage" in the "line of sight" and "false" if otherwise, so in your LUA code it can be used like:
if funcs.lineofsight(x1,y1) then (draw the creature or shoot the arrow or whatever) end along with your other checks for the action.


I made it go "one round further" when LOS was blocked, so my engine would draw the trees and monsters even though they blocked los.
I made it go "one round further" when LOS was blocked, so my engine would draw the trees and monsters even though they blocked los.


The many comments are his, also.  Credit goes to him basically. I got it to work on for roguelikes though.
The many comments are his, also.  Credit goes to him basically.
 


function funcs.lineofsight(x1,y1,x2,y2)
function funcs.lineofsight(x1,y1,x2,y2)
Line 23: Line 28:
if (x2 >= x1) then              --  // The x-values are increasing
if (x2 >= x1) then              --  // The x-values are increasing


  xinc1 = 1;
xinc1 = 1;


  xinc2 = 1;
xinc2 = 1;


else                        -- // The x-values are decreasing
else                        -- // The x-values are decreasing


  xinc1 = -1;
xinc1 = -1;


  xinc2 = -1
xinc2 = -1


end
end
Line 39: Line 44:
if (y2 >= y1) then            --    // The y-values are increasing
if (y2 >= y1) then            --    // The y-values are increasing


  yinc1 = 1;
yinc1 = 1;


  yinc2 = 1;
yinc2 = 1;


else                        --  // The y-values are decreasing
else                        --  // The y-values are decreasing


  yinc1 = -1;
yinc1 = -1;


  yinc2 = -1;
yinc2 = -1;


end
end
Line 55: Line 60:
if (deltax >= deltay) then      --  // There is at least one x-value for every y-value
if (deltax >= deltay) then      --  // There is at least one x-value for every y-value


  xinc1 = 0;              --  // Don't change the x when numerator >= denominator
xinc1 = 0;              --  // Don't change the x when numerator >= denominator


  yinc2 = 0;              --    // Don't change the y for every iteration
yinc2 = 0;              --    // Don't change the y for every iteration


  den = deltax;
den = deltax;


  num = deltax / 2;
num = deltax / 2;


  numadd = deltay;
numadd = deltay;


  numpixels = deltax;      --  // There are more x-values than y-values
numpixels = deltax;      --  // There are more x-values than y-values


else                        --  // There is at least one y-value for every x-value
else                        --  // There is at least one y-value for every x-value


  xinc2 = 0;                --  // Don't change the x for every iteration
xinc2 = 0;                --  // Don't change the x for every iteration


  yinc1 = 0;                --  // Don't change the y when numerator >= denominator
yinc1 = 0;                --  // Don't change the y when numerator >= denominator


  den = deltay;
den = deltay;


  num = deltay / 2;
num = deltay / 2;


  numadd = deltax;
numadd = deltax;


  numpixels = deltay;      --  // There are more y-values than x-values
numpixels = deltay;      --  // There are more y-values than x-values


end
end
Line 89: Line 94:
while (true) do
while (true) do


roundnum = roundnum + 1 --forces two distance sight
roundnum = roundnum + 1 --forces two distance sight


             --  // Draw the current pixel
             --  // Draw the current pixel


if onemoreround == 1 and roundnum > 2 then return false end --this stuff is so it penetrates one round and doesnt stop on  
if onemoreround == 1 and roundnum > 2 then return false end --this stuff is so it penetrates one round and doesnt stop on  
the first round
the first round


if (roundnum ~= 1) and funcs.checkforlosblock(x,y) then onemoreround = 1 end --was return false
if (roundnum ~= 1) and funcs.checkforlosblock(x,y) then onemoreround = 1 end --was return false


if x == x2 and y == y2 then return true end
if x == x2 and y == y2 then return true end




Line 104: Line 109:




num = num + numadd;              --// Increase the numerator by the top of the fraction
num = num + numadd;              --// Increase the numerator by the top of the fraction


  if (num >= den) then          --  // Check if numerator >= denominator
if (num >= den) then          --  // Check if numerator >= denominator


    num = num - den;            --  // Calculate the new numerator value
num = num - den;            --  // Calculate the new numerator value


    x = x +xinc1;            --  // Change the x as appropriate
x = x +xinc1;            --  // Change the x as appropriate


    y = y+ yinc1;            --  // Change the y as appropriate
y = y+ yinc1;            --  // Change the y as appropriate


  end
end


  x = x+xinc2;              --  // Change the x as appropriate
x = x+xinc2;              --  // Change the x as appropriate


  y = y+yinc2;              --  // Change the y as appropriate
y = y+yinc2;              --  // Change the y as appropriate


end
end
Line 127: Line 132:
-------------------------------------------------
-------------------------------------------------
function funcs.checkforlosblock(x,y)
function funcs.checkforlosblock(x,y)
          --enter your own checks here to see if the square is has any objects that would block LOS like trees, etc.  Those objects should just have "block_los" = true. Return true if square is blocked, false if its clear.
--enter your own checks here to see if the square is has any objects that would block LOS like trees, etc.  Those objects should just have "block_los" = true. Return true if square is blocked, false if its clear.
------------------------------------------------------------
------------------------------------------------------------
By [[User:Rustle]]
By [[User:Rustle]]
[[Category:Developing]]

Latest revision as of 10:41, 25 October 2012

Hi, I adapted this function to suit my roguelike from:

http://www.gamedev.net/reference/articles/article1275.asp code by Tom Ootjers

It returns true if x1,y1 can "see" x2,y2 without "blockage" in the "line of sight" and "false" if otherwise, so in your LUA code it can be used like:

if funcs.lineofsight(x1,y1) then (draw the creature or shoot the arrow or whatever) end along with your other checks for the action.

I made it go "one round further" when LOS was blocked, so my engine would draw the trees and monsters even though they blocked los.

The many comments are his, also. Credit goes to him basically.


function funcs.lineofsight(x1,y1,x2,y2)

local math = math

local deltax = math.abs(x2 - x1) -- // The difference between the x's

local deltay = math.abs(y2 - y1) -- // The difference between the y's

local x = x1; -- // Start x off at the first pixel

local y = y1; -- // Start y off at the first pixel

local xinc1,xinc2,yinc1,yinc2

if (x2 >= x1) then -- // The x-values are increasing

xinc1 = 1;

xinc2 = 1;

else -- // The x-values are decreasing

xinc1 = -1;

xinc2 = -1

end


if (y2 >= y1) then -- // The y-values are increasing

yinc1 = 1;

yinc2 = 1;

else -- // The y-values are decreasing

yinc1 = -1;

yinc2 = -1;

end


if (deltax >= deltay) then -- // There is at least one x-value for every y-value

xinc1 = 0; -- // Don't change the x when numerator >= denominator

yinc2 = 0; -- // Don't change the y for every iteration

den = deltax;

num = deltax / 2;

numadd = deltay;

numpixels = deltax; -- // There are more x-values than y-values

else -- // There is at least one y-value for every x-value

xinc2 = 0; -- // Don't change the x for every iteration

yinc1 = 0; -- // Don't change the y when numerator >= denominator

den = deltay;

num = deltay / 2;

numadd = deltax;

numpixels = deltay; -- // There are more y-values than x-values

end

local onemoreround = 0

local roundnum = 0

while (true) do

roundnum = roundnum + 1 --forces two distance sight

           --  // Draw the current pixel

if onemoreround == 1 and roundnum > 2 then return false end --this stuff is so it penetrates one round and doesnt stop on the first round

if (roundnum ~= 1) and funcs.checkforlosblock(x,y) then onemoreround = 1 end --was return false

if x == x2 and y == y2 then return true end



num = num + numadd; --// Increase the numerator by the top of the fraction

if (num >= den) then -- // Check if numerator >= denominator

num = num - den; -- // Calculate the new numerator value

x = x +xinc1; -- // Change the x as appropriate

y = y+ yinc1; -- // Change the y as appropriate

end

x = x+xinc2; -- // Change the x as appropriate

y = y+yinc2; -- // Change the y as appropriate

end

end



function funcs.checkforlosblock(x,y) --enter your own checks here to see if the square is has any objects that would block LOS like trees, etc. Those objects should just have "block_los" = true. Return true if square is blocked, false if its clear.


By User:Rustle