Sunday, July 9, 2017

Monkey-X - Example - Boids Flocking - code example


' Converted to Monkey-X - from Blitzmax ( coded originally by Flanker)
'

Import mojo

Class obstacle
    Field x:Float,y:Float
    Field radius:Int
    Method New(x:Int,y:Int)
        Self.x = x
        Self.y = y
        Self.radius = 20    
    End Method
    Method draw()
        SetColor 255,255,0
        DrawCircle(x,y,radius)
    End Method    
End Class

Class boid
    Field friendlist:List<boid> = New List<boid>
    Field x:Float,y:Float,angle:Float
    Field vx:Float,vy:Float
    Field alignspeed:Float = 8
    Field speed:Float = 3
    Field smoothturn:Float = 25
    Field radius:Float = 10
    Field cohesionfactor:Float = 100
    Field friendradius:Float = 75
    Field frienddistance:Float = 30
    Field friendsqradius:Float
    Field friendsqrdistance:Float
    Field obstaclemargin:Float = 2
    Method New()
        friendsqradius = friendradius*friendradius
        friendsqrdistance = frienddistance*frienddistance
    End Method
    Method create(count:Int)
        For Local i:=0 Until count
            Local newboid:boid = New boid()
            newboid.x = Rnd(640)
            newboid.y = Rnd(480)
            newboid.angle = Rnd(360)
            boidlist.AddLast(newboid)
        Next
    End Method
    Method update()
        getfriends()
        If friendlist.Count > 0
            vx = 0
            vy = 0
            cohesion()
            obstacle()
            distance()
            align()
        Else
            obstacle()
        End If        
        ' Clamp the movement speed
         If vx < -2 Then vx = -2 
         If vy < -2 Then vy = -2
         If vx > 2 Then vx = 2
         If vy > 2 Then vy = 2
        move()
    End Method
    Method obstacle()
        For Local i:=Eachin myobstacle
            Local diffx:Float = x - i.x
            Local diffy:Float = y - i.y
            Local sqrdistance:Float=diffx*diffx+diffy*diffy
            If diffx*diffx+diffy*diffy < i.radius*i.radius*i.radius/obstaclemargin
                vx -= (i.x - x) / Sqrt(sqrdistance) 
                vy -= (i.y - y) / Sqrt(sqrdistance)
            End If
        Next
    End Method
    Method cohesion()
        Local centerx:Float
        Local centery:Float
        For Local i:= Eachin friendlist
            centerx += i.x
            centery += i.y
        Next
        centerx /= friendlist.Count
        centery /= friendlist.Count
        vx += (centerx-x) / cohesionfactor
        vy += (centery-y) / cohesionfactor
    End Method
    Method distance()
        For Local i:=Eachin friendlist
            Local diffx:Float=x-i.x
            Local diffy:Float=y-i.y
            Local sqrdistance:Float=diffx*diffx+diffy*diffy
            If diffx*diffx+diffy*diffy < friendsqrdistance
                vx -= (i.x - x) / Sqrt(sqrdistance)
                vy -= (i.y - y) / Sqrt(sqrdistance)
            End If
        Next
    End Method
    Method align()
        Local sumvx:Float
        Local sumvy:Float
        For Local i:=Eachin friendlist
            sumvx += i.vx
            sumvy += i.vy
        Next
        sumvx /= friendlist.Count
        sumvy /= friendlist.Count
        vx += (sumvx - vx) / alignspeed
        vy += (sumvy - vy) / alignspeed
    End Method
    Method move()
         x += vx
        y += vy
        angle = smoothrotate(x,y,angle,x+vx,y+vy,smoothturn)
        x += Cos(angle) * speed
        y += Sin(angle) * speed
        If x<0 Then x = 640
        If y<0 Then y = 480
        If x>640 Then x = 0
        If y>480 Then y = 0
    End Method
    Method getfriends()
        friendlist.Clear()
        For Local i:=Eachin boidlist
            Local diffx:Float=x-i.x
            Local diffy:Float=y-i.y            
            If diffx*diffx+diffy*diffy < friendsqradius
                If i <> Self Then 
                    friendlist.AddLast(i)
                End If
            End If
        Next
    End Method
    Method updateall()
        For Local i:=Eachin boidlist
            i.update
        Next
    End Method
    Method drawall()
        For Local i:=Eachin boidlist
            i.draw
        Next
    End Method
    Method draw()
        SetColor 255,255,255
        DrawCircle(x,y,10)
    End Method
    Function smoothrotate:Float(sourceX:Float,sourceY:Float,sourceAngle:Float,destX:Float,destY:Float,smooth:Float)
        ' Thanks to BlackSp1der on BB forums for this piece of code ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        Local targetAngle:Float = ATan2(sourceY-destY,sourceX-destX)
        Local tempAngle:Float = targetAngle - Sgn(targetAngle-sourceAngle) * 360
        If Abs(targetAngle-sourceAngle) > Abs(tempAngle-sourceAngle) Then targetAngle = tempAngle
        If sourceAngle <> targetAngle Then sourceAngle = sourceAngle - Sgn(targetAngle-sourceAngle) * (180-Abs(targetAngle-sourceAngle)) / (1+smooth)
        If sourceAngle >= 360 Then sourceAngle -= 360 Else If sourceAngle < 0 Then sourceAngle += 360
        Return sourceAngle
    End Function    
