Login [Register]
Don't have an account? Register now to chat, post, use our tools, and much more.
Okay, I am trying to port this raycaster to the Prizm Lua for LuaZM. Here is my code so far:


Code:
--Raycasting script
--Based On James Carmack Method
--Thx to http://student.kuleuven.be/~m0216922/CG/raycasting.html Tutorial
--Thx to Jdourlens (http://jdourlens.fr.nf)

function makecolor(r,g,b) 
    return bit32.lshift(bit32.rshift(r,3),11)+bit32.lshift(bit32.rshift(g,2),5)+bit32.rshift(b,3) 
end 
--Define first Map Features in a table
map = {
width = 10,
height = 10,
--mapping decor : 1 = Wall, 0 = No Wall
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,1,1,1,1,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,1,0,0,0,0,0,0,1,1},
{1,0,0,0,1,0,1,0,0,1},
{1,0,0,0,1,0,1,0,0,1},
{1,0,0,0,1,0,1,0,0,1},
{1,0,0,1,1,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1},
}

--Player's Starting Position
posx = 2
posy = 3

--Initial Directior Vector, Plane Setting and Time Settings
dirx = 1
diry = 0
planex = 0
planey = 0.66

move = 1
rotation = 0.1
direction = 1

timer = 0
oldtime = 0

--screen Dimensions
screenx = 384
screeny = 216

while true do
zmg.clear()

   x=0
   for x = 0,screenx do
   camx = 2*x/screenx - 1
   rayposx = posx
   rayposy = posy
   raydirx = dirx + planex*camx
   raydiry = diry + planey*camx

   mapx = rayposx
   mapy = rayposy

   sidedistx = 0
   sidedisty = 0

   deltadistx = math.sqrt(1+(raydiry*raydiry)/(raydirx*raydirx))
   deltadisty = math.sqrt(1+(raydirx*raydirx)/(raydiry*raydiry))
   perp = 0

   stepx = 0
   stepy = 0
   hit = 0
   side = 0

      if raydirx < 0 then
      stepx = -1
      sidedistx = (rayposx - mapx)*deltadistx
      else stepx = 1
      sidedistx = (mapx + 1 - rayposx)*deltadistx end

      if raydiry < 0 then
      stepy = -1
      sidedisty = (rayposy - mapy)*deltadisty
      else stepy = 1
      sidedisty = (mapy + 1 - rayposy)*deltadisty end

      while hit == 0 do
         if sidedistx < sidedisty then
         sidedistx = sidedistx + deltadistx
         mapx = mapx + stepx
         side = 0
         else
         sidedisty = sidedisty + deltadisty
         mapy = mapy + stepy
         side = 1
         end
         
         if map[mapx][mapy] > 0 then hit = 1 end
      end
      
      if side == 0 then
      perp = math.abs((mapx - rayposx + (1-stepx)/2)/raydirx)
      else perp = math.abs((mapy - rayposy + (1-stepy)/2)/raydiry)
      end
      
      lineheight = math.abs(screeny/perp)   
      
      draw = -lineheight/2 + screeny/2
      if draw < 0 then draw = 0 end
      drawE = lineheight/2 + screeny/2
      if drawE >= screenx then drawE = screenx - 1 end
      

       a = 65
       b = 58
       c = 63   
      colorRoof = makecolor(30, 70, 30)
      colorSky = makecolor(30, 70, 200)
      colorStripes = makecolor(70, 56, 90)
      if side == 1 then
      a = a-30
      b = b-30
      c = c-30
      end
      color = makecolor(a, b, c)
      bandUp = screeny/2+drawE
      bandDown = screeny/2+draw   
       zmg.drawRectFill(x, draw, 1, drawE, color);
       zmg.drawRectFill(x, drawE, 1, 272, colorRoof);
       zmg.drawRectFill(x, 0, 1, draw, colorSky);
       zmg.drawRectFill(x, bandUp/2, 1, 1,colorStripes)
       zmg.drawRectFill(x, bandDown/2, 1, 1,colorStripes)
       zmg.drawRectFill(x, screeny/2, 1, 1,colorStripes)
   end   
   

   
if zmg.keyMenuFast() == 28 then
if timer >= oldtime then
      if map[posx + dirx * move][posy] == 0 then posx = posx + dirx * move end
      if map[posx][posy + diry * move] == 0 then posy = posy + diry * move end
timer = 0
end
end

