Efficient RTS "fog of war" setup.

Blitz3D Forums/Blitz3D Programming/Efficient RTS "fog of war" setup.

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Forgive the lengthly code, its mostly remarks




;the Psuedo Grid (500,500) is equal to real world 0,0
;if =0 then invisable area, =1 then visable
Dim mapgrid(1000,1000)

;This is how large each grid square will be in real XZ world values
;meaning our virtual grid squares are 20x20 on x+z axi in 3d space
Global gridindex=20

;globals required for the BANK functions
;all of our checks will be at an offset of 500
;this is because our bank array cannot go into negative numbers
;using 500 offset makes 500 equal to 0,0 of real 3d space.. now 0,0
;of our grid is equal to -500*gridindex,-500*gridindex of real 3d XZ space
Global MapBank,CleanBank
mapbank=makebank(1000,1000)
CleanBank=makebank(1000,1000)


;how often we will zero out the vitual grid
Global DetailFogtimer#=MilliSecs()+100


;tree type
Type tree
Field entity
Field woodleft
Field Visable
End Type


;all units have these properties
Type Unit
Field Friendly
Field Visable
Field Entity
End Type



Graphics3D 640,480
;our camera
camera=CreateCamera()
temp=CreatePivot()
PositionEntity camera,10,60,-40
PointEntity camera,temp
FreeEntity temp
CameraFogMode camera,1
CameraFogColor camera,100,100,100
CameraFogRange camera,5,110

;create friendly unit
U.unit=New unit
u\friendly=True
u\visable=True
EntityParent camera,u\entity
u\entity=CreateCube()
EntityColor u\entity,0,0,200
PositionEntity u\entity,Rand(-20,20),0,Rand(-20,20)

;create a few enemies
For i=1 To 200
U.unit=New unit
u\friendly=False
u\visable=False

u\entity=CreateCube()
EntityColor u\entity,200,0,0
PositionEntity u\entity,Rand(-35,35),0,Rand(-35,35)
Next



;put some ground underneath it all
ground=CreatePlane()
EntityColor ground,0,100,0


For I=1 To 100
t.tree=New tree
T\entity=CreateCone()
PositionEntity t\entity,Rand(-100,100),0,Rand(-100,100)
EntityAlpha t\entity,.3
EntityColor t\entity,0,200,0
ScaleEntity t\entity,14,14,14
Next

;main loop
While Not KeyDown(1)
If MilliSecs()>detailfogtimer# Then
detailfogtimer#=MilliSecs()+200
detailfog()
EndIf

moving#=0
turn#=0
If KeyDown(200) Then Moving#=.3
If KeyDown(203) Then turn#=-2
If KeyDown(205) Then turn#=2
For u.unit=Each unit
checkgridarea(u)
;if unit is friendly we change grid he is in to
;visable, if unit is enemy we just check to see if he is
;inside of a visable area or invisable area, in in visable
;we change his alpha and visable state.
If u\friendly=True Then
MoveEntity u\entity,0,0,moving
TurnEntity u\entity,0,turn,0
Else
MoveEntity u\entity,0,0,-.1
TurnEntity u\entity,0,.35,0
EndIf
Next
RenderWorld()
UpdateWorld()
Flip
Wend


Function CheckGridArea(cu.unit)
entity=cu\entity
Px=EntityX(entity,1)
Pz=EntityZ(entity,1)
gridX=Int((px/gridindex))+500
gridZ=Int((pz/gridindex))+500
If cu\friendly=True Then
If Getbank(Mapbank,Gridx,Gridz,4000)=0 Then
Putbank(Mapbank,gridx,gridz,4000,1)
;tree check not neccessary in an rts game as
;you cn usually see the terrain. You could get
;by with only unit checks. wich are fast.
For t.tree=Each tree
If t\visable=0 Then
If EntityDistance(t\entity,entity)<=GridIndex Then
t\visable=1
EntityAlpha t\entity,1
EndIf
EndIf
Next
EndIf
Else
;enemy/unfriendly unit check.. does not reveal map
;only reveals unit if map area is already explored
If Getbank(mapbank,gridx,gridz,4000)=1 Then
cu\visable=1
EntityAlpha cu\entity,1
Else
cu\visable=0
EntityAlpha cu\entity,0
EndIf
EndIf
End Function





Function detailfog()
;this function will set the whole grid back to 0
;meaning unexplored. Terrain should have a way
;to stay visable.. here is how I did it. When terrain
;is in sight, its alpha is chaged from a low number to 1
;this will change it to visable regardless of the grid value
;units are different, they always check grid value to see
;if they should be visable. So when a friendly unit is not
;nearby they are not visable.
CopyBank cleanbank,1,mapbank,1,4000000
;if you remove the call to this function. Enemy units will
;remain visable in areas the player has been, even if player
;is no longer there
End Function

Function MakeBank(Xlen,Ylen)
;makes a bank with the 2 dimensions you specify
Mybank=CreateBank((xlen*4)*(ylen*4))
Return Mybank
End Function

Function GetBank(Bank,Xindex,Yindex,AXlen)
;will return the value in the bank. Lets you use it
;like a 2 dimensional array though. AXLEN is the first
;arrays max length.. so in b=CREATEBANK(10,20)
;you would call Getbank(b,x,y,10)
Return PeekInt(bank,((Yindex-1)*(AXlen)+((Xindex-1)*4)-1))
End Function

Function PutBank(Bank,Xindex,Yindex,AXlen,VALUE)
;same as getbank but you insert a value
PokeInt(bank,((Yindex-1)*(AXlen)+((Xindex-1)*4)-1),value)
End Function