Tuesday, November 3, 2015

Monkey-X - FLoodFill Pathfinding moving mobs - code example


In games sometimes you want to agents to move towards the player. With Floodfill pathfinding you create a map around the player that increases in value the farther away from the player. These values van be used by the agents to count back towards the player. You can do more with the floodfill pathfinding I bet.

Import mojo

Const tilewidth = 32
Const tileheight = 32
Const mapwidth:Int=20
Const mapheight:Int=15
Global gamemap:Int[][] = [  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
                            [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1],
                            [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
                            [1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1],
                            [1,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,1],
                            [1,0,1,1,1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1],
                            [1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
                            [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],                       
                            [1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1],
                            [1,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,0,0,1],
                            [1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1],
                            [1,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,1],
                            [1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1],
                            [1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1],
                            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] ]

Class openlist
    Field x:Int,y:Int
    Field val:Int
    Method New(x:Int,y:Int,val:Int)
        Self.x=x
        Self.y=y
        Self.val=val
    End Method
End Class
Class closedlist
    Field x:Int,y:Int
    Field val:Int
    Method New(x:Int,y:Int,val:Int)
        Self.x=x
        Self.y=y
        Self.val=val
    End Method    
End Class

Class agent
    Field x:Int,y:Int
    Field delay:Int    
    Field delete:Bool=False
    Method New()
        Local exitloop:Bool=False
        While exitloop = False
            Local x1:Int=Rnd(mapwidth)
            Local y1:Int=Rnd(mapheight)
            If myplayer.map[x1][y1] > 10
                x = x1
                y=y1
                exitloop=True
            End If
        Wend
    End Method
    Method update()
        delay-=1
        If delay<1
            delay = 30
            'move towards the player
            Local val:Int=myplayer.map[x][y]
            Local exitloop:Bool=False        
            Local dx:Int=x,dy:Int=y
            While exitloop = False
                Local x1:Int = x+Rnd(-1,2)
                Local y1:Int = y+Rnd(-1,2)
                If gamemap[y1][x1] = 0
                If myplayer.map[x1][y1] < val
                    dx=x1
                    dy=y1
                    val = myplayer.map[x1][y1]
                End If
                End If
                If Rnd(100)<5 Then exitloop = True
            Wend
            x = dx
            y = dy
            ' if close to the player remove
            If myplayer.map[x][y] < 2
                delete = True
            End If
        End If
    End Method
    Method draw()
        SetColor 255,0,0
        DrawOval x*tilewidth+5,y*tileheight+5,tilewidth-10,tileheight-10
    End Method
End Class

Class player
    Field ol:List<openlist> = New List<openlist>
    Field x:Int=10,y:Int=10
    Field map:Int[][]
    Method New()
        map = New Int[mapwidth][]
        For Local i = 0 Until mapwidth
            map[i] = New Int[mapheight]
        Next
        DebugLog mapwidth+","+mapheight
        makefloodmap()
    End Method
    Method update()
        If KeyHit(KEY_LEFT)
        If x-1 > 0
        If gamemap[y][x-1] = 0
            x-=1
            makefloodmap
        End If
        End If
        End If
        If KeyHit(KEY_RIGHT)
        If x+1 < mapwidth
        If gamemap[y][x+1] = 0
            x+=1
            makefloodmap
        End If
        End If
        End If
        If KeyHit(KEY_UP)
        If y-1 > 0
        If gamemap[y-1][x] = 0
            y-=1
            makefloodmap
        End If
        End If
        End If
        If KeyHit(KEY_DOWN)
        If y+1 < mapheight
        If gamemap[y+1][x] = 0
            y+=1
            makefloodmap
        End If
        End If
        End If
    End Method
    Method makefloodmap()        
        For Local y1=0 Until mapheight
        For Local x1=0 Until mapwidth
            map[x1][y1] = 0
        Next
        Next
        ol.Clear()
        ol.AddLast(New openlist(x,y,1))
        map[x][y] = 1
        While ol.IsEmpty() = False
            For Local i:=Eachin ol
                Local tx:Int=i.x
                Local ty:Int=i.y
                Local tv:Int=i.val
                ol.Remove i                
                If ty-1 > 0 
                    If map[tx][ty-1] = 0                
                    If gamemap[ty-1][tx] = 0
                        ol.AddLast(New openlist(tx,ty-1,tv+1))
                        map[tx][ty-1] = tv+1
                    End If
                    End If
                End If
                If tx+1 < mapwidth 
                    If map[tx+1][ty] = 0                
                    If gamemap[ty][tx+1] = 0                    
                        ol.AddLast(New openlist(tx+1,ty,tv+1))
                        map[tx+1][ty] = tv+1
                    End If
                    End If
                End If
                If ty+1 < mapheight 
                    If map[tx][ty+1] = 0                
                    If gamemap[ty+1][tx] = 0
                        ol.AddLast(New openlist(tx,ty+1,tv+1))
                        map[tx][ty+1] = tv+1
                    End If
                    End If
                End If
                If tx-1 > 0 
                    If map[tx-1][ty] = 0                
                    If gamemap[ty][tx-1] = 0
                        ol.AddLast(New openlist(tx-1,ty,tv+1))
                        map[tx-1][ty] = tv+1
                    End If
                    End If
                End If

            Next
        Wend
    End Method
    Method isonclosedlist:Bool(x1:Int,y1:Int)
        For Local i:=Eachin cl
            If i.x = x1 And i.y = y1 Then Return True
        Next
        Return False
    End Method
    Method draw()
        SetColor 255,255,0
        DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight
        SetColor 255,255,255
        For Local y1=0 Until mapheight
        For Local x1=0 Until mapwidth
            If map[x1][y1] > 0
                DrawText map[x1][y1],x1*tilewidth,y1*tileheight
            End If
        Next
        Next
    End Method
End Class

Global myplayer:player = New player()
Global myagent:List<agent> = New List<agent>

Class MyGame Extends App

    Method OnCreate()
        SetUpdateRate(60)
    End Method
    Method OnUpdate()        
        If Rnd(100) < 2
            myagent.AddLast(New agent())
        End If
        myplayer.update
        For Local i:=Eachin myagent
            i.update
            If i.delete = True
                myagent.Remove i
            End If
        Next
    End Method
    Method OnRender()
        Cls 0,0,0 
        SetColor 255,255,255
        drawmap
        For Local i:=Eachin myagent
            i.draw
        Next
        myplayer.draw
        SetColor 255,255,255
        DrawText "Monkey-X - Floodfill pathfinding agents - code example.",10,2
        DrawText "Use Cursor keys to move (yellow) player.",10,16
        
    End Method
End Class

Function drawmap:Void()
    SetColor 255,255,255
    For Local y=0 Until mapheight
    For Local x=0 Until mapwidth
        If gamemap[y][x] = 1
            DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight
        End If
    Next
    Next
End Function


Function Main()
    New MyGame()
End Function

No comments:

Post a Comment