End Class

Global myobstacle:List<obstacle>
Global boidlist:List<boid> = New List<boid>

Class MyGame Extends App
    Field myboid:boid
    Method OnCreate()
        SetUpdateRate(60)
        myobstacle = New List<obstacle>
        For Local i:Int = 0 Until 10
            myobstacle.AddLast(New obstacle(Rnd(640),Rnd(480)))
        Next
        myboid = New boid()
        myboid.create(20)
    End Method
    Method OnUpdate()
        myboid.updateall()     
        If MouseDown(MOUSE_LEFT) Then myobstacle.AddLast(New obstacle(MouseX,MouseY))
        If KeyHit(KEY_SPACE) Then 
            For Local i:Int = 0 Until 10
                myobstacle.AddLast(New obstacle(Rnd(640),Rnd(480)))
            Next
        End If
    End Method
    Method OnRender()
        Cls 0,0,0 
        SetColor 255,255,255
        myboid.drawall()
        For Local i:=Eachin myobstacle
            i.draw
        Next
        SetColor 255,255,255
        DrawText "Hold LMB to draw obstacles.",0,0
        DrawText "Press space for random obstacles.",0,20
    End Method
End Class

Function Main()
    New MyGame()
End Function

Monkey-X - Beginners - 2D Vector Rotation - code example


Import mojo

Class vector
    ' A vector has a origin of 0,0. The length and direction
    ' is the x and y variables. 
    Field x:Float
    Field y:Float
    Method New(x:Float=0.0,y:Float=0.0)
        ' Fill in the x and y
        Self.x = x
        Self.y = y
    End Method
    ' This method rotates the input vector by a value(degrees)
    Method rotate:vector(v:vector,val:Int)
        ' create a temporary vector
        Local u:vector = New vector()
        ' rotate the inputted vector and put the data in u.
        u.x = v.x * Cos(val) - v.y * Sin(val)
        u.y = v.x * Sin(val) + v.y * Cos(val)
        ' return the new vector
        Return u
    End Method
End Class

Class MyGame Extends App
    ' some local variables.
    Field alienx:Float=100,alieny:Float=100
    Field myvec:vector
    Method OnCreate()
        SetUpdateRate(60)
        ' create the new vector (2,2)
        myvec = New vector(2,2)
    End Method
    Method OnUpdate()        
    End Method
    Method OnRender()
        Cls 0,0,0 
        SetColor 255,255,255
        ' Move the alien based on the vector's x,y
        alienx+=myvec.x
        alieny+=myvec.y
        ' rotate the vector.
        myvec = myvec.rotate(myvec,10)
        ' draw the alien.
        DrawCircle(alienx,alieny,10)
        '
        DrawText "2D Vector Rotation",0,0
    End Method
