found this article on tinternet
http://student.kuleuven.be/~m0216922/CG/raycasting.html
and to help me make sense of it I blitzified it.. and added a topdown map view. Its quite messy code still and I have only taken the first part where the walls are just plain colors but it works.
Now I need to mess around to get my head around exactly what it does !
Anyway. some might find it useful. Not really all my code so I cant really enter it into the
Keys: cursor to move,q to quit
Edit : This version calcs the xpos (0-1) on the cell that the ray has hit. The 2d view draws all the rays now.
http://student.kuleuven.be/~m0216922/CG/raycasting.html
and to help me make sense of it I blitzified it.. and added a topdown map view. Its quite messy code still and I have only taken the first part where the walls are just plain colors but it works.
Now I need to mess around to get my head around exactly what it does !
Anyway. some might find it useful. Not really all my code so I cant really enter it into the
Keys: cursor to move,q to quit
Edit : This version calcs the xpos (0-1) on the cell that the ray has hit. The 2d view draws all the rays now.
SuperStrict ' Based on code by Lode Vandevenne ' Original totorial and source code 'can be found at : <a href="http://student.kuleuven.be/~m0216922/CG/raycasting.html" target="_blank">http://student.kuleuven.be/~m0216922/CG/raycasting.html</a> Global world:TWorld main() End Function main() Local player:TPlayer world = New TWorld player = New TPlayer Graphics 640,400,0 While Not KeyHit(KEY_Q) Cls player.Update() SetOrigin 0,0 SetColor 100,100,100 DrawLine 320,0,320,400 DrawLine 0,200,320,200 world.Draw() player.Draw() Local x:Int Local cameraX:Double Local rayPosX:Double Local rayPosY:Double Local rayDirX:Double Local rayDirY:Double For x=0 To 320 ' calculate ray position And direction cameraX = -2.0 * Double(x) / 320.0 + 1.0 ' x-coordinate in camera space rayPosX = player.xPos rayPosY = player.yPos rayDirX = player.direction.x + player.camera.x * cameraX rayDirY = player.direction.y + player.camera.y * cameraX ' which box of the map we're in Local mapX:Int = rayPosX Local mapY:Int = rayPosY ' length of ray from current position To Next x Or y-side Local sideDistX:Double Local sideDistY:Double ' length of ray from one x Or y-side To Next x Or y-side Local deltaDistX:Double = Sqr(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX)) Local deltaDistY:Double = Sqr(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY)) Local perpWallDist:Double ' what direction To Step in x Or y-direction (either +1 Or -1) Local stepX:Int Local stepY:Int Local hit:Int = 0 ' was there a wall hit? Local side:Int ' was a NS Or a EW wall hit? ' calculate Step And initial sideDist If rayDirX < 0 Then stepX = -1 sideDistX = (rayPosX - mapX) * deltaDistX Else stepX = 1 sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX End If If rayDirY < 0 Then stepY = -1 sideDistY = (rayPosY - mapY) * deltaDistY; Else stepY = 1; sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY; End If ' perform DDA While hit = 0 ' jump To Next map square, Or in x-direction, Or in y-direction If sideDistX < sideDistY Then sideDistX :+ deltaDistX mapX :+ stepX side = 0 Else sideDistY :+ deltaDistY mapY :+ stepY side = 1 End If ' Check If ray has hit a wall If world.cell[mapX,mapY] > 0 Then hit = 1 End If Wend SetColor 255,255,0 SetOrigin 320+12,0+12 ' calculate value of wallX Local wallX:Double ' where exactly the wall was hit If side = 1 Then wallX = rayPosX + ((mapY - rayPosY + (1.0 - stepY) / 2.0) / rayDirY) * rayDirX Else wallX = rayPosY + ((mapX - rayPosX + (1.0 - stepX) / 2.0) / rayDirX) * rayDirY End If wallX :- Floor((wallX)); ' Draw the ray for each screen column we are drawing Local drawMapX:Double Local drawMapY:Double drawMapX = mapX drawMapY = mapy SetColor 255,255,0 If side = 1 Then If player.yPos > drawMapY Then drawMapY :+ 1 End If drawMapX = drawMapX + wallX Else If player.xPos > drawMapX Then drawMapX :+ 1 End If drawMapY = drawMapY + wallX End If SetColor 0,255,255 DrawLine player.xPos*12.0,player.yPos*12.0,drawMapX*12.0,drawMapY*12.0 SetOrigin 0,0 ' Calculate distance projected on camera direction (oblique distance will give fisheye effect!) If side = 0 perpWallDist = Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) Else perpWallDist = Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) End If 'Calculate height of line To draw on screen Local lineHeight:Int = Abs(Int(200 / perpWallDist)) ' calculate lowest And highest pixel To fill in current stripe Local drawStart:Int = -lineHeight / 2 + 200 / 2 If drawStart < 0 Then drawStart = 0 End If Local drawEnd:Int = lineHeight / 2 + 200 / 2; If drawEnd >= 200 Then drawEnd = 200 - 1 End If ' choose wall color Local colR:Int Local colG:Int Local colB:Int Select world.cell[mapX,mapY] Case world.CELL_OUTER_WALL colR = 200 colG = 200 colB = 200 Case world.CELL_INNER_WALL1 colR = 200 colG = 100 colB = 100 Case world.CELL_OUTER_COLUMN colR = 200 colG = 0 colB = 200 Case world.CELL_INNER_WALL2 colR = 100 colG = 100 colB = 200 Case world.CELL_EXIT colR = 100 colG = 200 colB = 100 End Select ' give x And y sides different brightness If side = 1 Then colR :/ 2 colG :/ 2 colB :/ 2 End If SetColor colR, colG, colB ' //draw the pixels of the stripe as a vertical line DrawLine x, drawStart, x, drawEnd Next Flip Wend End Function Type TVector Field x:Float Field y:Float End Type Type Tplayer Field xPos:Float Field yPos:Float Field direction:TVector Field camera:TVector Const moveSpeed:Float= 5.0/30.0 Const rotSpeed:Float = 60.0 / 30.0 Method New() direction = New TVector camera = New TVector xPos = 22 yPos = 12 direction.x = -1 direction.y = 0 camera.x = 0 camera.y = .66 End Method Method Draw() ' draw player SetColor 255,0,0 DrawLine xPos*12-6,yPos*12-6,xPos*12+6,yPos*12+6 DrawLine xPos*12-6,yPos*12+6,xPos*12+6,yPos*12-6 ' draw direction SetColor 255,255,255 DrawLine xPos*12,yPos*12,xPos*12+direction.x*12,yPos*12+direction.y*12 ' drawcamera DrawLine xPos*12+direction.x*12, .. yPos*12+direction.y*12, .. xPos*12+direction.x*12 + camera.x*12, .. yPos*12+direction.y*12 + camera.y*12 DrawLine xPos*12+direction.x*12, .. yPos*12+direction.y*12, .. xPos*12+direction.x*12 - camera.x*12, .. yPos*12+direction.y*12 - camera.y*12 ' draw end rays ' SetColor 0,200,0 ' Local endX:Float ' Local endY:Float ' ' endX = (direction.x + camera.x) * 25 ' endY = (direction.y + camera.y) * 25 ' DrawLine xPos*12,yPos*12,xPos*12+endX*12, yPos*12+endY * 12 ' endX = (direction.x - camera.x) * 25 ' endY = (direction.y - camera.y) * 25 ' DrawLine xPos*12,yPos*12,xPos*12+endX*12, yPos*12+endY * 12 End Method Method Update() ' move Forwards If KeyDown(Key_UP) If world.cell[(xPos + direction.x * moveSpeed),Int(yPos)] = 0 Then xPos :+ direction.x * moveSpeed End If If world.cell[(xPos),Int(yPos + direction.y * moveSpeed)] = 0 Then yPos :+ direction.y * moveSpeed End If End If ' move Backwards If KeyDown(Key_DOWN) If world.cell[(xPos - direction.x * moveSpeed),Int(yPos)] = 0 Then xPos :- direction.x * moveSpeed End If If world.cell[(xPos),Int(yPos - direction.y * moveSpeed)] = 0 Then yPos :- direction.y * moveSpeed End If End If ' rotate left If KeyDown(KEY_LEFT) Local temp:Float temp = direction.x direction.x = direction.x * Cos(-rotSpeed) - direction.y * Sin(-rotSpeed) direction.y = temp*Sin(-rotSpeed) + direction.y * Cos(-rotSpeed) temp = camera.x camera.x = camera.x * Cos(-rotSpeed) - camera.y * Sin(-rotSpeed) camera.y = temp*Sin(-rotSpeed) + camera.y * Cos(-rotSpeed) End If ' rotate right If KeyDown(KEY_RIGHT) Local temp:Float temp = direction.x direction.x = direction.x * Cos(rotSpeed) - direction.y * Sin(rotSpeed) direction.y = temp*Sin(rotSpeed) + direction.y * Cos(rotSpeed) temp = camera.x camera.x = camera.x * Cos(rotSpeed) - camera.y * Sin(rotSpeed) camera.y = temp*Sin(rotSpeed) + camera.y * Cos(rotSpeed) End If End Method End Type Type TWorld Field width:Int Field height:Int Field cell:Int[,] Const CELL_EMPTY:Int = 0 Const CELL_OUTER_WALL:Int = 1 Const CELL_INNER_WALL1:Int = 2 Const CELL_OUTER_COLUMN:Int = 3 Const CELL_INNER_WALL2:Int = 4 Const CELL_EXIT:Int = 5 Method New() RestoreData WorldData ReadData width,height cell = New Int[width,height] Local x:Int Local y:Int For y = 0 Until height For x = 0 Until width ReadData cell[x,y] Next Next End Method Method Draw() Local x:Int Local y:Int SetOrigin 320+12,0+12 For y = 0 Until height For x = 0 Until width Select cell[x,y] Case CELL_EMPTY SetColor 0,0,0 Case CELL_OUTER_WALL SetColor 200,200,200 Case CELL_INNER_WALL1 SetColor 200,100,100 Case CELL_OUTER_COLUMN SetColor 200,0,200 Case CELL_INNER_WALL2 SetColor 100,100,200 Case CELL_EXIT SetColor 100,200,100 End Select DrawRect x*12,y*12,11,11 Next Next End Method End Type #WorldData DefData 24,24 DefData 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1 DefData 1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1 DefData 1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 DefData 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1