if zmg.keyMenuFast() == 37 then
if timer >= oldtime then
      if map[posx - dirx * move][posy] == 0 then posx = posx - dirx * move end
      if map[posx][posy - diry * move] == 0 then posy = posy - diry * move end
timer = 0
end
end
if zmg.keyMenuFast() == 38 then
if timer >= oldtime then
      --both camera direction and camera plane must be rotated
      oldDirX = dirx;
      dirx = dirx * math.cos(-rotation) - diry * math.sin(-rotation);
      diry = oldDirX * math.sin(-rotation) + diry * math.cos(-rotation);
      oldPlaneX = planex;
      planex = planex * math.cos(-rotation) - planey * math.sin(-rotation);
      planey = oldPlaneX * math.sin(-rotation) + planey * math.cos(-rotation);
direction = direction + 1
timer = 0
end
end
if zmg.keyMenuFast() == 27 then
if timer >= oldtime then
      --both camera direction and camera plane must be rotated
      oldDirX = dirx;
      dirx = dirx * math.cos(rotation) - diry * math.sin(rotation);
      diry = oldDirX * math.sin(rotation) + diry * math.cos(rotation);
      oldPlaneX = planex;
      planex = planex * math.cos(rotation) - planey * math.sin(rotation);
      planey = oldPlaneX * math.sin(rotation) + planey * math.cos(rotation);
direction = direction - 1
timer = 0
end
end
   

   
   
zmg.fastCopy()   
end


It works until I turn left or right. After that, when I press the forward button, it gives me this:


Code:
RaycastLua.lua:138: attempt to index field '?' (a nil value) stack traceback:
RaycastLua.lua:138: in main chunk
[C]: in function 'run'
stdin:1: in main chunk
[C]: in ?


Any suggestions?
As far as I can tell, line 138 is this:
Code:
      if map[posx + dirx * move][posy] == 0 then posx = posx + dirx * move end
Are you sure that map[][] is properly formatted?

Edit: It would have to be, if it can draw the initial screen. What about the fact that rows 0 and 1 of the map array are shorter than the rest? Or is that not the case?
KermMartian wrote:
As far as I can tell, line 138 is this:
Code:
      if map[posx + dirx * move][posy] == 0 then posx = posx + dirx * move end
Are you sure that map[][] is properly formatted?

It might not be. I didn't really check.

Edit:
KermMartian wrote:

Edit: It would have to be, if it can draw the initial screen. What about the fact that rows 0 and 1 of the map array are shorter than the rest? Or is that not the case?

What do you mean? How are they shorter?

Edit2:
It messes up immediately after you press up or down when I changed move to 0.1.
I suspect the problem is that you're passing floating-point position values as array indices, which need to be integral. Do you think that's possible? If so, try the math.floor() function.
Since 0.1 causes an error, I say that you are indeed passing a float. When you press left or right, you rotate, therefore it also gets a floating pt. number. Floor it like KermM recommended
What does math.floor do?

And where in the code do I put it?
Spenceboy98 wrote:
What does math.floor do?


http://pgl.yoyo.org/luai/i/math.floor

I suggest you go through the other math lib functions on that site, since knowing them is crucial.
Spenceboy98 wrote:
What does math.floor do?

And where in the code do I put it?
You put it wherever you need to use xpos and ypos to index into the map[][] array in the code. Better yet, before a bunch of accesses to map[][] that involve xpos/ypos, do:

Code:
local xposi = math.floor(xpos)
local yposi = math.floor(ypos)

And then use xposi and yposi in place of xpos and ypos to index map[][].
Now it says,


Code:
bad argument #1 to 'floor' (number expected, got nil)
Spenceboy98 wrote:
Now it says,


Code:
bad argument #1 to 'floor' (number expected, got nil)
That's because your code uses posx and posy, not xpos and ypos. I didn't bother checking over the code before naming the variables, unfortunately.
KermMartian wrote:
Spenceboy98 wrote:
Now it says,


Code:
bad argument #1 to 'floor' (number expected, got nil)
That's because your code uses posx and posy, not xpos and ypos. I didn't bother checking over the code before naming the variables, unfortunately.


I figured that out right before you posted that. It is now giving me the same error as before.

Also, now it won't let move forward or backward.
Spenceboy98 wrote:
KermMartian wrote:
Spenceboy98 wrote:
Now it says,