End Class

Function Main()
    New MyGame()
End Function

Friday, July 7, 2017

Monkey Getting started - MouseHit - code example


'import mojo needs to be called so that it recognizes the
'mojo commands.
Import mojo 

Class MyGame Extends App
    Field timedown:Int
    Field mytext:String = "Press the mouse."
    Method OnCreate() 'This method is only run when the program starts
        SetUpdateRate(10) 'how many times should the screen be redrawn per second
    End Method
    Method OnUpdate() ' Run every frame(put keyinput ect. in here)
        timedown-=1
        If timedown <= 0 Then
            timedown = 0
            mytext = "Press the mouse"
        End If
        If MouseHit(MOUSE_LEFT) Then mytext = "The left mouse was last pressed." ; timedown=10
        ' Flash does not recognize middle and right mouse buttons....
        If MouseHit(MOUSE_RIGHT) Then mytext = "The Right mouse was last pressed."; timedown=10
        If MouseHit(MOUSE_MIDDLE) Then mytext = "The Middle mouse was last pressed."; timedown=10
    End Method    
    Method OnRender() 'Drawing commands here.
        ' Clear the screen with color 0,0,0
        Cls 0,0,0 
        ' Set the Color of the next drawing commands
        SetColor 255,255,255
        ' Draw text to the screen. txt,x,y
        DrawText mytext,0,0
    End Method
End Class

Function Main()
    New MyGame()
End Function

Monkey Getting started - SetColor - code example


Import mojo

Class MyGame Extends App
    Method OnCreate() 'This method is only run when the program starts
        SetUpdateRate(10) 'how many times should the screen be redrawn per second
    End Method
    Method OnUpdate() ' Run every frame(put keyinput ect. in here)
    End Method    
    Method OnRender() 'Drawing commands here.
        ' Clear the screen with color 0,0,0
        Cls 0,0,0 
        ' Set the Color of the next drawing commands
        ' red(0..255),green(0..255),blue(0..255)
        SetColor 255,255,255
        DrawText "This is text..",0,0
        ' Set the drawing color for the next drawing commands
        SetColor 0,255,255
        ' Draw a rectangle
        DrawRect 100,100,200,200
    End Method
End Class

Function Main()
    New MyGame()
End Function

Monkey-X - Fill Triangle with Bresenham Algorithm - code example


'
' Fill triangles using the bresenham algorithm
'

Import mojo

