Ray Casting

BlitzMax Forums/BlitzMax Programming/Ray Casting

I've been trying for a week now to get some simple ray casting working. I have made 3 different versions (issues with me not saving properly :P) and only two of them had any sort of workability. When I started I just did horizontal checks and I could get a strait wall but when I started to use verticle checks aswell I started to get problems. There should be any problems with the verticle checks as it is a copy of the horizontal version with the bits that need to be changed changed.

Here's what I have so far. Its part of a corner and even though there should be some walls that were from verticle checks there isnt (they should be in red - horizontal in blue). The littl map at the bottom shows which direction the person is pointing.

Rem
	RAY CASTING
	
	The ray casting test program. will hopefully work!
End Rem

SuperStrict

Type Point
	Field X:Int
	Field Y:Int
	Field GX:Int
	Field GY:Int
	
	Field XA:Int
	Field YA:Int
	
	Field Distance:Int
	
	Field Exist:Int=True
End Type

Global H:Point 'Horizontal checks
Global V:Point 'Verticle checks

Global Width:Int=4, Height:Int=4
Global Grid:Int[Width,Height]
SetUpGrid()

Global PlayerX:Int = 256
Global PlayerY:Int = 256
Global PlayerR:Float = 135

Global CurrentRayAngle:Float, Count1:Int, CDistance:Float, CosB:Float, Proj:Float, Direction:String

Graphics 800, 600, 32

Trace()

While Not KeyHit(KEY_ESCAPE)
	
	If KeyHit(KEY_LEFT) Then PlayerR:+1; Trace()
	If KeyHit(KEY_RIGHT) Then PlayerR:-1; Trace()
	
Wend

Function Trace()
	CurrentRayAngle = PlayerR+30.0
	Cls
	For Count1 = 0 To 319 'Go through columns
		H = New Point
		V = New Point
		TraceH()
		TraceV()
		
		If V.Exist = False And H.Exist = False
		Else
			If V.Exist = True And H.Exist = True
				If V.Exist < H.Exist Then CDistance = V.Distance; Direction ="V"
				If H.Exist < V.Exist Then CDistance = H.Distance; Direction = "H"
			Else
				If V.Exist = True Then CDistance = V.Distance; Direction = "V"
				If H.Exist = True Then CDistance = H.Distance; Direction = "H"
			End If
			
			CosB = (30.0)-((60.0/320.0)*Float(Count1))  'Sort out distance problems -
			H.Distance:*Cos(CosB) 						'- find correct distance
			
			Proj = 64.0/H.Distance*277.0 'work out slice height
			DrawSlice(Proj,Direction)
		End If
		CurrentRayAngle:-(60.0/320.0)
		H=Null
		V=Null
	Next
	
	DrawMap()
	Flip
End Function

Function TraceH()
	
	If PlayerR < 180 And PlayerR > 0 Then H.Y = Floor(PlayerY/64)*64-1
	If PlayerR > 180 And PlayerR < 0 Then H.Y = Floor(PlayerY/64)*64+64
	H.GY = H.Y/64
	
	H.X = PlayerX+(PlayerY-H.Y)/Tan(CurrentRayAngle)
	H.GX = H.X/64
	
	If H.GX > -1 And H.GX < Width And H.GY > -1 And H.GY < Height
		If Grid[H.GX,H.GY] = 1 'We hit an object!
			H.Distance = Sqr(((PlayerX-H.X)*(PlayerX-H.X))+((PlayerY-H.Y)*(PlayerY-H.Y)))
		Else 'Better keep looking!
			Repeat 'We may need to go through this alot
				If PlayerR < 180 And PlayerR > 0 Then H.YA = -64
				If PlayerR > 180 And PlayerR < 0 Then H.YA = 64
				H.Y:+H.YA
				H.GY = H.Y/64
				
				H.XA = 64/Tan(CurrentRayAngle)
				H.X:+H.XA
				H.GX=H.X/64
				
				If H.GX > -1 And H.GX < Width And H.GY > -1 And H.GY < Height
					If Grid[H.GX,H.GY] = 1 'We hit an object!
						H.Distance = Sqr(((PlayerX-H.X)*(PlayerX-H.X))+((PlayerY-H.Y)*(PlayerY-H.Y)))
						Exit
					End If
				Else
					H.Exist = False
					Exit
				End If
			Forever
		End If
	Else
		H.Exist = False 'There is nothing in this line of sight (shouldnt happen with default map)
	End If
	
End Function

