1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
| 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
|