Class filledtriangle
    ' These variables are the points of
    ' the triangle.
    Field x1:Int,y1:Int
    Field x2:Int,y2:Int
    Field x3:Int,y3:Int
    ' This variable is the y of the triangle
    ' that has the lowest value.
    Field lowesty:Int
    ' This is the total height of the triangle.
    Field sizey:Int
    ' These arrays hold the x coordinates with
    ' which we draw the lines.
    Field lefty:Int[]
    Field righty:Int[]
    ' Here we create and draw the triangle.
    Method New(x1:Int,y1:int,x2:Int,y2:int,x3:int,y3:int)
        ' In order to draw below ZERO we add a value to the inputted
        ' coordinates. We decrease this amount when drawing the
        ' actual triangles on the canvas.
        Local offscreen:Int=10000
        x1 += offscreen
        y1 += offscreen
        x2 += offscreen
        y2 += offscreen
        x3 += offscreen
        y3 += offscreen
        ' We need to know which coordinate has the lowest
        ' y value and we put that in the lowesty variable.
        'find lowest
        If y1<y2 And y1<y3 Then lowesty = y1
        If y2<y1 And y2<y3 Then lowesty = y2
        If y3<y1 And y3<y2 Then lowesty = y3
        ' We also need to know the total height of the
        ' triangle so we can create a array of that size
        ' where we store the left and right side line
        ' coordinates in.
        'find height
        If y1>y2 And y1>y3 Then sizey = y1-lowesty
        If y2>y1 And y2>y3 Then sizey = y2-lowesty
        If y3>y1 And y3>y2 Then sizey = y3-lowesty
        '
        ' If there is nothing to draw then
        ' exit this method.
        If sizey = 0 Then Return
        ' Create two arrays which will hold the coordinates
        ' for the lines inside the triangles. The x coordinates.
        lefty = New Int[sizey+1]
        righty = New Int[sizey+1]
        ' Here we fill the lefty and righty arrays with the
        ' x coordinates of the lines inside the triangles.
        bline(x1,y1,x2,y2)
        bline(x2,y2,x3,y3)
        bline(x1,y1,x3,y3)
        ' Here we draw the lines inside the triangles. Filling
        ' it. You can do per pixel for colloring ect.
        For Local y:Int=0 until sizey
            DrawLine(lefty[y]-offscreen,lowesty+y-offscreen,righty[y]-offscreen,lowesty+y-offscreen)
        Next
    End Method
    '
    ' This is the bresenham algorithm. It is modified so
    ' it fills two arrays with the x coordinates of the
    ' lines inside the triangles.
    Method bline:Void(x4:Int,y4:Int,x5:Int,y5:Int)
        Local dx:Int, dy:Int, sx:Int, sy:Int, e:Int
        dx = Abs(x5 - x4)
        sx = -1
        If x4 < x5 Then sx = 1      
        dy = Abs(y5 - y4)
        sy = -1
        If y4 < y5 Then sy = 1
        If dx < dy Then 
            e = dx / 2 
        Else 
            e = dy / 2          
        End If
        Local exitloop:Bool=False
        While exitloop = False
            ' Here we fill the left and right sides arrays.
            ' we draw lines between these later on to fill the triangle                            
              
            If lefty[y4-lowesty] = 0 Then 'If left not used then fill left
                 lefty[y4-lowesty] = x4
            Elseif righty[y4-lowesty] = 0 'if right not used then fill right
                   righty[y4-lowesty] = x4    
             Else 'if both sides are filled
                If lefty[y4-lowesty] = x4 Then  'overwrite same value
                    lefty[y4-lowesty] = x4
                Else 'write new value
                    righty[y4-lowesty] = x4    
                End If       
              End If
      

          If x4 = x5 
              If y4 = y5
                  exitloop = True
              End If
          End If
          If dx > dy Then
              x4 += sx ; e -= dy 
               If e < 0 Then e += dx ; y4 += sy
          Else
              y4 += sy ; e -= dx 
              If e < 0 Then e += dy ; x4 += sx
          Endif

        Wend
    
    End Method
        
End Class

Class MyGame Extends App
    ' cnt is used for the seed
    Field cnt:Int
    ' mytriangle is used to draw a triangle
    Field mytriangle:filledtriangle

    Method OnCreate()
        SetUpdateRate(10)
    End Method
    
    Method OnUpdate()
        ' If pressed space/touch/lmb then new set of triangles
        If KeyHit(KEY_SPACE) Or MouseHit(MOUSE_LEFT) Then cnt+=1    
       End Method    
        
    Method OnRender()
        Cls 0,0,0
        ' Always draw the same using this seed
        Seed = cnt
        ' Draw 100 triangles
        For Local i:=0 Until 100
            Local x1:Int=Rnd(0,DeviceWidth)
            Local y1:Int=Rnd(0,DeviceHeight)
            Local x2:Int=x1+Rnd(-80,80)
            Local y2:Int=y1+Rnd(-80,80)
            Local x3:Int=x1+Rnd(-80,80)
            Local y3:Int=y1+Rnd(-80,80)        
            SetColor(Rnd(255),Rnd(255),Rnd(255))
            mytriangle = New filledtriangle(x1,y1,x2,y2,x3,y3)
        Next
        ' Draw some text
        SetColor 255,255,255
        DrawText("Press the space bar/lmb/touch to draw new set.",0,0)
    End Method    
    
