Wednesday, July 12, 2017

Monkey-X - Flow Fields - code example

Import mojo

Class flowfield
    Field mapwidth:Int,mapheight:Int
    Field tilewidth:Float,tileheight:Float
    Field screenwidth:Int,screenheight:Int
    Field map: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
        map = New Int[mapwidth][]
        For Local i = 0 Until mapwidth
            map[i] = New Int[mapheight]
        Next    
        pointtocenter
    End Method
    '
    ' In the flowfield array there are 8 directions. 
    ' Here we point the directions towards the center
    '
    Method pointtocenter()
        For Local y:Int=0 Until mapheight
        For Local x:Int=0 Until mapwidth
            Local x2:Int=mapwidth/2
            Local y2:Int=mapheight/2
            Local nd:Int=0
            If x<x2 Then nd=0
            If x>x2 Then nd=4
            If y<y2 Then nd=2
            If y>y2 Then nd=6
            
            If x<x2 And y<y2 Then nd=1
            If x>x2 And y<y2 Then nd=3
            If x<x2 And y>y2 Then nd=7
            If x>x2 And y>y2 Then nd=5

            map[x][y] = nd
        Next
        Next
    End Method
    Method draw()
        SetColor 255,255,255
        For Local y:=0 Until mapheight
        For Local x:=0 Until mapwidth
            Local direction:Int = map[x][y]
            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 MyGame Extends App
    Field myflowfield:flowfield
    Field alienx:Int=200,alieny:Int=200
    Method OnCreate()
        SetUpdateRate(60)
        myflowfield = New flowfield(DeviceWidth(),DeviceHeight(),20,20)
    End Method
    Method OnUpdate()        
        Local d:Int=myflowfield.map[alienx/myflowfield.tilewidth][alieny/myflowfield.tileheight]
        Select d
            Case 0
            alienx+=1
            Case 1
            alienx+=1;alieny+=1
            Case 2
            alieny+=1
            Case 3
            alienx-=1
            alieny+=1
            Case 4
            alienx-=1
            Case 5
            alienx-=1
            alieny-=1
            Case 6
            alieny-=1
            Case 7
            alieny-=1
            alienx+=1
        End Select

        If rectsoverlap(alienx-10,alieny-10,20,20,DeviceWidth/2-30,DeviceHeight/2-30,60,60)
            alienx = Rnd(DeviceWidth)
            alieny = Rnd(DeviceHeight)
        End If

        If MouseHit(MOUSE_LEFT) Then
            alienx = MouseX
            alieny = MouseY
        End If

    End Method
    Method OnRender()
        Cls 0,0,0 
        SetColor 255,255,255
        myflowfield.draw()
        SetColor 255,0,0
        DrawCircle(alienx,alieny,20)
        SetColor 255,255,255
        DrawText("Flow Fields - Press Left Mouse to place alien",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