Around each agent flow fields are placed direction agents who want to travel
in their path around them. On the map itself random flowfields are placed.
The code does not work 100% correctly yet since sometimes agents go through
each other.
Import mojo
Class flowfield
Field mapwidth:Int,mapheight:Int
Field tilewidth:Float,tileheight:Float
Field screenwidth:Int,screenheight:Int
Field map:Int[][]
Field tempmap:Int[][]
Field flowlinestartx:Int
Field flowlinestarty:Int
Method New(screenwidth:Int,screenheight:Int,mapwidth:Int,mapheight:Int)
Self.screenwidth = screenwidth
Self.screenheight = screenheight
Self.tilewidth = Float(screenwidth)/Float(mapwidth)
Self.tileheight = Float(screenheight)/Float(mapheight)
Self.mapwidth = mapwidth
Self.mapheight = mapheight
' make a array
map = New Int[mapwidth][]
tempmap = New Int[mapwidth][]
For Local i = 0 Until mapwidth
map[i] = New Int[mapheight]
tempmap[i] = New Int[mapheight]
Next
' -1 if no direction
For Local y:=0 Until mapheight
For Local x:=0 Until mapheight
map[x][y] = -1
Next
Next
'
' Here we create a number of points
' with which we draw the lines in between.
'
Seed = GetDate[5]
Local lastx:Int=Rnd(2,mapwidth-2)
Local lasty:Int=Rnd(2,mapheight-2)
flowlinestartx = lastx
flowlinestarty = lasty
For Local i:=0 Until mapwidth*mapheight/10
Local newx:Int=Rnd(2,mapwidth-2)
Local newy:Int=Rnd(2,mapheight-2)
flowline(lastx,lasty,newx,newy)
lastx=newx
lasty=newy
Next
End Method
'copy temp into map
Method refreshmap()
For Local y:=0 Until mapheight
For Local x:=0 Until mapwidth
map[x][y] = tempmap[x][y]
Next
Next
End Method
' Make a flowfield(line) between two points
Method flowline(x1:Int,y1:Int,x2:Int,y2:Int)
Local dx:Int, dy:Int, sx:Int, sy:Int, e:Int
dx = Abs(x2 - x1)
sx = -1
If x1 < x2 Then sx = 1
dy = Abs(y2 - y1)
sy = -1
If y1 < y2 Then sy = 1
If dx < dy Then
e = dx / 2
Else
e = dy / 2
End If
Local exitloop:Bool=False
While exitloop = False
'SetColor 255,255,255
'DrawPoint x1,y1
If x1 = x2
If y1 = y2
exitloop = True
End If
End If
For Local y:=-6 To 6
For Local x:=-6 To 6
If x1+x<0 Or x1+x>=mapwidth Or y1+y<0 Or y1+y>=mapheight Then continue
map[x1+x][y1+y] = pointto(x1+x,y1+y,x1,y1)
Next
Next
map[x1][y1] = pointto(x1,y1,x2,y2)
If dx > dy Then
x1 += sx ; e -= dy
If e < 0 Then e += dx ; y1 += sy
Else
y1 += sy ; e -= dx
If e < 0 Then e += dy ; x1 += sx
Endif
Wend
' put contents in tempmap
For Local y:=0 Until mapheight
For Local x:=0 Until mapwidth
tempmap[x][y] = map[x][y]
Next
Next
End Method
' point the flow field direction to the x2,y2 from x1,y1
Function pointto:Int(x1:Int,y1:Int,x2:Int,y2:Int)
Local nd:Int=-1
If x1<x2 Then nd=0
If x1>x2 Then nd=4
If y1<y2 Then nd=2
If y1>y2 Then nd=6
If x1<x2 And y1<y2 Then nd=1
If x1>x2 And y1<y2 Then nd=3
If x1<x2 And y1>y2 Then nd=7
If x1>x2 And y1>y2 Then nd=5
Return nd
End Function
Method draw()
SetColor 255,255,255
For Local y:=0 Until mapheight
For Local x:=0 Until mapwidth
Local direction:Int = map[x][y]
If direction=-1 Then Continue
Local x1:Float=Float(x)*tilewidth+tilewidth/2
Local y1:Float=Float(y)*tileheight+tileheight/2
Local ang:Int= (360/8*direction)
Local x2:Float=x1+(Cos(ang)*tilewidth/2)
Local y2:Float=y1+(Sin(ang)*tileheight/2)
Local x3:Float=x1+(Cos(ang+150)*tilewidth/4)
Local y3:Float=y1+(Sin(ang+150)*tileheight/4)
Local x4:Float=x1+(Cos(ang-150)*tilewidth/4)
Local y4:Float=y1+(Sin(ang-150)*tileheight/4)
DrawPoly([x2,y2,x3,y3,x4,y4])
Next
Next
End Method
End Class
Class alien
Field alienx:Float,alieny:Float
Field speed:Float
Method New(x:Int,y:Int)
Self.alienx = x
Self.alieny = y
Self.speed = Rnd(0.1,1)
End Method
'
' here we modify the flowfield so that other units can move around the
' unit. We do this by placing arrows around the unit based on his direction.
Method modifyflowmap()
Local x:Int=alienx / myflowfield.tilewidth
Local y:Int=alieny / myflowfield.tileheight
If x-1<0 Or x+1>=myflowfield.mapwidth Or y-1<0 Or y+1>=myflowfield.mapheight Then Return
Local d:Int=myflowfield.map[x][y]
Local a:Int[8]
Select d
Case 2 'moving down
a[0]=2;a[1]=1;a[2]=2;a[3]=7
a[4]=0;a[5]=5;a[6]=2;a[7]=3
Case 3 'moving left down
a[0]=4;a[1]=3;a[2]=2;a[3]=3
a[4]=4;a[5]=1;a[6]=2;a[7]=3
Case 4 'moving left
a[0]=4;a[1]=5;a[2]=4;a[3]=3
a[4]=4;a[5]=5;a[6]=6;a[7]=3
Case 5 'moving left up
a[0]=4;a[1]=5;a[2]=6;a[3]=5
a[4]=4;a[5]=5;a[6]=6;a[7]=3
Case 6 ' moving up
a[0]=4;a[1]=5;a[2]=6;a[3]=7
a[4]=6;a[5]=5;a[6]=6;a[7]=7
Case 7 ' moving right up
a[0]=0;a[1]=5;a[2]=6;a[3]=7
a[4]=0;a[5]=7;a[6]=6;a[7]=7
Case 0 ' moving right
a[0]=0;a[1]=1;a[2]=6;a[3]=7
a[4]=0;a[5]=1;a[6]=0;a[7]=7
Case 1 ' moving right down
a[0]=0;a[1]=1;a[2]=2;a[3]=3
a[4]=0;a[5]=1;a[6]=2;a[7]=7
End Select
myflowfield.map[x][y+1] = a[0]
myflowfield.map[x-1][y+1] = a[1]
myflowfield.map[x-1][y] = a[2]
myflowfield.map[x-1][y-1] = a[3]
myflowfield.map[x][y-1] = a[4]
myflowfield.map[x+1][y-1] = a[5]
myflowfield.map[x+1][y] = a[6]
myflowfield.map[x+1][y+1] = a[7]
End Method
Method move()
Local x2:Int=alienx/myflowfield.tilewidth
Local y2:Int=alieny/myflowfield.tileheight
Local d:Int=myflowfield.map[x2][y2]
' Move the alien based on the flowfield array's direction 0=right 1=rightdown 7=rightup
Select d
Case 0
alienx+=speed
Case 1
alienx+=speed;alieny+=speed
Case 2
alieny+=speed
Case 3
alienx-=speed
alieny+=speed
Case 4
alienx-=speed
Case 5
alienx-=speed
alieny-=speed
Case 6
alieny-=speed
Case 7
alieny-=speed
alienx+=speed
End Select
' stay inside array(screen)
If alienx+10>myflowfield.screenwidth Then alienx = myflowfield.screenwidth-10
If alienx-10<0 Then alienx = 10
If alieny+10>myflowfield.screenheight Then alieny = myflowfield.screenheight-10
If alieny-10<0 Then alieny = 10
End Method
Method draw()
SetColor 255,0,0
DrawCircle(alienx,alieny,myflowfield.tilewidth/2)
End Method
End Class
Global myflowfield:flowfield
Global myalien:List<alien> = New List<alien>
Class MyGame Extends App
Field mapwidth:Int,mapheight:Int
Method OnCreate()
Seed = GetDate[5] + GetDate[4]
SetUpdateRate(60)
myflowfield = New flowfield(DeviceWidth(),DeviceHeight(),20,20)
For Local i:=0 Until 10
myalien.AddLast(New alien(Rnd(DeviceWidth),Rnd(DeviceHeight)))
Next
End Method
Method OnUpdate()
myflowfield.refreshmap()
For Local i:=Eachin myalien
i.modifyflowmap
i.move()
Next
' if pressed space or no move by alien then new flowfield
If KeyHit(KEY_SPACE) Or MouseHit(MOUSE_LEFT)
Seed = Millisecs()
mapwidth = Rnd(20,80)
mapheight = mapwidth
myflowfield = New flowfield(DeviceWidth(),DeviceHeight(),mapwidth,mapheight)
myalien.Clear()
For Local i:=0 Until mapwidth*mapheight/20
Local x:Int=Rnd(DeviceWidth)
Local y:Int=Rnd(DeviceHeight)
myalien.AddLast(New alien(x,y))
Next
End If
End Method
Method OnRender()
Cls 0,0,0
SetColor 255,255,255
myflowfield.draw()
For Local i:=Eachin myalien
i.draw
Next
SetColor 255,255,255
DrawText("Flow Fields multiple agents - space(touch/lmb) new map.",0,0)
End Method
End Class
Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int)
If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False
If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False
Return True
End
Function Main()
New MyGame()
End Function
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.