Code archives/Graphics/3D Maze

This code has been declared by its author to be Public Domain code.

Download source code

3D Maze by jfk EO-11110
(Posted 24 years ago)
Simple 2.5D Raycasting Engine, enjoy.
Graphics 320,240,16,2
SetBuffer BackBuffer()

; read level data
Dim grid(15,15)
For j=0 To 15
 For i=0 To 15
  Read grid(i,j)
 Next
Next
Dim rgb(9,2)
For i=1 To 9
 Read rgb(i,0):Read rgb(i,1):Read rgb(i,2)
Next

Global px#=8.0
Global pz#=8.0
Global a#, pxold#=0.0, pzold#=0.0, premind#, info$
;__________________________MAINLOOP_________________________
While KeyDown(1)=0
 Cls
 If KeyDown(200) Then ; up
  pxold=px
  pzold=pz
  px=px+Sin(a)/5.0
  pz=pz+Cos(a)/5.0
  sliding()
 EndIf
 If KeyDown(208) Then ; down
  pxold=px
  pzold=pz
  px=px-Sin(a)/5.0
  pz=pz-Cos(a)/5.0
  sliding()
 EndIf
 a=(a-mxs#) Mod 360 ; use mouse to steer
 raycast() ; do magic (well, actually not)
 Color 0,255,0 ; map info onscreen...
 Line (px*5-Sin(a)*2),(pz*5-Cos(a)*2),(px*5+Sin(a)*2),(pz*5+Cos(a)*2)
 Color 255,0,0
 Oval (px*5+(Sin(a)*2))-1,(pz*5+(Cos(a)*2))-1,2,2
 Color 127,127,127
 For j=0 To 15
  For i=0 To 15
   If grid(i,j)<>0
    Rect i*5-3,j*5-3,5,5,0
   EndIf
  Next
 Next
 If info$<>"" Then Text GraphicsWidth()/2,GraphicsHeight()/2,info$,1,1
 Flip
 mxs#=MouseXSpeed()/3.0 ; used by steer
 MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
Wend
End
;________________________eo mainloop__________________________

Function sliding()
  If grid(px,pz)<>0 ; sliding collision...
   premind=px
   px=pxold
   If grid(px,pz)<>0
    px=premind
    pz=pzold
    If grid(px,pz)<>0
     px=pxold
    EndIf
   EndIf
  EndIf
End Function

Function raycast()
 For i=-160 To 159
  rayx#=px
  rayz#=pz
  stepx#=Sin(a+0.125*i)/50.0  ; pretty small steps - would be way to slow on old machines
  stepz#=Cos(a+0.125*i)/50.0
  count=0
  touched=0
  While touched=0 And count<1000
   rayx#=rayx+stepx
   rayz#=rayz+stepz
   count=count+1
   If grid(rayx,rayz)<>0 Then
    touched=grid(rayx,rayz)
   EndIf
  Wend
  If touched<>0 Then
   h#=7000.0/count
   bright#=(h#+20.0)/127.0
   If bright>1.0 Then bright=1.0
   Color rgb(touched,0)*bright,rgb(touched,1)*bright,rgb(touched,2)*bright
   Line 160-i,120-h,160-i,120+h
   If touched=9
    If info$=""
     info$="Level Exit found!!! Congratzz!!!"
    EndIf
   EndIf
  EndIf
 Next
End Function

; map
Data 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
Data 2,9,0,0,1,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,4,3,5,6,5,6,0,0,0,2
Data 2,0,1,3,4,2,2,0,0,0,0,2,3,0,0,1
Data 1,2,1,0,0,0,2,1,4,0,0,1,2,2,0,2
Data 2,0,0,0,4,0,0,0,7,0,0,0,1,0,0,1
Data 1,0,8,4,3,0,0,0,0,0,0,0,1,2,0,2
Data 2,0,7,0,0,0,0,0,0,4,5,4,1,0,0,1
Data 1,0,6,0,0,1,0,0,0,1,0,0,2,2,0,2
Data 2,0,5,1,2,1,3,0,1,1,0,0,0,0,0,1
Data 1,0,4,0,0,0,0,0,2,4,2,4,2,2,0,2
Data 2,0,3,1,0,0,0,0,0,0,3,0,0,1,0,1
Data 1,0,2,1,1,0,0,0,0,0,0,0,0,1,0,2
Data 2,0,1,2,3,4,5,4,5,4,5,5,6,3,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
Data 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1

; wall colors: 1,2,3...
Data 127,127,255
Data 64,64,255
Data 255,127,255
Data 255,0,0
Data 0,255,0
Data 0,0,255
Data 255,0,255
Data 0,255,255
Data 255,255,0
Data 255,255,255

Comments

impixi
(Posted 20 years ago)
BlitzMax port and modification:

SuperStrict

Graphics 320,240

Local MV:TMazeView = New TMazeView
MV.loadMap
MV.loadColors

Local a:Float
Local mxs:Float

Local OldTime:Int = 0
Local CurTime:Int

HideMouse

' *** MAIN LOOP ***

While Not KeyHit(KEY_ESCAPE)

	Local mxs:Float = (MouseX() - GraphicsWidth() / 2) / 3.0
	MoveMouse (GraphicsWidth() / 2), (GraphicsHeight() / 2)

	Cls
 
	CurTime = 1000 / (MilliSecs() - OldTime)
 	OldTime = MilliSecs()

	If KeyDown(KEY_W)
		MV.moveForward a
	EndIf
	
	If KeyDown(KEY_S) 
		MV.moveBackward a
	EndIf
	
	If KeyDown(KEY_Q) 'turn left 
		a :+ 2
 	EndIf

	If KeyDown(KEY_E) 'turn right
		a :- 2
 	EndIf
	
	a = (a - mxs) Mod 360 
	
 	MV.raycast a 

	MV.drawMap a 

 	If MV.info <> "" Then DrawText MV.info, 1, (GraphicsHeight() - 20)

 	DrawText "WQSE and mouse to move. FPS:" + CurTime, 1, (GraphicsHeight() - (2 * 20))

	Flip 1

Wend

End


Type TMazeView

	Field Cols:Int
	Field Rows:Int
	Field Grid:Int[,]
	Field RGB:Byte[,]

	Field px:Float 
	Field pxold:Float
	Field pz:Float
	Field pzold:Float
	Field premind:Float
	
	Field info:String

	Method New()
	
		Cols = 16
		Rows = 16
		Grid = New Int[cols, rows]
		RGB = New Byte[10, 3]
	
		px = 8.0
		pxold = 0.0
		pz = 8.0
		pzold = 0.0
		
		info = ""	
	
	EndMethod

	Method loadMap()

		RestoreData Map

		For Local j:Int = 0 To Rows - 1
			For Local i:Int = 0 To Cols - 1
				ReadData Grid[i, j]
 			Next
		Next
	
	EndMethod
	
	Method loadColors()
	
		RestoreData Colors 
		For Local i:Int = 0 To 9
			ReadData RGB[i, 0]
 			ReadData RGB[i, 1]
			ReadData RGB[i, 2]
		Next
	
	EndMethod

	Method checkCollision()
	
		If Grid[px, pz] <> 0 
  			premind = px
			px = pxold
   			If Grid[px, pz] <> 0
				px = premind
				pz = pzold
			    If Grid[px, pz] <> 0
					px = pxold
				EndIf
			EndIf
		 EndIf

	EndMethod

	Method drawMap(a:Float)
				
		SetColor 0,255,0
	
 		DrawLine (px * 5 - Sin(a) * 2), (pz * 5 - Cos (a) * 2), (px * 5 + Sin(a) * 2), (pz * 5 + Cos(a) * 2)
		SetColor 255, 0, 0
	
		DrawOval (px * 5 + (Sin(a) * 2)) - 1, (pz * 5 + (Cos(a) * 2)) - 1, 2, 2
	
		SetColor 127, 127, 127

		SetBlend ALPHABLEND
		SetAlpha 0.5

		For Local j:Int = 0 To (Rows - 1)
  			For Local i:Int = 0 To (Cols - 1)
   				If Grid[i, j] <> 0
    				DrawRect (i * 5 - 3), (j * 5 - 3), 5, 5
				EndIf
			Next
		Next
	
		SetBlend SOLIDBLEND
	
	EndMethod

	Method moveForward(a:Float)

  		pxold = px
  		pzold = pz
  		px :+ Sin(a) / 5.0
  		pz :+ Cos(a) / 5.0
  		CheckCollision

	EndMethod

	Method moveBackward(a:Float)
	
		pxold = px
		pzold = pz
		px :- Sin(a) / 5.0
		pz :- Cos(a) / 5.0
		CheckCollision
		
	EndMethod

	Method raycast(a:Float)
	
		For Local i:Int = -160 To 159
		
			Local rayx:Float = px
			Local rayz:Float = pz
			Local stepx:Float = Sin(a + 0.125 * i) / 50.0  
  			Local stepz:Float = Cos( a + 0.125 * i) / 50.0
  			Local count:Int = 0
  			Local touched:Int = 0
			
			While touched = 0 And count < 1000
		  		rayx :+ stepx
				rayz :+ stepz
				count :+ 1
				If Grid[rayx, rayz] <> 0 Then touched = Grid[rayx, rayz]
			Wend
			
			If touched <> 0 
				Local h:Float = 7000.0 / count
				Local bright:Float = (h + 20.0) / 127.0
				If bright > 1.0 Then bright = 1.0
				SetColor RGB[touched, 0] * bright, RGB[touched, 1] * bright, RGB[touched, 2] * bright
				DrawLine 160 - i, 120 - h, 160 - i, 120 + h
				If touched = 9
				    If info = ""
						info = "Level Exit found!!! Congratzz!!!"
					EndIf
				EndIf
			EndIf
			
		Next
	
	EndMethod

EndType


#Map
DefData 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
DefData 2,9,0,0,1,0,0,0,0,0,0,0,0,0,0,1
DefData 1,0,0,0,0,0,4,3,5,6,5,6,0,0,0,2
DefData 2,0,1,3,4,2,2,0,0,0,0,2,3,0,0,1
DefData 1,2,1,0,0,0,2,1,4,0,0,1,2,2,0,2
DefData 2,0,0,0,4,0,0,0,7,0,0,0,1,0,0,1
DefData 1,0,8,4,3,0,0,0,0,0,0,0,1,2,0,2
DefData 2,0,7,0,0,0,0,0,0,4,5,4,1,0,0,1
DefData 1,0,6,0,0,1,0,0,0,1,0,0,2,2,0,2
DefData 2,0,5,1,2,1,3,0,1,1,0,0,0,0,0,1
DefData 1,0,4,0,0,0,0,0,2,4,2,4,2,2,0,2
DefData 2,0,3,1,0,0,0,0,0,0,3,0,0,1,0,1
DefData 1,0,2,1,1,0,0,0,0,0,0,0,0,1,0,2
DefData 2,0,1,2,3,4,5,4,5,4,5,5,6,3,0,1
DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
DefData 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1

#Colors
DefData 127,127,255
DefData 64,64,255
DefData 255,127,255
DefData 255,0,0
DefData 0,255,0
DefData 0,0,255
DefData 255,0,255
DefData 0,255,255
DefData 255,255,0
DefData 255,255,255



PS: JFK EO-11110, you're a legend. Thanks for the code.

jfk EO-11110
(Posted 20 years ago)
Thank you :)

Code Archives Forum