End    Class

Function Main()
    New MyGame()
End Function

Tuesday, June 20, 2017

Monkey-X - Closest Point in Line Segment - code example


This can be turned into a collision function. Circle to line segment. Use a 
distance function for that.


' Example on how to get the closest point in a line segment
' to another point.
'
'

Import mojo

Class point
    Field x:Float
    Field y:Float
    Method New(x:Float,y:Float)
        Self.x = x
        Self.y = y
    End Method
End Class

Class MyGame Extends App

    Method OnCreate()
        SetUpdateRate(30)        
    End Method
    Method OnUpdate()        
    End Method
    Method OnRender()
        Cls 0,0,0 
        SetColor 255,255,255        
        DrawText "Mouse the mouse around to see the closest point",0,0
        DrawText "of the line segment..",0,20
        Local mypoint:point = New point(0,0)
        ' the mouse location for point x and y closest to line point
        Local cx:Float=MouseX(),cy:Float=MouseY()
        ' line coordinates
        Local lx1:Float=100
        Local ly1:Float=100
        Local lx2:Float=200
        Local ly2:Float=200
        ' draw the line
        SetColor 100,100,100
        DrawLine lx1,ly1,lx2,ly2
        ' get the closest point on the line segment
        mypoint = getclosestpointonsegment(lx1,ly1,lx2,ly2,cx,cy)
        ' draw this point
           SetColor 255,255,0
           DrawCircle mypoint.x,mypoint.y,10

    End Method
End Class

Function getclosestpointonsegment:point(sx1:Int, sy1:Int, sx2:Int, sy2:Int, px:Int, py:Int)
    Local xDelta:Float = sx2 - sx1
    Local yDelta:Float = sy2 - sy1
    Local u:Float

    If ((xDelta = 0) And (yDelta = 0))    
      Error("Segment start equals segment end")
    End If

    u = ((px - sx1) * xDelta + (py - sy1) * yDelta) / (xDelta * xDelta + yDelta * yDelta)

       Local closestPoint:point = New point(0,0)
    If (u < 0)
      closestPoint = New point(sx1, sy1)
    Else If (u > 1)
      closestPoint = New point(sx2, sy2)
    Else
      closestPoint = New point(Int(Floor(sx1 + u * xDelta)), Int(Floor(sy1 + u * yDelta)))
    End If
    
    Return closestPoint
End Function


Function Main()
    New MyGame()
End Function

Friday, June 9, 2017

Monkey-X - Interface Data in array - code example


'
' When building an interface on the screen it might
' be useful to put the data of it and store it elsewhere.
' Sometimes you might use the coordinates more then once
' and for other things like collision(mouse click) 
'
  
Import mojo

' Here we create 1 array with the coordinates 
' and width and height and 1 string for the
' text. Ends with c and s.
Global label1c:Int[] = [10,10,50,15] ' coordinates x,y,w,h
Global label1s:String = "Label1" ' text
Global label2c:Int[] = [10,30,50,15]
Global label2s:String = "Label2"

Class MyGame Extends App

    Method OnCreate()
        SetUpdateRate(1)
    End Method
    Method OnUpdate()        
    End Method
    Method OnRender()
        Cls 0,0,0 
        ' Here we call the drawlabel function.
        ' We put one string and a array in it.
        drawlabel(label1s,label1c)
        drawlabel(label2s,label2c)
    End Method
End Class

' this function takes a string and a int array
' into the function.
Function drawlabel:Void(a:String,b:Int[])
    SetColor 255,55,55
    ' draw a rect x,y,w,h
    DrawRect b[0],b[1],b[2],b[3]
    SetColor 255,255,255
    DrawText a,b[0]+b[2]/2,b[1]+b[3]/2,.5,.5
End Function

Function Main()
    New MyGame()
End Function