found this article on tinternet
http://student.kuleuven.be/~m0216922/CG/raycasting.htmland 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