Function TraceV()
	
	If PlayerR > 90 And PlayerR < 270
		V.X = Floor(PlayerX/64)*64-1
	Else
		V.X = Floor(PlayerX/64)*64+64
	End If
	V.GX = V.X/64
	
	V.Y = PlayerY+(PlayerX-V.X)*Tan(CurrentRayAngle)
	V.GY = V.Y/64
	
	If V.GX > -1 And V.GX < Width And V.GY > -1 And V.GY < Height
		If Grid[V.GX,V.GY] = 1 'We hit an object!
			V.Distance = Sqr(((PlayerX-V.X)*(PlayerX-V.X))+((PlayerY-V.Y)*(PlayerY-V.Y)))
		Else 'Better keep looking!
			Repeat 'We may need to go through this alot
				If PlayerR > 90 And PlayerR < 270
					V.XA = -64
				Else
					V.XA = 64
				End If
				V.X:+V.XA
				V.GX = V.X/64
				
				V.YA = 64*Tan(CurrentRayAngle)
				V.Y:+V.YA
				V.GY=V.Y/64
				
				If V.GX > -1 And V.GX < Width And V.GY > -1 And V.GY < Height
					If Grid[V.GX,V.GY] = 1 'We hit an object!
						V.Distance = Sqr(((PlayerX-V.X)*(PlayerX-V.X))+((PlayerY-V.Y)*(PlayerY-V.Y)))
						Exit
					End If
				Else
					V.Exist = False
					Exit
				End If
			Forever
		End If
	Else
		V.Exist = False 'There is nothing in this line of sight (shouldnt happen with default map)
	End If
	
End Function


Function DrawSlice(Height:Int,Dir:String)
	If Dir = "H" Then SetColor 0, 0, 255
	
	If Dir = "V" Then SetColor 255, 0, 0
	
	DrawLine(Count1,100-(Height/2),Count1,100+(Height/2))
End Function

Function DrawMap()
	Local CountA:Int,CountB:Int
	
	SetColor 0, 255, 0
	DrawLine 320, 0, 320, 200
	DrawLine 0, 200, 320, 200
	DrawText "PlayerX: " + PlayerX, 330, 10
	DrawText "PlayerY: " + PlayerY, 330, 30
	DrawText "PlayerR: " + PlayerR, 330, 50
	
	For CountA = 3 To 0 Step -1
	For CountB = 3 To 0 Step -1
		If Grid[CountA,CountB] = 1 SetColor 255, 0, 0
		If Grid[CountA,CountB] = 0 SetColor 255, 255, 255
		DrawHollowRect(100+(64*CountA),300+(64*CountB),64,64)
	Next
	Next
	
	SetColor 0, 0, 255
	Plot PlayerX+100, PlayerY+300
	
	SetColor 0, 255, 0
	DrawLine PlayerX+100, PlayerY+300, PlayerX+(300*Sin(PlayerR-270)+100), PlayerY+(300*Cos(PlayerR-270)+300)
	DrawLine PlayerX+100, PlayerY+300, PlayerX+(300*Sin((PlayerR-30)-270)+100), PlayerY+(300*Cos((PlayerR-30)-270)+300)
	DrawLine PlayerX+100, PlayerY+300, PlayerX+(300*Sin((PlayerR+30)-270)+100), PlayerY+(300*Cos((PlayerR+30)-270)+300)
	
End Function

Function DrawHollowRect(x:Int, y:Int, w:Int, h:Int)
	DrawLine x, y, x+w, y
	DrawLine x, y, x, y+h
	DrawLine x+w, y, x+w, y+h
	DrawLine x, y+h, x+w, y+h
End Function

Function SetUpGrid()
	Grid[0,0] = 1
	Grid[1,0] = 1
	Grid[2,0] = 1
	Grid[3,0] = 1
	
	Grid[0,1] = 1
	'Grid[0,2] = 1
	'Grid[0,3] = 1
End Function


I'm sure that the problem is simple to work out, and I would have liked to have been able to work it out myself, but I just can't get it. I've gone through the permadi tutorial over and over and have been checking each equation to make sure that I didn't didnt divide when I should have multiplied and other little errors like that, but I'm sure I've sorted all those little things out now.

Any help that can be given on this problem is highly appreciated.

Thanks

Matthew

Did you check the raycasting demo that comes with Bmax?

I thought I'd seen a demo with BlitzMAX but when I looked for it I couldn't find it. I had a look through them again just now but it doesnt seem to be there.