Code:
bad argument #1 to 'floor' (number expected, got nil)
That's because your code uses posx and posy, not xpos and ypos. I didn't bother checking over the code before naming the variables, unfortunately.


I figured that out right before you posted that. It is now giving me the same error as before.

Also, now it won't let move forward or backward.
On which line? And please repost your code.
It is the same line as before.

Code:
--Raycasting script
--Based On James Carmack Method
--Thx to http://student.kuleuven.be/~m0216922/CG/raycasting.html Tutorial
--Thx to Jdourlens (http://jdourlens.fr.nf)

function makecolor(r,g,b) 
    return bit32.lshift(bit32.rshift(r,3),11)+bit32.lshift(bit32.rshift(g,2),5)+bit32.rshift(b,3) 
end 
--Define first Map Features in a table
map = {
width = 10,
height = 10,
--mapping decor : 1 = Wall, 0 = No Wall
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,1,1,1,1,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,1,0,0,0,0,0,0,1,1},
{1,0,0,0,1,0,1,0,0,1},
{1,0,0,0,1,0,1,0,0,1},
{1,0,0,0,1,0,1,0,0,1},
{1,0,0,1,1,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1},
}

--Player's Starting Position
posx = 2
posy = 3
local xposi = math.floor(posx)
local yposi = math.floor(posy)

--Initial Directior Vector, Plane Setting and Time Settings
dirx = 1
diry = 0
planex = 0
planey = 0.66

move = 1
rotation = 0.1
direction = 1

timer = 0
oldtime = 0

--screen Dimensions
screenx = 384
screeny = 216

while true do
zmg.clear()

   x=0
   for x = 0,screenx do
   camx = 2*x/screenx - 1
   rayposx = posx
   rayposy = posy
   raydirx = dirx + planex*camx
   raydiry = diry + planey*camx

   mapx = rayposx
   mapy = rayposy

   sidedistx = 0
   sidedisty = 0

   deltadistx = math.sqrt(1+(raydiry*raydiry)/(raydirx*raydirx))
   deltadisty = math.sqrt(1+(raydirx*raydirx)/(raydiry*raydiry))
   perp = 0

   stepx = 0
   stepy = 0
   hit = 0
   side = 0

      if raydirx < 0 then
      stepx = -1
      sidedistx = (rayposx - mapx)*deltadistx
      else stepx = 1
      sidedistx = (mapx + 1 - rayposx)*deltadistx end

      if raydiry < 0 then
      stepy = -1
      sidedisty = (rayposy - mapy)*deltadisty
      else stepy = 1
      sidedisty = (mapy + 1 - rayposy)*deltadisty end

      while hit == 0 do
         if sidedistx < sidedisty then
         sidedistx = sidedistx + deltadistx
         mapx = mapx + stepx
         side = 0
         else
         sidedisty = sidedisty + deltadisty
         mapy = mapy + stepy
         side = 1
         end
         
         if map[mapx][mapy] > 0 then hit = 1 end
      end
      
      if side == 0 then
      perp = math.abs((mapx - rayposx + (1-stepx)/2)/raydirx)
      else perp = math.abs((mapy - rayposy + (1-stepy)/2)/raydiry)
      end
      
      lineheight = math.abs(screeny/perp)   
      
      draw = -lineheight/2 + screeny/2
      if draw < 0 then draw = 0 end
      drawE = lineheight/2 + screeny/2
      if drawE >= screenx then drawE = screenx - 1 end
      

       a = 65
       b = 58
       c = 63   
      colorRoof = makecolor(30, 70, 30)
      colorSky = makecolor(30, 70, 200)
      colorStripes = makecolor(70, 56, 90)
      if side == 1 then
      a = a-30
      b = b-30
      c = c-30
      end
      color = makecolor(a, b, c)
      bandUp = screeny/2+drawE
      bandDown = screeny/2+draw   
       zmg.drawRectFill(x, draw, 1, drawE, color);
       zmg.drawRectFill(x, drawE, 1, 272, colorRoof);
       zmg.drawRectFill(x, 0, 1, draw, colorSky);
       zmg.drawRectFill(x, bandUp/2, 1, 1,colorStripes)
       zmg.drawRectFill(x, bandDown/2, 1, 1,colorStripes)
       zmg.drawRectFill(x, screeny/2, 1, 1,colorStripes)
   end   
   

   
