While I know this thread is somewhat dated, and the topic really has shifted more towards the CX's DRM, I thought I would highlight the importance of basic Lua optimizations.
I ran the code from the first page (slightly modified, included a timer call so I could get a consistent frame rate), and it ran at 4 to 5 frames per second.
I modify the code some (only localizes variables and common functions), and then I can get 6 - 7 frames per second.
This doesn't change the algorithm at all, though that could probably be improved.
local timer_stop = timer.stop;
local timer_start = timer.start;
local window = platform.window;
local invalidate = window.invalidate;
local w, h, planeX, planeY, map;
function on.timer()
timer_stop();
invalidate(window);
end
local math_abs = math.abs;
local math_floor = math.floor;
local math_cos, math_sin = math.cos, math.sin;
local function racine(a)
local x=1
local y=0.5*(1+a)
while math_abs(y-x)>0.001 do
x=y
y=0.5*(x+a/x)
end
return y
end
local function renderMap(gc,map,w,h,camera)
local math_cos, math_sin = math_cos, math_sin;
local dirX, dirY, rayPosX, rayPosY, rayDirX, rayDirY, mapX, mapY, deltaDistX,
deltaDisY, hit, stepX, sideDistX, stepY, sideDistY;
for x=0,w,2 do
dirX=math_cos(camera[3])
dirY=math_sin(camera[3])
planeX=math_cos(camera[3]-1.5707963267949)
planeY=math_sin(camera[3]-1.5707963267949)
cameraX=(x*2/w)-1
rayPosX=camera[1]
rayPosY=camera[2]
rayDirX=dirX+planeX*cameraX
rayDirY=dirY+planeY*cameraX
mapX=math_floor(rayPosX)
mapY=math_floor(rayPosY)
deltaDistX=racine(1+(rayDirY*rayDirY)/(rayDirX*rayDirX))
deltaDistY=racine(1+(rayDirX*rayDirX)/(rayDirY*rayDirY))
hit=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
local perpWallDist;
if side==0 then
perpWallDist=math_abs((mapX-rayPosX+(1-stepX)/2)/rayDirX)
else
perpWallDist=math.abs((mapY-rayPosY+(1-stepY)/2)/rayDirY)
end
local hauteurLigne=math.abs(math_floor(h/perpWallDist))
local drawStart=math_floor(-hauteurLigne/2+h/2)
local drawEnd=math_floor(hauteurLigne/2+h/2)
if drawStart<0 then
drawStart=0
end
if drawEnd>=h then
drawEnd=h-1
end
gc:setColorRGB(10,10,10)
if side==1 then
gc:setColorRGB(100,100,100)
end
gc:fillRect(x,drawStart,2,drawEnd-drawStart)
end
end
local menu;
function on.escapeKey()
menu=1
invalidate(window);
end
on.escapeKey()
function on.enterKey()
menu=nil
--fovy=60
camera={10,10,0.05}
w=320 h=240
planeX=0 planeY=1
map={{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},{1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1},{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},{1,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1},{1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,1},{1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1},{1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1},{1,0,0,0,0,0,1,0,0,1,0,0,1,0,0,1},{1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1},{1,0,0,1,0,0,0,0,0,0,0,0,1,1,1,1},{1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},{1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,1},{1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1},{1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1},{1,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1},{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}
invalidate(window);
end
function on.arrowKey(ar)
turn=nil
if ar=="right" then
camera[3]=camera[3]-0.1
end
if ar=="left" then
camera[3]=camera[3]+0.1
end
if ar=="up" then
if map[math_floor(camera[1]+math_cos(camera[3])/3)][math_floor(camera[2]+math_sin(camera[3])/3)]==0 then
camera[1]=camera[1]+math_cos(camera[3])/3
camera[2]=camera[2]+math_sin(camera[3])/3
end
end
if ar=="down" then
if map[math_floor(camera[1]-math_cos(camera[3])/4)][math_floor(camera[2]-math_sin(camera[3])/4)]==0 then
camera[1]=camera[1]-math_cos(camera[3])/4
camera[2]=camera[2]-math_sin(camera[3])/4
end
end
invalidate(window);
end
local milli = timer.getMilliSecCounter;
local last = 0;
function on.paint(gc)
if menu then
gc:setColorRGB(0,0,255)
gc:setFont("sansserif","r",30)
gc:drawString("RayCaster Demo",30,0,"top")
gc:setFont("serif","b",10)
gc:drawString("Press Enter to start",100,100,"top")
else
gc:setColorRGB(200,200,200)
gc:fillRect(0,0,platform.window:width(),platform.window:height())
renderMap(gc,map,platform.window:width(),platform.window:height(),camera)
end
gc:setColorRGB(0,0,0)
gc:setFont("sansserif","r",8)
gc:drawString("FPS: " .. tostring(1000/(milli()-last)),10,200,"top")
last = milli();
timer_start(0.01);
end