Something I did a while ago and forgot about.
I found a raycast tutorial and follow that.
Set Display Mode 800,600,16
autocam off
Sync On
Sync Rate 60
set text size 15
Hide mouse
Make Matrix 1,2048,2048,32,32
ink rgb(255,255,255),1
Set camera range 0,0.1,2500
Color backdrop Rgb(197,197,225)
MAKE OBJECT SPHERE 1,5
color object 1,rgb(255,0,0)
set object ambient 1,0
randomize timer()
cls
Dim map(50,50)
cls
FOR I=1000 TO 1064
XX=RND(30)+1
ZZ=RND(30)+1
RNDH=200
`200+(RND(5)*55)
if map(XX,ZZ)<1
map(XX,ZZ)=RNDH
MAKE OBJECT BOX 1000+I,64,RNDH,64
color object 1000+I,rgb(0,0,255)
POSITION OBJECT 1000+I,(64*XX)+32,RNDH/2,(64*ZZ)+32
endif
next I
Speed# = 10
make object plain 2,32,32
position object 2,0,0,200
ink rgb(255,0,0),1
line 12,16,14,16
line 12,15,14,15
line 18,16,20,16
line 18,15,20,15
line 16,18,16,20
line 15,18,15,20
get image 1,0,0,32,32
texture object 2,1
set object 2,1,1,0
lock object on 2
POSITION CAMERA 1024,100,1024
While SpaceKey() = 0
IF mouseclick()=1 THEN MOVE CAMERA 6
IF mouseclick()=2 THEN MOVE CAMERA -6
Gridx=CAMERA position x()/64
Gridz=CAMERA position Z()/64
CAM_X#=CAMERA POSITION X()
CAM_HEIGHT#=CAMERA POSITION Y()
CAM_Z#=CAMERA POSITION Z()
`LET THERE BE TRIG
CAM_ANG_Y# =camera angle y()
CAM_ANG_X# =camera angle X()
SIN_y#=sin(CAM_ANG_Y#)
COS_y#=cos(CAM_ANG_Y#)
IF CAM_ANG_Y#<>OLD_Cy# OR CAM_ANG_X#<>OLD_Cx#
GOSUB VCHECK
GOSUB HCHECK
Ax# =90-CAM_ANG_X#
RADIUS#=CAM_HEIGHT#*TAN(Ax#)
NY#=RADIUS#*COS_y#
NX#=RADIUS#*SIN_y#
CROSS_Y#=CAM_HEIGHT#-(Vdist*TAN(CAM_ANG_X#))
IF CROSS_Y#<0 or Vdist=10000
POSITION OBJECT 1,CAM_X#+NX#,0,CAM_Z#+NY#:text 0,20,"FLOOR"
ELSE
POSITION OBJECT 1,CROSS_X#,CROSS_Y#,CROSS_Z#
ENDIF
OLD_Cy#=CAM_ANG_Y#
OLD_Cx#=CAM_ANG_X#
ENDIF
text 0,150,STR$(screen fps())
`Rotation controls
_AngleX# = WrapValue( _AngleX# + MouseMoveY() )
_AngleY# = WrapValue( _AngleY# + MouseMoveX() )
Current_AngleX# = CurveAngle(_AngleX#,Current_AngleX#,Speed#)
Current_AngleY# = CurveAngle(_AngleY#,Current_AngleY#,Speed#)
XRotate Camera Current_AngleX#
YRotate Camera Current_AngleY#
Sync
EndWhile
VCHECK:
I=0:Vdist=10000
if SIN_y#>0
NEWV_GRID#=((Gridx+1)*64)+1:DIRV_GRID#=64
else NEWV_GRID#=(Gridx*64)-1:DIRV_GRID#=-64
endif
OPP#=(NEWV_GRID#-CAM_X#)*tan(CAM_ANG_Y#-90)
NEW_Z#=CAM_Z#-OPP#
Ya#=DIRV_GRID#*tan(CAM_ANG_Y#-90)
WHILE I<33
Gridx2=(NEWV_GRID#+(DIRV_GRID#*I))/64
Gridz2=(NEW_Z#-(Ya#*I))/64
if Gridz2>0 and Gridz2<33
IF map(Gridx2,Gridz2)>1
CROSS_X#=NEWV_GRID#+(DIRV_GRID#*I)
CROSS_Z#=NEW_Z#-(Ya#*I):
Vdist=sqrt((CAM_X#-CROSS_X#)^2 + (CAM_Z#-CROSS_Z#)^2)
if CAM_HEIGHT#-(Vdist*TAN(CAM_ANG_X#))<map(Gridx2,Gridz2) then I=33
ENDIF
ELSE I=33
ENDIF
I=I+1
ENDWHILE
RETURN
HCHECK:
I=0:Hdist=10000
if COS_y#>0
NEWH_GRID#=((Gridz+1)*64)+1:DIRH_GRID#=-64
else NEWH_GRID#=(Gridz*64)-1:DIRH_GRID#=64
endif
MM#=-DIRH_GRID#
Adjacent#=(CAM_Z#-NEWH_GRID#)/tan(CAM_ANG_Y#-90)
NEW_X#=CAM_X#+Adjacent#
Xa# = DIRH_GRID#/tan(CAM_ANG_Y# -90)
WHILE I<33
Gridx3=(NEW_X#+(Xa#*I))/64
Gridz3=(NEWH_GRID#+(MM#*I))/64
if Gridx3>0 and Gridx3<33 and Gridz3>0 and Gridz3<33
IF map(Gridx3,Gridz3)>1
CROSS_X2#=NEW_X#+(Xa#*I)
CROSS_Z2#=NEWH_GRID#+(MM#*I):
Hdist=sqrt((CAM_X#-CROSS_X2#)^2 + (CAM_Z#-CROSS_Z2#)^2)
if CAM_HEIGHT#-(Hdist*TAN(CAM_ANG_X#))<map(Gridx3,Gridz3) then I=33
Endif
ELSE I=33
endif
I=I+1
ENDWHILE
IF Hdist<Vdist THEN CROSS_X#=CROSS_X2#:CROSS_Z#=CROSS_Z2#:Vdist=Hdist
RETURN
Deano
"When I examine myself and my methods of thought, I come to the conclusion that the gift of fantasy has meant more than my talent for absorbing positive knowledge."
-ALBERT EINSTEIN