if zmg.keyMenuFast() == 28 then
if timer >= oldtime then
      if map[xposi + dirx * move][yposi] == 0 then xposi = xposi + dirx * move end
      if map[xposi][yposi + diry * move] == 0 then yposi = yposi + diry * move end
timer = 0
end
end

if zmg.keyMenuFast() == 37 then
if timer >= oldtime then
      if map[xposi - dirx * move][yposi] == 0 then xposi = xposi - dirx * move end
      if map[xposi][yposi - diry * move] == 0 then yposi = yposi - diry * move end
timer = 0
end
end
if zmg.keyMenuFast() == 38 then
if timer >= oldtime then
      --both camera direction and camera plane must be rotated
      oldDirX = dirx;
      dirx = dirx * math.cos(-rotation) - diry * math.sin(-rotation);
      diry = oldDirX * math.sin(-rotation) + diry * math.cos(-rotation);
      oldPlaneX = planex;
      planex = planex * math.cos(-rotation) - planey * math.sin(-rotation);
      planey = oldPlaneX * math.sin(-rotation) + planey * math.cos(-rotation);
direction = direction + 1
timer = 0
end
end
if zmg.keyMenuFast() == 27 then
if timer >= oldtime then
      --both camera direction and camera plane must be rotated
      oldDirX = dirx;
      dirx = dirx * math.cos(rotation) - diry * math.sin(rotation);
      diry = oldDirX * math.sin(rotation) + diry * math.cos(rotation);
      oldPlaneX = planex;
      planex = planex * math.cos(rotation) - planey * math.sin(rotation);
      planey = oldPlaneX * math.sin(rotation) + planey * math.cos(rotation);
direction = direction - 1
timer = 0
end
end
   

   
   
zmg.fastCopy()   
end


The error message:


Code:
RaycastLua.lua:140: attempt to index field '?' (a nil value) stack traceback:
RaycastLua.lua:140: in main chunk
[C]: in function 'run'
stdin:1: in main chunk
[C]: in ?


The only difference with the error message from before is that this newer one says 140 instead of 138, but that is because I added 2 new lines of code for the math.floor variables.
when you write:
local xposi = math.floor(posx)
local yposi = math.floor(posy)
then xposi and yposi contain the integer value of what posx and posy contain at the moment.
If posx change, xposi won't change if you don't rewrite the line.

If you don't want to rewrite math.floor everytime, you can use metatable system to convert a floating integer into an integer one.


I've never used the metatable system, but that should work:

Code:

meta = {}
function myindex(t,i)
return t[math.floor(i)]
end
meta.__index = myindex

setmetatable(map,meta)

now when you call map[i], if map[i] == nil (because i is not integer for example), it will return myindex(map,i).


also remember that if I say map = { 1,2,3} then map[1] = 1 and map [0] = nil: the index begins from 1.
However the lua allows to fill floating point indexes and negative or nul indexes, then map[1.1] = 5 is allowed, but map[1.1] ~= map[1] in lua (unless you use the metatable system like I show you)
What about the fact that it's two-dimensional, vebveb? And yes, Spence, as written xposi and yposi never get updated themselves, so that won't work. Not to mention that the addition and multiplication there means the index is still going to be a non-integer. You can either use Vebveb's solution (provided that it works for two dimensional tables) or change things like:
Code:
if map[xposi - dirx * move][yposi] == 0 then xposi = xposi - dirx * move end
to
Code:
if map[math.floor(posx - dirx * move)][math.floor(posy)] == 0 then posx = posx - dirx * move end
you are right Kerm.

I think this require this fix:

Code:

for i = 1, #map do
setmetatable(map[i],meta)
end
vebveb wrote:
you are right Kerm.

I think this require this fix:

Code:

for i = 1, #map do
setmetatable(map[i],meta)
end
Indeed, in addition to the existing code, so the whole thing would look like:


Code:
meta = {}
function myindex(t,i)
return t[math.floor(i)]
end
meta.__index = myindex

setmetatable(map,meta)
for i = 1, #map do
setmetatable(map[i],meta)
end
yes, except that the line "setmetatable(map,meta) " is not needed.
vebveb wrote:
yes, except that the line "setmetatable(map,meta) " is not needed.
I disagree. I believe it still is, so that if you index map as map[float][int] or map[float][float] it will still work.
oh yes, you are right.
However a issue may remain if Spenceboy98 didn't consider that the index begin at 1 and not 0.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are GMT - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement