Please note that this is only a quickly hacked-up example, and there might be a few bugs... Here is the PB implementation:
Code: Select all
Enumeration
#MaxDistance = 35
#MinX = 1 : #MaxX = 500
#MinY = 1 : #MaxY = 500
EndEnumeration
Structure LOCATION
Terrain . L
Visibility . L
Distance . L
Lighting . L
EndStructure
Global Dim Map . LOCATION ( #MaxX , #MaxY )
Global PX = 5 + Random ( #MaxX - 10 )
Global PY = 5 + Random ( #MaxY - 10 )
CreateImage ( 100 , 71 * 8 , 71 * 8 )
If StartDrawing ( ImageOutput ( 100 ) )
Box ( 0 , 0 , 800 , 800 , #Black )
StopDrawing ( )
EndIf
Macro PointInRange ( X , Y )
( X => #MinX And X <= #MaxX And Y => #MinY And Y <= #MaxY )
EndMacro
Procedure MapMake ( )
For CounterY = #MinY To #MaxY : For CounterX = #MinX To #MaxX
Map ( CounterX , CounterY ) \ Terrain = #Null
Next : Next
For Counter = #MinX To #MaxX : Map ( Counter , #MinY ) \ Terrain = 1 : Next
For Counter = #MinX To #MaxX : Map ( Counter , #MaxY ) \ Terrain = 1 : Next
For Counter = #MinY To #MaxY : Map ( #MinX , Counter ) \ Terrain = 1 : Next
For Counter = #MinY To #MaxY : Map ( #MaxX , Counter ) \ Terrain = 1 : Next
For Counter = 1 To 100
X = Random ( #MaxX - 20 ) + 10
Y = Random ( #MaxY - 20 ) + 10
If Random ( 1 )
Map ( X , Y ) \ Terrain = 1
Else
Map ( X , Y ) \ Terrain = 1
Map ( X , Y + 1 ) \ Terrain = 1
Map ( X + 1 , Y ) \ Terrain = 1
Map ( X + 1 , Y + 1 ) \ Terrain = 1
EndIf
Next
For Counter = 1 To 1000
X = Random ( #MaxX - 30 ) + 5
Y = Random ( #MaxY - 30 ) + 5
If Random ( 1 )
For Z = 1 To Random ( 15 ) : Map ( X , Y + Z ) \ Terrain = 1 : Next
Else
For Z = 1 To Random ( 15 ) : Map ( X + Z , Y ) \ Terrain = 1 : Next
EndIf
Next
For Counter = 1 To 200
Size = Random ( 9 )
X = 10 + Random ( #MaxX - 20 )
Y = 10 + Random ( #MaxY - 20 )
Map ( X , Y ) \ Terrain = 1
For Z = 1 To Size
Map ( X + Z , Y ) \ Terrain = 1
Map ( X , Y + Z ) \ Terrain = 1
Map ( X + Size , Y + Z ) \ Terrain = 1
Map ( X + Z , Y + Size ) \ Terrain = 1
Next
Next
EndProcedure
Procedure MapForget ( )
For X = 1 To #MaxX
For Y = 1 To #MaxY
Map ( X , Y ) \ Visibility = 0
Map ( X , Y ) \ Lighting = 0
Next
Next
EndProcedure
Procedure TileBlocked ( X , Y )
If PointInRange ( X , Y ) And Map ( X , Y ) \ Terrain > #Null
ProcedureReturn #True
EndIf
EndProcedure
Procedure SetTileVisible ( X , Y , Distance )
If PointInRange ( X , Y )
Map ( X , Y ) \ Visibility = #True
Map ( X , Y ) \ Distance = Distance
EndIf
EndProcedure
Procedure SetTileLighting ( X , Y , Distance )
If PointInRange ( X , Y )
Map ( X , Y ) \ Lighting = ( #MaxDistance - Distance ) + Random ( 1 ) - Random ( 1 )
EndIf
EndProcedure
Enumeration
#FovRectangular
#FovCircular
EndEnumeration
Procedure . f Slope ( X1 . f , Y1 . f , X2 . f , Y2 . f )
ProcedureReturn ( X1 - X2 ) / ( Y1 - Y2 )
EndProcedure
Procedure . f InverseSlope ( X1 . f , Y1 . f , X2 . f , Y2 . f )
ProcedureReturn 1 / Slope ( X1 , Y1 , X2 , Y2 )
EndProcedure
Procedure Distance ( X1 , Y1 , X2 , Y2 )
ProcedureReturn Pow ( ( X2 - X1 ) * ( X2 - X1 ) + ( Y2 - Y1 ) * ( Y2 - Y1 ) , 0.5 )
EndProcedure
Procedure ScanOctant1 ( Type , X , Y , Distance , MaxDistance , AlphaSlope . f , OmegaSlope . f , *Function )
If Distance > MaxDistance
ProcedureReturn #Null
EndIf
AlphaX = Int ( X + 0.5 - AlphaSlope * Distance )
OmegaX = Int ( X + 0.5 - OmegaSlope * Distance )
CheckY = Y - Distance
If Type = #FovRectangular And AlphaX <> X - Distance
CallFunctionFast ( *Function , AlphaX , CheckY , Distance )
EndIf
If Type = #FovCircular
AlphaX - 1
EndIf
Blocked = TileBlocked ( AlphaX , CheckY )
For CheckX = AlphaX + 1 To OmegaX
If Type = #FovCircular And Distance ( X , Y , CheckX , CheckY ) > MaxDistance
Continue
EndIf
If CheckX <> X
CallFunctionFast ( *Function , CheckX , CheckY , Distance )
EndIf
If TileBlocked ( CheckX , CheckY )
If Not Blocked
ScanOctant1 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , Slope ( X + 0.5 , Y + 0.5 , CheckX - 0.00001 , CheckY + 0.99999 ) , *Function )
EndIf
Blocked = #True
Else
If Blocked
AlphaSlope = Slope ( X + 0.5 , Y + 0.5 , CheckX , CheckY )
EndIf
Blocked = #False
EndIf
Next
If Not Blocked
ScanOctant1 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , OmegaSlope , *Function )
EndIf
EndProcedure
Procedure ScanOctant2 ( Type , X , Y , Distance , MaxDistance , AlphaSlope . f , OmegaSlope . f , *Function )
If Distance > MaxDistance
ProcedureReturn #Null
EndIf
AlphaX = Int ( X + 0.5 - AlphaSlope * Distance )
OmegaX = Int ( X + 0.5 - OmegaSlope * Distance )
CheckY = Y - Distance
If Type = #FovRectangular And AlphaX <> X - ( -Distance )
CallFunctionFast ( *Function , AlphaX , CheckY , Distance )
EndIf
If Type = #FovCircular
AlphaX + 1
EndIf
Blocked = TileBlocked ( AlphaX , CheckY )
For CheckX = AlphaX - 1 To OmegaX Step -1
If Type = #FovCircular And Distance ( X , Y , CheckX , CheckY ) > MaxDistance
Continue
EndIf
If CheckX <> X
CallFunctionFast ( *Function , CheckX , CheckY , Distance )
EndIf
If TileBlocked ( CheckX , CheckY )
If Not Blocked
ScanOctant2 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , Slope ( X + 0.5 , Y + 0.5 , CheckX + 1.0 , CheckY + 0.99999 ) , *Function )
EndIf
Blocked = #True
Else
If Blocked
AlphaSlope = Slope ( X + 0.5 , Y + 0.5 , CheckX + 0.99999 , CheckY )
EndIf
Blocked = #False
EndIf
Next
If Not Blocked
ScanOctant2 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , OmegaSlope , *Function )
EndIf
EndProcedure
Procedure ScanOctant3 ( Type , X , Y , Distance , MaxDistance , AlphaSlope . f , OmegaSlope . f , *Function )
If Distance > MaxDistance
ProcedureReturn #Null
EndIf
AlphaY = Int ( Y + 0.5 + AlphaSlope * Distance )
OmegaY = Int ( Y + 0.5 + OmegaSlope * Distance )
CheckX = X + Distance
If Type = #FovRectangular And AlphaY <> Y + ( -Distance )
CallFunctionFast ( *Function , CheckX , AlphaY , Distance )
EndIf
If Type = #FovCircular
AlphaY - 1
EndIf
Blocked = TileBlocked ( CheckX , AlphaY )
For CheckY = AlphaY + 1 To OmegaY
If Type = #FovCircular And Distance ( X , Y , CheckX , CheckY ) > MaxDistance
Continue
EndIf
If CheckY <> Y
CallFunctionFast ( *Function , CheckX , CheckY , Distance )
EndIf
If TileBlocked ( CheckX , CheckY )
If Not Blocked
ScanOctant3 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , InverseSlope ( X + 0.5 , Y + 0.5 , CheckX , CheckY - 0.00001 ) , *Function )
EndIf
Blocked = #True
Else
If Blocked
AlphaSlope = InverseSlope ( X + 0.5 , Y + 0.5 , CheckX + 0.99999 , CheckY )
EndIf
Blocked = #False
EndIf
Next
If Not Blocked
ScanOctant3 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , OmegaSlope , *Function )
EndIf
EndProcedure
Procedure ScanOctant4 ( Type , X , Y , Distance , MaxDistance , AlphaSlope . f , OmegaSlope . f , *Function )
If Distance > MaxDistance
ProcedureReturn #Null
EndIf
AlphaY = Int ( Y + 0.5 + AlphaSlope * Distance )
OmegaY = Int ( Y + 0.5 + OmegaSlope * Distance )
CheckX = X + Distance
If Type = #FovRectangular And AlphaY <> Y + Distance
CallFunctionFast ( *Function , CheckX , AlphaY , Distance )
EndIf
If Type = #FovCircular
AlphaY + 1
EndIf
Blocked = TileBlocked ( CheckX , AlphaY )
For CheckY = AlphaY - 1 To OmegaY Step -1
If Type = #FovCircular And Distance ( X , Y , CheckX , CheckY ) > MaxDistance
Continue
EndIf
If CheckY <> Y
CallFunctionFast ( *Function , CheckX , CheckY , Distance )
EndIf
If TileBlocked ( CheckX , CheckY )
If Not Blocked
ScanOctant4 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , InverseSlope ( X + 0.5 , Y + 0.5 , CheckX , CheckY + 1.0 ) , *Function )
EndIf
Blocked = #True
Else
If Blocked
AlphaSlope = InverseSlope ( X + 0.5 , Y + 0.5 , CheckX + 0.99999 , CheckY + 0.99999 )
EndIf
Blocked = #False
EndIf
Next
If Not Blocked
ScanOctant4 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , OmegaSlope , *Function )
EndIf
EndProcedure
Procedure ScanOctant5 ( Type , X , Y , Distance , MaxDistance , AlphaSlope . f , OmegaSlope . f , *Function )
If Distance > MaxDistance
ProcedureReturn #Null
EndIf
AlphaX = Int ( X + 0.5 + AlphaSlope * Distance )
OmegaX = Int ( X + 0.5 + OmegaSlope * Distance )
CheckY = Y + Distance
If Type = #FovRectangular And AlphaX <> X + Distance
CallFunctionFast ( *Function , AlphaX , CheckY , Distance )
EndIf
If Type = #FovCircular
AlphaX + 1
EndIf
Blocked = TileBlocked ( AlphaX , CheckY )
For CheckX = AlphaX - 1 To OmegaX Step -1
If Type = #FovCircular And Distance ( X , Y , CheckX , CheckY ) > MaxDistance
Continue
EndIf
If CheckX <> X
CallFunctionFast ( *Function , CheckX , CheckY , Distance )
EndIf
If TileBlocked ( CheckX , CheckY )
If Not Blocked
ScanOctant5 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , Slope ( X + 0.5 , Y + 0.5 , CheckX + 1.0 , CheckY ) , *Function )
EndIf
Blocked = #True
Else
If Blocked
AlphaSlope = Slope ( X + 0.5 , Y + 0.5 , CheckX + 0.99999 , CheckY + 0.99999 )
EndIf
Blocked = #False
EndIf
Next
If Not Blocked
ScanOctant5 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , OmegaSlope , *Function )
EndIf
EndProcedure
Procedure ScanOctant6 ( Type , X , Y , Distance , MaxDistance , AlphaSlope . f , OmegaSlope . f , *Function )
If Distance > MaxDistance
ProcedureReturn #Null
EndIf
AlphaX = Int ( X + 0.5 + AlphaSlope * Distance )
OmegaX = Int ( X + 0.5 + OmegaSlope * Distance )
CheckY = Y + Distance
If Type = #FovRectangular And AlphaX <> X + ( -Distance )
CallFunctionFast ( *Function , AlphaX , CheckY , Distance )
EndIf
If Type = #FovCircular
AlphaX - 1
EndIf
Blocked = TileBlocked ( AlphaX , CheckY )
For CheckX = AlphaX + 1 To OmegaX
If Type = #FovCircular And Distance ( X , Y , CheckX , CheckY ) > MaxDistance
Continue
EndIf
If CheckX <> X
CallFunctionFast ( *Function , CheckX , CheckY , Distance )
EndIf
If TileBlocked ( CheckX , CheckY )
If Not Blocked
ScanOctant6 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , Slope ( X + 0.5 , Y + 0.5 , CheckX - 0.00001 , CheckY ) , *Function )
EndIf
Blocked = #True
Else
If Blocked
AlphaSlope = Slope ( X + 0.5 , Y + 0.5 , CheckX , CheckY + 0.99999 )
EndIf
Blocked = #False
EndIf
Next
If Not Blocked
ScanOctant6 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , OmegaSlope , *Function )
EndIf
EndProcedure
Procedure ScanOctant7 ( Type , X , Y , Distance , MaxDistance , AlphaSlope . f , OmegaSlope . f , *Function )
If Distance > MaxDistance
ProcedureReturn #Null
EndIf
AlphaY = Int ( Y + 0.5 - AlphaSlope * Distance )
OmegaY = Int ( Y + 0.5 - OmegaSlope * Distance )
CheckX = X - Distance
If Type = #FovRectangular And AlphaY <> Y - ( -Distance )
CallFunctionFast ( *Function , CheckX , AlphaY , Distance )
EndIf
If Type = #FovCircular
AlphaY + 1
EndIf
Blocked = TileBlocked ( CheckX , AlphaY )
For CheckY = AlphaY - 1 To OmegaY Step -1
If Type = #FovCircular And Distance ( X , Y , CheckX , CheckY ) > MaxDistance
Continue
EndIf
If CheckY <> Y
CallFunctionFast ( *Function , CheckX , CheckY , Distance )
EndIf
If TileBlocked ( CheckX , CheckY )
If Not Blocked
ScanOctant7 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , InverseSlope ( X + 0.5 , Y + 0.5 , CheckX + 0.99999 , CheckY + 1.0 ) , *Function )
EndIf
Blocked = #True
Else
If Blocked
AlphaSlope = InverseSlope ( X + 0.5 , Y + 0.5 , CheckX , CheckY + 0.99999 )
EndIf
Blocked = #False
EndIf
Next
If Not Blocked
ScanOctant7 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , OmegaSlope , *Function )
EndIf
EndProcedure
Procedure ScanOctant8 ( Type , X , Y , Distance , MaxDistance , AlphaSlope . f , OmegaSlope . f , *Function )
If Distance > MaxDistance
ProcedureReturn #Null
EndIf
AlphaY = Int ( Y + 0.5 - AlphaSlope * Distance )
OmegaY = Int ( Y + 0.5 - OmegaSlope * Distance )
CheckX = X - Distance
If Type = #FovRectangular And AlphaY <> Y - Distance
CallFunctionFast ( *Function , CheckX , AlphaY , Distance )
EndIf
If Type = #FovCircular
AlphaY - 1
EndIf
Blocked = TileBlocked ( CheckX , AlphaY )
For CheckY = AlphaY + 1 To OmegaY
If Type = #FovCircular And Distance ( X , Y , CheckX , CheckY ) > MaxDistance
Continue
EndIf
If CheckY <> Y
CallFunctionFast ( *Function , CheckX , CheckY , Distance )
EndIf
If TileBlocked ( CheckX , CheckY )
If Not Blocked
ScanOctant8 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , InverseSlope ( X + 0.5 , Y + 0.5 , CheckX + 0.99999 , CheckY - 0.00001 ) , *Function )
EndIf
Blocked = #True
Else
If Blocked
AlphaSlope = InverseSlope ( X + 0.5 , Y + 0.5 , CheckX , CheckY )
EndIf
Blocked = #False
EndIf
Next
If Not Blocked
ScanOctant8 ( Type , X , Y , Distance + 1 , MaxDistance , AlphaSlope , OmegaSlope , *Function )
EndIf
EndProcedure
Procedure ScanNW ( Type , X , Y , MaxDistance , *Function )
For Counter = 1 To MaxDistance
If Type = #FovCircular And Distance ( X , Y , X - Counter , Y - Counter ) > MaxDistance
ProcedureReturn #Null
EndIf
CallFunctionFast ( *Function , X - Counter , Y - Counter , Counter )
If TileBlocked ( X - Counter , Y - Counter )
ProcedureReturn #Null
EndIf
Next
EndProcedure
Procedure ScanN ( Type , X , Y , MaxDistance , *Function )
For Counter = 1 To MaxDistance
CallFunctionFast ( *Function , X , Y - Counter , Counter )
If TileBlocked ( X , Y - Counter )
ProcedureReturn #Null
EndIf
Next
EndProcedure
Procedure ScanNE ( Type , X , Y , MaxDistance , *Function )
For Counter = 1 To MaxDistance
If Type = #FovCircular And Distance ( X , Y , X + Counter , Y - Counter ) > MaxDistance
ProcedureReturn #Null
EndIf
CallFunctionFast ( *Function , X + Counter , Y - Counter , Counter )
If TileBlocked ( X + Counter , Y - Counter )
ProcedureReturn #Null
EndIf
Next
EndProcedure
Procedure ScanE ( Type , X , Y , MaxDistance , *Function )
For Counter = 1 To MaxDistance
CallFunctionFast ( *Function , X + Counter , Y , Counter )
If TileBlocked ( X + Counter , Y )
ProcedureReturn #Null
EndIf
Next
EndProcedure
Procedure ScanSE ( Type , X , Y , MaxDistance , *Function )
For Counter = 1 To MaxDistance
If Type = #FovCircular And Distance ( X , Y , X + Counter , Y + Counter ) > MaxDistance
ProcedureReturn #Null
EndIf
CallFunctionFast ( *Function , X + Counter , Y + Counter , Counter )
If TileBlocked ( X + Counter , Y + Counter )
ProcedureReturn #Null
EndIf
Next
EndProcedure
Procedure ScanS ( Type , X , Y , MaxDistance , *Function )
For Counter = 1 To MaxDistance
CallFunctionFast ( *Function , X , Y + Counter , Counter )
If TileBlocked ( X , Y + Counter )
ProcedureReturn #Null
EndIf
Next
EndProcedure
Procedure ScanSW ( Type , X , Y , MaxDistance , *Function )
For Counter = 1 To MaxDistance
If Type = #FovCircular And Distance ( X , Y , X - Counter , Y + Counter ) > MaxDistance
ProcedureReturn #Null
EndIf
CallFunctionFast ( *Function , X - Counter , Y + Counter , Counter )
If TileBlocked ( X - Counter , Y + Counter )
ProcedureReturn #Null
EndIf
Next
EndProcedure
Procedure ScanW ( Type , X , Y , MaxDistance , *Function )
For Counter = 1 To MaxDistance
CallFunctionFast ( *Function , X - Counter , Y , Counter )
If TileBlocked ( X - Counter , Y )
ProcedureReturn #Null
EndIf
Next
EndProcedure
Procedure CastLight ( X , Y , Radius )
*Function = @SetTileLighting ( )
ScanNW ( #FovCircular , X , Y , Radius , *Function )
ScanN ( #FovCircular , X , Y , Radius , *Function )
ScanNE ( #FovCircular , X , Y , Radius , *Function )
ScanE ( #FovCircular , X , Y , Radius , *Function )
ScanSE ( #FovCircular , X , Y , Radius , *Function )
ScanS ( #FovCircular , X , Y , Radius , *Function )
ScanSW ( #FovCircular , X , Y , Radius , *Function )
ScanW ( #FovCircular , X , Y , Radius , *Function )
ScanOctant1 ( #FovCircular , X , Y , 1 , Radius , 1.0 , 0 , *Function )
ScanOctant2 ( #FovCircular , X , Y , 1 , Radius , -1.0 , 0 , *Function )
ScanOctant3 ( #FovCircular , X , Y , 1 , Radius , -1.0 , 0 , *Function )
ScanOctant4 ( #FovCircular , X , Y , 1 , Radius , 1.0 , 0 , *Function )
ScanOctant5 ( #FovCircular , X , Y , 1 , Radius , 1.0 , 0 , *Function )
ScanOctant6 ( #FovCircular , X , Y , 1 , Radius , -1.0 , 0 , *Function )
ScanOctant7 ( #FovCircular , X , Y , 1 , Radius , -1.0 , 0 , *Function )
ScanOctant8 ( #FovCircular , X , Y , 1 , Radius , 1.0 , 0 , *Function )
EndProcedure
Procedure CastVision ( X , Y , Distance , Type )
*Function = @SetTileVisible ( )
ScanNW ( Type , X , Y , Distance , *Function )
ScanN ( Type , X , Y , Distance , *Function )
ScanNE ( Type , X , Y , Distance , *Function )
ScanE ( Type , X , Y , Distance , *Function )
ScanSE ( Type , X , Y , Distance , *Function )
ScanS ( Type , X , Y , Distance , *Function )
ScanSW ( Type , X , Y , Distance , *Function )
ScanW ( Type , X , Y , Distance , *Function )
ScanOctant1 ( Type , X , Y , 1 , Distance , 1.0 , 0 , *Function )
ScanOctant2 ( Type , X , Y , 1 , Distance , -1.0 , 0 , *Function )
ScanOctant3 ( Type , X , Y , 1 , Distance , -1.0 , 0 , *Function )
ScanOctant4 ( Type , X , Y , 1 , Distance , 1.0 , 0 , *Function )
ScanOctant5 ( Type , X , Y , 1 , Distance , 1.0 , 0 , *Function )
ScanOctant6 ( Type , X , Y , 1 , Distance , -1.0 , 0 , *Function )
ScanOctant7 ( Type , X , Y , 1 , Distance , -1.0 , 0 , *Function )
ScanOctant8 ( Type , X , Y , 1 , Distance , 1.0 , 0 , *Function )
CastLight ( X , Y , #MaxDistance / 2 )
EndProcedure
Procedure Draw ( )
If StartDrawing ( ImageOutput ( 100 ) )
Box ( 0 , 0 , ImageWidth ( 100 ) , ImageHeight ( 100 ) , #Black )
Width = 8
Height = 8
For CounterY = PY - 35 To PY + 35
For CounterX = PX - 35 To PX + 35
If PointInRange ( CounterX , CounterY )
If Map ( CounterX , CounterY ) \ Visibility
TargetX = ( CounterX - PX + 35 ) * Width
TargetY = ( CounterY - PY + 35 ) * Height
Distance = Map ( CounterX , CounterY ) \ Distance
If Map ( CounterX , CounterY ) \ Terrain = 0 : Color = RGB ( 120 - Distance , 120 - Distance , 120 - Distance ) : EndIf
If Map ( CounterX , CounterY ) \ Terrain = 1 : Color = RGB ( 180 - Distance , 180 - Distance, 180 - Distance ) : EndIf
Lighting = Map ( CounterX , CounterY ) \ Lighting
If Lighting
Color = RGB ( Red ( Color ) + Lighting , Green ( Color ) + Lighting , Blue ( Color ) + Lighting )
EndIf
Box ( TargetX , TargetY , Width , Height , Color )
EndIf
EndIf
Next
Next
Box ( 35 * Width , 35 * Height , Width , Height , #White )
StopDrawing ( )
EndIf
EndProcedure
OpenWindow ( 0 , 0 , 0 , ImageWidth ( 100 ) , ImageHeight ( 100 ) , "" , #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered )
If CreateGadgetList ( WindowID ( 0 ) ) : ImageGadget ( 1 , 0 , 0 , 200 , 200 , ImageID ( 100 ) ) : EndIf
MapMake ( ) : CastVision ( PX , PY , #MaxDistance , #FovCircular ) : Changed = #True
Repeat
Event = WaitWindowEvent ( )
Select Event
Case #WM_KEYDOWN
Select EventwParam ( )
Case #VK_LEFT
If Not TileBlocked ( PX - 1 , PY ) And PointInRange ( PX - 1 , PY )
PX - 1 : MapForget ( ) : CastVision ( PX , PY , #MaxDistance , 1 ) : Changed = #True
EndIf
Case #VK_RIGHT
If Not TileBlocked ( PX + 1 , PY ) And PointInRange ( PX + 1 , PY )
PX + 1 : MapForget ( ) : CastVision ( PX , PY , #MaxDistance , 1 ) : Changed = #True
EndIf
Case #VK_UP
If Not TileBlocked ( PX , PY - 1 ) And PointInRange ( PX , PY - 1 )
PY - 1 : MapForget ( ) : CastVision ( PX , PY , #MaxDistance , 1 ) : Changed = #True
EndIf
Case #VK_DOWN
If Not TileBlocked ( PX , PY + 1 ) And PointInRange ( PX , PY + 1 )
PY + 1 : MapForget ( ) : CastVision ( PX , PY , #MaxDistance , 1 ) : Changed = #True
EndIf
EndSelect
EndSelect
If Changed
Draw ( ) : SetGadgetState ( 1 , ImageID ( 100 ) ) : Changed = #False
EndIf
If Event = #PB_Event_CloseWindow
Break
EndIf
ForEver