Raycaster

Miscellaneous Forums/Blitz Showcase/Raycaster

not bad!
it is kind of slow for 320 x 200. isn't it?
anyway..

just did a quick glance at your code and I think I fixed a couple of your errors:
Const MAPSIZE = 16
Const GRIDSIZE = 64
Const GRIDSHIFTS = 6
Const GWIDTH = 320
Const GHEIGHT = 200
Const ANGLEOFVIEW = 60
Const CASTINGSTEP# = ANGLEOFVIEW/Float( GWIDTH )
Const TILES = 2
Const TEXTURESIZE = 64
Const SCALEFACTOR# = TEXTURESIZE/GRIDSIZE
Const FLOORTILE = 2
Const CEILINGTILE = 2
Const HD = ( SCALEFACTOR# <> 1 )
Const CEILING = True

Graphics GWIDTH, GHEIGHT, 32, 2

Global CamX# = 5*GRIDSIZE + GRIDSIZE/2, CamY# = 5*GRIDSIZE + GRIDSIZE/2, ProjectionDistance# = ( GWIDTH/2 )/Tan( ANGLEOFVIEW/2 )
Global CameraAngle = 270, PlayerHeight = 32, PlaneDisplacement

Dim MapData( MAPSIZE - 1, MAPSIZE - 1 )
Dim TextureData( TILES*( TEXTURESIZE)*( TEXTURESIZE ) )
Dim Distances#( GWIDTH - 1 )

For i = 0 To Tiles - 1
	Texture = LoadImage( "Tile" + ( i + 1 ) + ".png" )
	SetBuffer ImageBuffer( Texture )
	LockBuffer ImageBuffer( Texture )
	For x = 0 To TEXTURESIZE - 1
		For y = 0 To TEXTURESIZE - 1
			TextureData( i*TEXTURESIZE*TEXTURESIZE + ( x*TEXTURESIZE + y ) ) = ReadPixelFast( x, y )
		Next
	Next
	
	FreeImage Texture
Next

Type Sprite
	Field X#
	Field Y#
	Field Height
	Field Width
	Field ImageData[ 256*256 ]
End Type

Dummy = LoadImage( "Alien.png" )
LockBuffer ImageBuffer( Dummy )
For i = 1 To 10
	Drink.Sprite = New Sprite
		Drink\X# = Rnd( 0, MAPSIZE*GRIDSIZE )
		Drink\Y# = Rnd( 0, MAPSIZE*GRIDSIZE )
		Drink\Height = ImageHeight( Dummy )
		Drink\Width = ImageWidth( Dummy )
		
		For x = 0 To Drink\Width - 1
			For y = 0 To Drink\Height - 1
				Drink\ImageData[ x*Drink\Width + y ] = ReadPixelFast( x, y, ImageBuffer( Dummy ) )
			Next
		Next
	
	If MapData( Drink\X# Shr GRIDSHIFTS, Drink\Y# Shr GRIDSHIFTS ) Then i = i - 1
Next

FreeImage( Dummy )

SetBuffer BackBuffer()

Restore MapData
For i = 0 To MAPSIZE - 1
	For t = 0 To MAPSIZE - 1
		Read MapData( t, i )
	Next
Next

Timer = CreateTimer( 60 )

DisplayFPS = 0
FPS = 0
Counter = MilliSecs()

While Not KeyHit( 1 )
	Cls
	
	LockBuffer BackBuffer()
	RenderScreen()
	RenderSprites()
	UnlockBuffer BackBuffer()
	
	MoveCamera()
	
	If MilliSecs() - Counter > 1000 Then
		DisplayFPS = FPS
		Counter = MilliSecs()
		FPS = 0
	EndIf
	
	Text 0, 0, DisplayFPS
	
	Flip 0
	WaitTimer Timer
	
	FPS = FPS + 1
Wend

End

Function MoveCamera()
	XSpeed# = -Sgn( KeyDown( 208 ) - KeyDown( 200 ) )*Cos( CameraAngle )
	YSpeed# = Sgn( KeyDown( 208 ) - KeyDown( 200 ) )*Sin( CameraAngle )
	
	TileX = ( CamX# + XSpeed# + Sgn( XSpeed# ) ) Shr GRIDSHIFTS
	TileY = ( CamY# + YSpeed# + Sgn( YSpeed# ) ) Shr GRIDSHIFTS
	OldTileX = CamX# Shr GRIDSHIFTS
	OldTileY = CamY# Shr GRIDSHIFTS
	
	If Not MapData( OldTileX, TileY ) Then CamY# = CamY# + YSpeed#
	If Not MapData( TileX, OldTileY ) Then CamX# = CamX# + XSpeed#
	
	CameraAngle = CameraAngle - KeyDown( 203 ) + KeyDown( 205 )
	
	PlaneDisplacement = PlaneDisplacement - KeyDown( 74 ) + KeyDown( 78 )
End Function

Function RenderScreen()
	For i = 0 To GWIDTH - 2
		Angle# = ( CameraAngle - ANGLEOFVIEW/2 + CASTINGSTEP#*i ) Mod 360
		Angle# = ( 360 + Angle# ) Mod 360
		
		;Wird der Strahl nach oben oder unten geschickt?
		YDirection = 1 - ( Angle# < 180 )*2
		
		;Wird der Strahl nach links oder rechts geschickt?
		XDirection = -1 + ( Angle# > 270 Or Angle# < 90 )*2
		
		;Horizontale Kollision
		Ya# = CamY# Mod GRIDSIZE
		If YDirection = 1 Then Ya# = GRIDSIZE - Ya#
		Xa# = Ya#/Tan( Angle# )
		
		IntersectionY# = CamY# + YDirection*Ya#
		IntersectionX# = CamX# - YDirection*Xa#
		
		TileY = ( IntersectionY# + YDirection ) Shr GRIDSHIFTS
		TileX = IntersectionX# Shr GRIDSHIFTS
		
		If TileX >= 0 And TileX < MAPSIZE And TileY >= 0 And TileY < MAPSIZE Then
			If MapData( TileX, TileY ) Then 
				WallTile = MapData( TileX, TileY )
			Else
				Ya# = YDirection Shl GRIDSHIFTS
				Xa# = Ya#/Tan( Angle# )
				Repeat
					IntersectionX# = IntersectionX# - Xa#
					IntersectionY# = IntersectionY# + Ya#
					TileY = ( IntersectionY# + YDirection ) Shr GRIDSHIFTS
					TileX = IntersectionX# Shr GRIDSHIFTS
					If TileX >= 0 And TileX < MAPSIZE And TileY >= 0 And TileY < MAPSIZE Then
						If MapData( TileX, TileY ) Then
							WallTile = MapData( TileX, TileY )
							Exit
						EndIf
					Else
						Exit
					EndIf
				Forever
			EndIf
		EndIf

		WallX# = IntersectionX#
		WallY# = IntersectionY#
		
		;Vertikale Kollision
		Xa# = CamX# Mod GRIDSIZE
		If XDirection = 1 Then Xa# = GRIDSIZE - Xa#
		Ya# = Xa#*Tan( Angle# )
		
		IntersectionX# = CamX# + XDirection*Xa#
		IntersectionY# = CamY# - XDirection*Ya#
		
		TileY = IntersectionY# Shr GRIDSHIFTS
		TileX = ( IntersectionX# + XDirection ) Shr GRIDSHIFTS
		
		If TileX >= 0 And TileX < MAPSIZE And TileY >= 0 And TileY < MAPSIZE Then
			If MapData( TileX, TileY ) Then
				IntersectionTile = MapData( TileX, TileY )
			Else
				Xa# = XDirection Shl GRIDSHIFTS
				Ya# = Xa#*Tan( Angle# )
				Repeat
					IntersectionX# = IntersectionX# + Xa#
					IntersectionY# = IntersectionY# - Ya#
					TileY = IntersectionY# Shr GRIDSHIFTS
					TileX = ( IntersectionX# + XDirection ) Shr GRIDSHIFTS
					If TileX >= 0 And TileX < MAPSIZE And TileY >= 0 And TileY < MAPSIZE Then
						If MapData( TileX, TileY ) Then
							IntersectionTile = MapData( TileX, TileY )
							Exit
						EndIf
					Else
						Exit
					EndIf
				Forever
			EndIf
		EndIf
	
		DistanceVertically# = Abs( ( WallY# - CamY# )/Sin( Angle# ) )
		DistanceHorizontally# = Abs( ( IntersectionX# - CamX# )/Cos( Angle# ) )
		
		If DistanceHorizontally# < DistanceVertically# Then 
			SmallerDistance# = DistanceHorizontally#
			If WallTile > 0 Then
				If HD Then 
					TextureRow = Floor( ( WallX# Mod GRIDSIZE )*SCALEFACTOR# )
				Else
					TextureRow = Floor( WallX# ) Mod GRIDSIZE
				EndIf
			EndIf
			If HD Then
				TextureRow = Floor( ( IntersectionY# Mod GRIDSIZE )*SCALEFACTOR# )
			Else
				TextureRow = Floor( IntersectionY# ) Mod GRIDSIZE
			EndIf
		Else
			SmallerDistance# = DistanceVertically#
			If IntersectionTile > 0 Then
				If HD Then
					TextureRow = Floor( ( IntersectionY# Mod GRIDSIZE )*SCALEFACTOR# )
				Else
					TextureRow = Floor( IntersectionY# ) Mod GRIDSIZE
				EndIf
			EndIf
			If HD Then
				TextureRow = Floor( ( WallX# Mod GRIDSIZE )*SCALEFACTOR# )
			Else
				TextureRow = Floor( WallX# ) Mod GRIDSIZE
			EndIf
		EndIf
		
		WallHeight = ( GRIDSIZE/( SmallerDistance#*Cos( CASTINGSTEP#*i - ANGLEOFVIEW/2 ) ) )*ProjectionDistance#
		If WallTile = 0 And IntersectionTile > 0 Then WallTile = IntersectionTile
		
		TStart = ( GHEIGHT/2 + PlaneDisplacement ) - WallHeight/2
		TEnd = ( GHEIGHT/2 + PlaneDisplacement ) + WallHeight/2
		If TStart < 0 Then YCorrection = Abs( TStart )
		If TEnd >= GHEIGHT Then YCorrection2 = TEnd - GHEIGHT + 1
				
		For t = TStart + YCorrection To TEnd - YCorrection2
			If WallTile = 1 Then
				WritePixelFast i, t, $FFFFFFFF 
			Else
				ARGB = TextureData( ( WallTile - 2 )*TEXTURESIZE*TEXTURESIZE + ( TextureRow*TEXTURESIZE + ( t - GHEIGHT/2 + WallHeight/2 - PlaneDisplacement )*( TEXTURESIZE/Float( WallHeight ) ) ) )
				WritePixelFast i, t, ARGB
			EndIf
		Next
		
		;Floor - Casting
		TStart = ( GHEIGHT/2 + PlaneDisplacement ) + WallHeight/2
		TStart = TStart*( TStart >= 0 )
		TEnd = GHEIGHT
;********************************
		For t = TStart To TEnd-1 ;fixed
;********************************
			Length# = ( ( GRIDSIZE/2 )/( ( t - GHEIGHT/2 - PlaneDisplacement )/ProjectionDistance# ) )/Cos( CASTINGSTEP#*i - ANGLEOFVIEW/2 )
			FloorX = CamX# + Cos( Angle# )*Length#
			FloorY = CamY# - Sin( Angle# )*Length#
			TextureColumn = FloorY Mod TEXTURESIZE
			TextureRow = FloorX Mod TEXTURESIZE
			ARGB = TextureData( ( FLOORTILE - 1 )*TEXTURESIZE*TEXTURESIZE + ( TextureRow*TEXTURESIZE + TextureColumn ) )
			If i >= 320 Or t >= 200 Then Print i+" "+t+" third"
			WritePixelFast i, t, ARGB
		Next
				
		If CEILING Then
			;Ceil - Casting
			TStart = 0
			TEnd = ( GHEIGHT/2 + PlaneDisplacement ) - WallHeight/2
			TEnd = TEnd*( TEnd < GHEIGHT ) + ( GHEIGHT - 1 )*( TEnd >= GHEIGHT )
;*************************************
			For t = TStart To TEnd-1 ;fixed
;*************************************
				Length# = ( ( GRIDSIZE/2 )/( ( GHEIGHT/2 - t + PlaneDisplacement )/ProjectionDistance# ) )/Cos( CASTINGSTEP#*i - ANGLEOFVIEW/2 )
				CeilingX = CamX# + Cos( Angle# )*Length#
				CeilingY = CamY# - Sin( Angle# )*Length#
				TextureRow = CeilingX Mod TEXTURESIZE
				TextureColumn = CeilingY Mod TEXTURESIZE
				ARGB = TextureData( ( CEILINGTILE - 1 )*TEXTURESIZE*TEXTURESIZE + ( TextureRow*TEXTURESIZE + TextureColumn ) )
				WritePixelFast i, t, ARGB
			Next
		EndIf
		
		Distances#( i ) = SmallerDistance#
		
		TextureRow = 0
		IntersectionTile = 0
		WallTile = 0
		Saviour = 0
		YCorrection = 0
		YCorrection2 = 0
	Next
End Function

Function RenderSprites()
	;Sprites
	For Drink.Sprite = Each Sprite
		Distance# = Sqr( ( CamX# - Drink\X# )*( CamX# - Drink\X# ) + ( CamY# - Drink\Y# )*( CamY# - Drink\Y# ) )
		Height = Drink\Height - 1
		Width = Drink\Width
		SpriteHeight = ( Height/Distance# )*ProjectionDistance#
		SpriteWidth = Width*( SpriteHeight/Float( Height ) )
		
		Difference# = ATan( ( Drink\Y# - CamY# )/( Drink\X# - CamX# ) )
		If Drink\X# - CamX# < 0 Then Difference# = 180 + Difference#
		Angle# = ( -Difference# - CameraAngle + 360 ) Mod 360
		StartSlice = ( Angle# + ANGLEOFVIEW/2 )/CASTINGSTEP# - SpriteWidth/2
		If ( StartSlice < 0 Or StartSlice > GWIDTH ) And Abs( Angle# ) > 360 - ANGLEOFVIEW/2 - SpriteWidth/2 Then
			Angle# = Angle# - Sgn( Angle# )*360
			StartSlice = ( Angle# + ANGLEOFVIEW/2 )/CASTINGSTEP# - SpriteWidth/2
		EndIf
		
		XStart = StartSlice*( StartSlice >= 0 )
		XEnd = StartSlice + SpriteWidth - 1
		XEnd = XEnd*( XEnd < GWIDTH ) + ( GWIDTH - 1 )*( XEnd > GWIDTH )
		YStart = ( GHEIGHT/2 - Spriteheight/2 + PlaneDisplacement )*( GHEIGHT/2 - SpriteHeight/2 + PlaneDisplacement >= 0 ) 
		YEnd = GHEIGHT/2 + SpriteHeight/2 - 1 + PlaneDisplacement
		YEnd = YEnd*( YEnd <= GHEIGHT ) + GHEIGHT*( YEnd > GHEIGHT )
;**************************************		
		For x = XStart To XEnd-1    	;fixed maybe?
			For y = YStart To YEnd-1	;fixed maybe?
;*****************************************
				If Distances#( x ) > Distance# Then
					ARGB = Drink\ImageData[ Floor( ( x - StartSlice )*( Width/Float( SpriteWidth ) ) )*Drink\Width + ( y - GHEIGHT/2 + SpriteHeight/2 - PlaneDisplacement )*( Height/Float( SpriteHeight ) ) ]
					If ARGB - $FF000000 <> 0 Then
						If x >= 320 Or y >= 200 Then Print x+" "+y+" fifth"
						WritePixelFast x, y, ARGB
					EndIf
				EndIf
			Next
		Next
	Next
End Function

.MapData
Data 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
Data 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2
Data 1, 0, 2, 0, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 0, 2
Data 2, 2, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 2
Data 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2
Data 2, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 2, 0, 2
Data 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 0, 2
Data 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 0, 2
Data 2, 2, 2, 0, 2, 2, 0, 2, 0, 0, 0, 2, 0, 2, 0, 2
Data 2, 2, 2, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2
Data 2, 0, 2, 0, 0, 0, 0, 2, 0, 2, 0, 2, 2, 2, 0, 2
Data 2, 0, 2, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2
Data 2, 0, 2, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 2
Data 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2
Data 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2
Data 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2