Raycaster Competition

BlitzMax Forums/BlitzMax Programming/Raycaster Competition

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.
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