• Dear Cerberus X User!

    As we prepare to transition the forum ownership from Mike to Phil (TripleHead GmbH), we need your explicit consent to transfer your user data in accordance with our amended Terms and Rules in order to be compliant with data protection laws.

    Important: If you accept the amended Terms and Rules, you agree to the transfer of your user data to the future forum owner!

    Please read the new Terms and Rules below, check the box to agree, and click "Accept" to continue enjoying your Cerberus X Forum experience. The deadline for consent is April 5, 2024.

    Do not accept the amended Terms and Rules if you do not wish your personal data to be transferred to the future forum owner!

    Accepting ensures:

    - Continued access to your account with a short break for the actual transfer.

    - Retention of your data under the same terms.

    Without consent:

    - You don't have further access to your forum user account.

    - Your account and personal data will be deleted after April 5, 2024.

    - Public posts remain, but usernames indicating real identity will be anonymized. If you disagree with a fictitious name you have the option to contact us so we can find a name that is acceptable to you.

    We hope to keep you in our community and see you on the forum soon!

    All the best

    Your Cerberus X Team

Blobmonster in Mojo2

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,414
Hey everyone, I must be tired but I just can't see the error here, I tried to convert Blobmonster example to Mojo2 but it looks
well not as it should. I'm sure I missed something simple but right now I just don't see it?

There seem to be some kind of relative coordinate thing going on?

Screenshot 2020-10-21 at 18.21.30.png

Cerberus:
Import mojo2

Function Main:Int()
    New blob_monster
    Return 0
End

Class blob_monster Extends App

     Field blobimage:Image
     Field theMonster:BlobMonster
     Field canvas:Canvas
   
       Method OnCreate:Int()
         canvas=New Canvas
        blobimage=Image.Load("blob.png",0,0,0)    ; MidHandle blobimage
         theMonster=New BlobMonster(10,10,blobimage)
        SetSwapInterval 1 ; SetUpdateRate 0
        Return 0
    End

    Method OnUpdate ()
        theMonster.Update()
        Return 0
    End

    Method OnRender ()
        canvas.Clear 0,0,0
        theMonster.Draw(canvas)
        canvas.Flush
        Return 0
    End

End

Class point
    Field x:Float,y:Float
End

Function MidHandle (image:Image)
    image.SetHandle image.Width () * 0.5, image.Height () * 0.5
End

Class BlobMonster

    Field x:Float, y:Float
    Field speed:Float = 1
    Field segments:Float = 10
    Field tail:point[10]
    Field time:Float = 0
    Field blob:Image

    Method New(inx:Float,iny:Float,inimage:Image)
        x = inx ; y = iny
        For Local i:Int = 0 To segments - 1
            tail[i] = New point
            tail[i].x = inx
            tail[i].y = iny
        Next
        blob=inimage
    End

    Method Update:Int()
        time+=speed
        y = (15 * Cos(time * -6)) + (DeviceHeight/2 + (180 * Sin(time * 1.3)))
        x = (15 * Sin(time * -6)) + (DeviceWidth/2 + (200 * Cos(time / 1.5)))
        tail[0].x = x
        tail[0].y = y
        For Local i:Int = 1 To segments - 1
                Local distX:Float = (tail[i - 1].x - tail[i].x)
                Local distY:Float = (tail[i - 1].y - tail[i].y)
            Local dist:Float = Sqrt(distX * distX + distY * distY)
                 If dist > 7 Then
                tail[i].x = tail[i].x + (distX * (0.3))
                    tail[i].y = tail[i].y + (distY * (0.3))
                 Endif
        Next
        Return False
    End Method

    Method Draw(canvas:Canvas)
        canvas.SetBlendMode BlendMode.Additive
        blob.SetHandle(blob.Width()*0.5,blob.Height()*0.5)
        For Local i:Int = 0 To segments - 1
            canvas.SetAlpha 0.15
            canvas.DrawImage blob, tail[i].x, tail[i].y,0,1 + (0.5 * Sin(i * 35)), 1 + (0.5 * Sin(i * 35))
            canvas.SetAlpha 0.8
            canvas.DrawImage blob, tail[i].x, tail[i].y,0,0.1, 0.1
        Next
        blob.SetHandle 0,blob.Height()*0.5
        canvas.DrawImage blob, tail[segments - 1].x, tail[segments - 1].y,10 * Sin(time * 10) + -calculateAngle(tail[segments - 1].x, tail[segments - 1].y, tail[segments - 5].x, tail[segments - 5].y) + 270,0.6, 0.1
        canvas.DrawImage blob, tail[segments - 1].x, tail[segments - 1].y,10 * Sin(-time * 10) + -calculateAngle(tail[segments - 1].x, tail[segments - 1].y, tail[segments - 5].x, tail[segments - 5].y) + 270,0.6, 0.1
        canvas.SetAlpha 1
        For Local i:Int = 1 To segments - 2
            canvas.DrawImage blob, tail[i].x, tail[i].y,33 * Sin(time * 5 + i * 30) + -calculateAngle(tail[i].x, tail[i].y, tail[i - 1].x, tail[i - 1].y),0.1 + (0.6 * Sin(i * 30)), 0.0
            canvas.DrawImage blob, tail[i].x, tail[i].y,33 * Sin(-time * 5 - i * 30) + -calculateAngle(tail[i].x, tail[i].y, tail[i - 1].x, tail[i - 1].y) + 180,0.1 + (0.6 * Sin(i * 30)), 0.05          
        Next
        MidHandle blob
        canvas.SetAlpha 0.1
        Local ang:Float = calculateAngle(tail[0].x, tail[0].y, tail[1].x, tail[1].y)
        canvas.DrawImage blob, x + (7 * Cos(ang + 50)), y + (7 * Sin(ang + 50)),0,0.6, 0.6
        canvas.DrawImage blob, x + (7 * Cos(ang + 140)), y + (7 * Sin(ang + 140)),0,0.6, 0.6
        canvas.SetAlpha 0.5
        canvas.DrawImage blob, x + (7 * Cos(ang + 50)), y + (7 * Sin(ang + 50)),0,0.1, 0.1
        canvas.DrawImage blob, x + (7 * Cos(ang + 140)), y + (7 * Sin(ang + 140)),0,0.1, 0.1
        canvas.SetAlpha 0.8
        blob.SetHandle 0, blob.Height()*0.5
        canvas.DrawImage blob, x, y,-ang + 275,0.3, 0.1
        MidHandle blob
        canvas.SetAlpha 0.2
        canvas.DrawImage blob, x, y,0,4, 4
    End Method
   
End  

Function calculateAngle:Float(x1:Float,y1:Float,x2:Float,y2:Float)
    Local theX:Float=x1-x2
    Local theY:Float=y1-y2
    Local theAngle:Float=-ATan2(theX,theY)
    Return theAngle
End Function



Code:
Import mojo.app
Import mojo.graphics
Import cerberus.math

' The overall Game object, handling loading, mouse position, high-level game control and rendering...

Class point
    Field x:Float,y:Float
End

Function MidHandle (image:Image)
    image.SetHandle image.Width () * 0.5, image.Height () * 0.5
End

Class BlobMonster
    'x and y coords
    Field x:Float, y:Float
    
    'speed, try changing it
    Field speed:Float = 1
    
    'number of nodes along the body, try changing it to 100
    Field segments:Float = 10
    
    'array to hold the points along the body
    Field tail:point[10]
    Field time:Float = 0

    Field blob:Image

    Method New(inx:Float,iny:Float,inimage:Image)
        x = inx
        y = iny
        'give the tail some coordinates, just make them the same as the main x and y for now
        For Local i:Int = 0 To segments - 1
            tail[i] = New point
            tail[i].x = inx
            tail[i].y = iny
        Next
        blob=inimage
    End

    Method Update:Int()
        'time is a bit misleading, it's used for all sorts of things
        time+=speed
        
        'here the x and y coordinates are updated.
        'this uses the following as a basic rule for moving things
        'around a point in 2d space:
        'x=radius*cos(angle)+xOrigin
        'y=raduis*sin(angle)+yOrigin
        'this basically is the basis for anything that moves in this example
        '
        'the 2 lines of code below make the monster move around, but
        'you can change this to anything you like, try setting x and y to the mouse
        'coordinates for example
        y = (15 * Cos(time * -6)) + (DeviceHeight/2 + (180 * Sin(time * 1.3)))
        x = (15 * Sin(time * -6)) + (DeviceWidth/2 + (200 * Cos(time / 1.5)))
        
        'put the head of the tail at x,y coords
        tail[0].x = x
        tail[0].y = y
    
        'update the tail
        'basically, the points don't move unless they're further that 7 pixels
        'from the previous point. this gives the kind of springy effect as the
        'body stretches
        For Local i:Int = 1 To segments - 1
               'calculate distance between the current point and the previous
                Local distX:Float = (tail[i - 1].x - tail[i].x)
                Local distY:Float = (tail[i - 1].y - tail[i].y)
            Local dist:Float = Sqrt(distX * distX + distY * distY)
              'move if too far away
                 If dist > 7 Then
                'the (distX*0.2) bit makes the point move
                'just 20% of the distance. this makes the
                'movement smoother, and the point decelerate
                'as it gets closer to the target point.
                'try changing it to 1 (i.e 100%) to see what happens
                tail[i].x = tail[i].x + (distX * (0.3))
                    tail[i].y = tail[i].y + (distY * (0.3))
                 Endif
            
        Next
    
        Return False
    End Method

    Method Draw()
        'time to draw stuff!
        
        'this sets the blend mode to LIGHTBLEND, or additive blending, which makes
        'the images progressively more bright as they overlap
        SetBlend 1
        '###########
        'draw the main bit of the body
        'start by setting the images handle (i.e the origin of the image) to it's center
        blob.SetHandle(blob.Width()*0.5,blob.Height()*0.5)
        
        
        'begin looping through the segments of the body
        For Local i:Int = 0 To segments - 1
            'set the alpha transparency vaue to 0.15, pretty transparent
            SetAlpha 0.15
            'the  (0.5*sin(i*35)) bit basically bulges the size of the images being
            'drawn as it gets closer to the center of the monsters body, and tapers off in size as it gets
            'to the end. try changing the 0.5 to a higher number to see the effect.
            
            'draw the image
            DrawImage blob, tail[i].x, tail[i].y,0,1 + (0.5 * Sin(i * 35)), 1 + (0.5 * Sin(i * 35))
            
            'this next chunk just draws smaller dots in the center of each segment of the body
            SetAlpha 0.8
            
            DrawImage blob, tail[i].x, tail[i].y,0,0.1, 0.1
        Next
        
        '#########################
        'draw little spikes on tail
        'note that the x and y scales are different
        
        'move the image handle to halfway down the left edge, this'll make the image
        'appear to the side of the coordinate it is drawn too, rather than the
        'center as we had for the body sections
        blob.SetHandle 0,blob.Height()*0.5
        
        'rotate the 1st tail image. basically, we're calculating the angle between
        'the last 2 points of the tail, and then adding an extra wobble (the 10*sin(time*10) bit)
        'to make the pincer type effect.
        
        
        DrawImage blob, tail[segments - 1].x, tail[segments - 1].y,10 * Sin(time * 10) + -calculateAngle(tail[segments - 1].x, tail[segments - 1].y, tail[segments - 5].x, tail[segments - 5].y) + 270,0.6, 0.1
        
        'second tail image uses negative time to make it move in the opposite direction
        
        DrawImage blob, tail[segments - 1].x, tail[segments - 1].y,10 * Sin(-time * 10) + -calculateAngle(tail[segments - 1].x, tail[segments - 1].y, tail[segments - 5].x, tail[segments - 5].y) + 270,0.6, 0.1

        
        
        '#####################
        'draw little fins/arms
        SetAlpha 1
        
        'begin looping through the body sections again. Note that we don't want fins
        'on the first and last section because we want other things at those coords.
        For Local i:Int = 1 To segments - 2
            'like the bulging body, we want the fins to grow larger in the center, and smaller
            'at the end, so the same sort of thing is used here.
            
            
            'rotate the image. We want the fins to stick out sideways from the body (the calculateangle() bit)
            'and also to move a little on their own. the 33 * Sin(time * 5 + i * 30) makes the
            'fin rotate based in the i index variable, so that all the fins look like they're moving
            'one after the other.
            DrawImage blob, tail[i].x, tail[i].y,33 * Sin(time * 5 + i * 30) + -calculateAngle(tail[i].x, tail[i].y, tail[i - 1].x, tail[i - 1].y),0.1 + (0.6 * Sin(i * 30)), 0.05
            
            
            'rotate the opposte fin, note that the signs have changes (-time and -i*30)
            'to reflect the rotations of the other fin
            DrawImage blob, tail[i].x, tail[i].y,33 * Sin(-time * 5 - i * 30) + -calculateAngle(tail[i].x, tail[i].y, tail[i - 1].x, tail[i - 1].y) + 180,0.1 + (0.6 * Sin(i * 30)), 0.05
            
            
        Next
        
        
        '###################
        'center the image handle
        MidHandle blob
        'Draw the eyes. These are just at 90 degrees to the head of the tail.
        SetAlpha 0.1
        Local ang:Float = calculateAngle(tail[0].x, tail[0].y, tail[1].x, tail[1].y)
        DrawImage blob, x + (7 * Cos(ang + 50)), y + (7 * Sin(ang + 50)),0,0.6, 0.6
        DrawImage blob, x + (7 * Cos(ang + 140)), y + (7 * Sin(ang + 140)),0,0.6, 0.6
        
        SetAlpha 0.5
        DrawImage blob, x + (7 * Cos(ang + 50)), y + (7 * Sin(ang + 50)),0,0.1, 0.1
        DrawImage blob, x + (7 * Cos(ang + 140)), y + (7 * Sin(ang + 140)),0,0.1, 0.1
    
        'draw beaky thing
        SetAlpha 0.8
        blob.SetHandle 0, blob.Height()*0.5
        
        DrawImage blob, x, y,-ang + 275,0.3, 0.1
        
        'yellow light
        MidHandle blob
        SetAlpha 0.2
        DrawImage blob, x, y,0,4, 4
        
        'Finished!
    End Method
End   

'This function calculates and returns the angle between two 2d coordinates
Function calculateAngle:Float(x1:Float,y1:Float,x2:Float,y2:Float)
    Local theX:Float=x1-x2
    Local theY:Float=y1-y2
    Local theAngle:Float=-ATan2(theX,theY)
    Return theAngle
End Function

Class blob_monster Extends App

    Field blobimage:Image
    Field theMonster:BlobMonster
    
     ' Stuff to do on startup...
    Method OnCreate ()
        
        blobimage=LoadImage( "blob.png" )

        theMonster=New BlobMonster(10,10,blobimage)
        
        SetUpdateRate 60

    End

    ' Stuff to do while running...
    Method OnUpdate ()
    
        theMonster.Update()
    End

    ' Drawing code...
    Method OnRender ()
        Cls(0, 0, 0)
        
        theMonster.Draw()
        
    End

End

' Here we go!

Function Main ()
    New blob_monster                                ' RocketGame extends App, so monkey will handle running from here...
End
 

Attachments

  • blob.png
    blob.png
    3.6 KB · Views: 102
Your problem lies most likely in the SetHandle statements. In mojo the values were pixels, in mojo2 its a Float value ranging from 0.0 to 1.0

This works:
Cerberus:
Import mojo2
Import cerberus.math

' The overall Game object, handling loading, mouse position, high-level game control and rendering...

Class point
    Field x:Float,y:Float
End

Function MidHandle (image:Image)
    image.SetHandle 0.5, 0.5
End

Class BlobMonster
    'x and y coords
    Field x:Float, y:Float
    
    'speed, try changing it
    Field speed:Float = 1
    
    'number of nodes along the body, try changing it to 100
    Field segments:Float = 10
    
    'array to hold the points along the body
    Field tail:point[10]
    Field time:Float = 0

    Field blob:Image
    Field cv:Canvas


    Method New(inx:Float,iny:Float,inimage:Image, _cv:Canvas)
        x = inx
        y = iny
        Self.cv = _cv
        'give the tail some coordinates, just make them the same as the main x and y for now
        For Local i:Int = 0 To segments - 1
            tail[i] = New point
            tail[i].x = inx
            tail[i].y = iny
        Next
        blob=inimage
    End

    Method Update:Int()
        'time is a bit misleading, it's used for all sorts of things
        time+=speed
        
        'here the x and y coordinates are updated.
        'this uses the following as a basic rule for moving things
        'around a point in 2d space:
        'x=radius*cos(angle)+xOrigin
        'y=raduis*sin(angle)+yOrigin
        'this basically is the basis for anything that moves in this example
        '
        'the 2 lines of code below make the monster move around, but
        'you can change this to anything you like, try setting x and y to the mouse
        'coordinates for example
        y = (15 * Cos(time * -6)) + (DeviceHeight/2 + (180 * Sin(time * 1.3)))
        x = (15 * Sin(time * -6)) + (DeviceWidth/2 + (200 * Cos(time / 1.5)))
        
        'put the head of the tail at x,y coords
        tail[0].x = x
        tail[0].y = y
    
        'update the tail
        'basically, the points don't move unless they're further that 7 pixels
        'from the previous point. this gives the kind of springy effect as the
        'body stretches
        For Local i:Int = 1 To segments - 1
               'calculate distance between the current point and the previous
                Local distX:Float = (tail[i - 1].x - tail[i].x)
                Local distY:Float = (tail[i - 1].y - tail[i].y)
            Local dist:Float = Sqrt(distX * distX + distY * distY)
              'move if too far away
                 If dist > 7 Then
                'the (distX*0.2) bit makes the point move
                'just 20% of the distance. this makes the
                'movement smoother, and the point decelerate
                'as it gets closer to the target point.
                'try changing it to 1 (i.e 100%) to see what happens
                tail[i].x = tail[i].x + (distX * (0.3))
                    tail[i].y = tail[i].y + (distY * (0.3))
                 Endif
            
        Next
    
        Return False
    End Method

    Method Draw()
        'time to draw stuff!
        
        'this sets the blend mode to LIGHTBLEND, or additive blending, which makes
        'the images progressively more bright as they overlap
        cv.SetBlendMode(BlendMode.Additive)
        '###########
        'draw the main bit of the body
        'start by setting the images handle (i.e the origin of the image) to it's center
        blob.SetHandle(0.5,0.5)
        
        
        'begin looping through the segments of the body
        For Local i:Int = 0 To segments - 1
            'set the alpha transparency vaue to 0.15, pretty transparent
            cv.SetAlpha 0.15
            'the  (0.5*sin(i*35)) bit basically bulges the size of the images being
            'drawn as it gets closer to the center of the monsters body, and tapers off in size as it gets
            'to the end. try changing the 0.5 to a higher number to see the effect.
            
            'draw the image
            cv.DrawImage blob, tail[i].x, tail[i].y,0,1 + (0.5 * Sin(i * 35)), 1 + (0.5 * Sin(i * 35))
            
            'this next chunk just draws smaller dots in the center of each segment of the body
            cv.SetAlpha 0.8
            
            cv.DrawImage blob, tail[i].x, tail[i].y,0,0.1, 0.1
        Next
        
        '#########################
        'draw little spikes on tail
        'note that the x and y scales are different
        
        'move the image handle to halfway down the left edge, this'll make the image
        'appear to the side of the coordinate it is drawn too, rather than the
        'center as we had for the body sections
        blob.SetHandle 0,0.5
        
        'rotate the 1st tail image. basically, we're calculating the angle between
        'the last 2 points of the tail, and then adding an extra wobble (the 10*sin(time*10) bit)
        'to make the pincer type effect.
        
        
        cv.DrawImage blob, tail[segments - 1].x, tail[segments - 1].y,10 * Sin(time * 10) + -calculateAngle(tail[segments - 1].x, tail[segments - 1].y, tail[segments - 5].x, tail[segments - 5].y) + 270,0.6, 0.1
        
        'second tail image uses negative time to make it move in the opposite direction
        
        cv.DrawImage blob, tail[segments - 1].x, tail[segments - 1].y,10 * Sin(-time * 10) + -calculateAngle(tail[segments - 1].x, tail[segments - 1].y, tail[segments - 5].x, tail[segments - 5].y) + 270,0.6, 0.1

        
        
        '#####################
        'draw little fins/arms
        cv.SetAlpha 1
        
        'begin looping through the body sections again. Note that we don't want fins
        'on the first and last section because we want other things at those coords.
        For Local i:Int = 1 To segments - 2
            'like the bulging body, we want the fins to grow larger in the center, and smaller
            'at the end, so the same sort of thing is used here.
            
            
            'rotate the image. We want the fins to stick out sideways from the body (the calculateangle() bit)
            'and also to move a little on their own. the 33 * Sin(time * 5 + i * 30) makes the
            'fin rotate based in the i index variable, so that all the fins look like they're moving
            'one after the other.
            cv.DrawImage blob, tail[i].x, tail[i].y,33 * Sin(time * 5 + i * 30) + -calculateAngle(tail[i].x, tail[i].y, tail[i - 1].x, tail[i - 1].y),0.1 + (0.6 * Sin(i * 30)), 0.05
            
            
            'rotate the opposte fin, note that the signs have changes (-time and -i*30)
            'to reflect the rotations of the other fin
            cv.DrawImage blob, tail[i].x, tail[i].y,33 * Sin(-time * 5 - i * 30) + -calculateAngle(tail[i].x, tail[i].y, tail[i - 1].x, tail[i - 1].y) + 180,0.1 + (0.6 * Sin(i * 30)), 0.05
            
            
        Next
        
        
        '###################
        'center the image handle
        MidHandle blob
        'Draw the eyes. These are just at 90 degrees to the head of the tail.
        cv.SetAlpha 0.1
        Local ang:Float = calculateAngle(tail[0].x, tail[0].y, tail[1].x, tail[1].y)
        cv.DrawImage blob, x + (7 * Cos(ang + 50)), y + (7 * Sin(ang + 50)),0,0.6, 0.6
        cv.DrawImage blob, x + (7 * Cos(ang + 140)), y + (7 * Sin(ang + 140)),0,0.6, 0.6
        
        cv.SetAlpha 0.5
        cv.DrawImage blob, x + (7 * Cos(ang + 50)), y + (7 * Sin(ang + 50)),0,0.1, 0.1
        cv.DrawImage blob, x + (7 * Cos(ang + 140)), y + (7 * Sin(ang + 140)),0,0.1, 0.1
    
        'draw beaky thing
        cv.SetAlpha 0.8
        blob.SetHandle 0,0.5
        
        cv.DrawImage blob, x, y,-ang + 275,0.3, 0.1
        
        'yellow light
        MidHandle blob
        cv.SetAlpha 0.2
        cv.DrawImage blob, x, y,0,4, 4
        
        'Finished!
    End Method
End   

'This function calculates and returns the angle between two 2d coordinates
Function calculateAngle:Float(x1:Float,y1:Float,x2:Float,y2:Float)
    Local theX:Float=x1-x2
    Local theY:Float=y1-y2
    Local theAngle:Float=-ATan2(theX,theY)
    Return theAngle
End Function

Class blob_monster Extends App

    Field blobimage:Image
    Field theMonster:BlobMonster
    Field canv:Canvas
        
     ' Stuff to do on startup...
    Method OnCreate ()
        canv = New Canvas
        blobimage=Image.Load( "blob.png" )

        theMonster=New BlobMonster(10,10,blobimage,canv)
        
        SetUpdateRate 60

    End

    ' Stuff to do while running...
    Method OnUpdate ()
    
        theMonster.Update()
    End

    ' Drawing code...
    Method OnRender ()
        canv.Clear(0, 0, 0.1)
        
        theMonster.Draw()
        canv.Flush()
    End

End

' Here we go!

Function Main ()
    New blob_monster                           
End
 
Thanks for helping out! I feel that I'm on the right track now with my game. Cheers!
 
Cerberus:
Import mojo2
'  SetHandle :  In mojo the values were pixels, in mojo2 its a Float value ranging from 0.0 to 1.0
Function Main ()
    New blob_monster                           
End

Class blob_monster Extends App

    Field blobimage:Image
    Field theMonster:BlobMonster
    Field canv:Canvas
        
    Method OnCreate ()
        canv = New Canvas
        blobimage=Image.Load("blob.png")
        theMonster=New BlobMonster(10,10,blobimage,canv)       
        SetSwapInterval 1 ; SetUpdateRate 0
    End

    Method OnUpdate ()   
        theMonster.Update()
    End

    Method OnRender ()
        canv.Clear(0,0,0.1)       
        theMonster.Draw()
        canv.Flush()
    End

End

' The overall Game object, handling loading, mouse position, high-level game control and rendering

Class point
    Field x:Float,y:Float
End

Function MidHandle (image:Image)
    image.SetHandle 0.5,0.5
End

Class BlobMonster

    Field x:Float,y:Float   
    Field speed:Float = 1   
    ' Number of nodes along the body, try changing it to 100
    Field segments:Float = 100
    ' Array to hold the points along the body
    Field tail:point[10]
    Field time:Float = 0
    Field blob:Image
    Field cv:Canvas

    Method New(inx:Float,iny:Float,inimage:Image,_cv:Canvas)
        x = inx
        y = iny
        Self.cv = _cv
        ' Give the tail some coordinates, just make them the same as the main x and y for now
        For Local i:Int = 0 To segments - 1
            tail[i] = New point
            tail[i].x = inx
            tail[i].y = iny
        Next
        blob=inimage
    End

    Method Update:Int()
        ' Time is a bit misleading, it's used for all sorts of things
        time+=speed
        ' Here the x and y coordinates are updated.
        ' this uses the following as a basic rule for moving things
        ' around a point in 2d space:
        ' x = radius*cos(angle)+xOrigin
        ' y = raduis*sin(angle)+yOrigin
        ' this basically is the basis for anything that moves in this example
        '
        ' the 2 lines of code below make the monster move around, but
        ' you can change this to anything you like, try setting x and y to the mouse
        ' coordinates for example
        y = (15 * Cos(time * -6)) + (DeviceHeight/2 + (180 * Sin(time * 1.3)))
        x = (15 * Sin(time * -6)) + (DeviceWidth/2 + (200 * Cos(time / 1.5)))       
        ' Put the head of the tail at x,y coords
        tail[0].x = x
        tail[0].y = y
        ' Update the tail
        ' Basically, the points don't move unless they're further that 7 pixels
        ' From the previous point. this gives the kind of springy effect as the
        ' Body stretches
        For Local i:Int = 1 To segments - 1
                ' calculate distance between the current point and the previous
                Local distX:Float = (tail[i - 1].x - tail[i].x)
                Local distY:Float = (tail[i - 1].y - tail[i].y)
            Local dist:Float = Sqrt(distX * distX + distY * distY)
                ' move if too far away
                 If dist > 7 Then
                ' the (distX*0.2) bit makes the point move just 20% of the distance. this makes the
                ' movement smoother,and the point decelerate as it gets closer to the target point.
                ' try changing it to 1 (i.e 100%) to see what happens
                 tail[i].x = tail[i].x + (distX * (0.3))
                 tail[i].y = tail[i].y + (distY * (0.3))
                 Endif
        Next
        Return False
    End Method

    Method Draw()
        cv.SetBlendMode BlendMode.Additive ' LIGHTBLEND or additive blending
        ' Draw the main bit of the body
        ' Start by setting the images handle (i.e the origin of the image) to it's center
        blob.SetHandle(0.5,0.5)
        ' Begin looping through the segments of the body
        For Local i:Int = 0 To segments - 1
            ' Set the alpha transparency vaue to 0.15,pretty transparent
            cv.SetAlpha 0.15
            ' The (0.5*sin(i*35)) bit basically bulges the size of the images being
            ' Drawn as it gets closer to the center of the monsters body, and tapers off in size as it gets
            ' To the end. try changing the 0.5 to a higher number to see the effect.
            cv.DrawImage blob,tail[i].x,tail[i].y,0,1 + (0.5 * Sin(i * 35)),1 + (0.5 * Sin(i * 35))
            
            ' This next chunk just draws smaller dots in the center of each segment of the body
            cv.SetAlpha 0.8
            cv.DrawImage blob,tail[i].x,tail[i].y,0,0.1,0.1
        Next
        ' Draw little spikes on tail
        ' Note that the x and y scales are different
        ' Move the image handle to halfway down the left edge,this'll make the image
        ' Appear to the side of the coordinate it is drawn too,rather than the
        ' Center as we had for the body sections
        blob.SetHandle 0,0.5       
        ' Rotate the 1st tail image. basically,we're calculating the angle between
        ' The last 2 points of the tail,and then adding an extra wobble (the 10*sin(time*10) bit)
        ' To make the pincer type effect.       
        cv.DrawImage blob,tail[segments - 1].x,tail[segments - 1].y,10 * Sin(time * 10) + -calculateAngle(tail[segments - 1].x,tail[segments - 1].y,tail[segments - 5].x,tail[segments - 5].y) + 270,0.6,0.1
        ' Second tail image uses negative time to make it move in the opposite direction
        cv.DrawImage blob,tail[segments - 1].x,tail[segments - 1].y,10 * Sin(-time * 10) + -calculateAngle(tail[segments - 1].x,tail[segments - 1].y,tail[segments - 5].x,tail[segments - 5].y) + 270,0.6,0.1
        ' Draw little fins/arms
        cv.SetAlpha 1
        
        ' Begin looping through the body sections again. Note that we don't want fins
        ' On the first and last section because we want other things at those coords.
        For Local i:Int = 1 To segments - 2
            ' Like the bulging body,we want the fins to grow larger in the center,and smaller
            ' At the end,so the same sort of thing is used here.

            ' Rotate the image. We want the fins to stick out sideways from the body (the calculateangle() bit)
            ' And also to move a little on their own. the 33 * Sin(time * 5 + i * 30) makes the
            ' Fin rotate based in the i index variable,so that all the fins look like they're moving
            ' One after the other.
            cv.DrawImage blob,tail[i].x,tail[i].y,33 * Sin(time * 5 + i * 30) + -calculateAngle(tail[i].x,tail[i].y,tail[i - 1].x,tail[i - 1].y),0.1 + (0.6 * Sin(i * 30)),0.05
            ' Rotate the opposte fin,note that the signs have changes (-time and -i*30)
            ' To reflect the rotations of the other fin
            cv.DrawImage blob,tail[i].x,tail[i].y,33 * Sin(-time * 5 - i * 30) + -calculateAngle(tail[i].x,tail[i].y,tail[i - 1].x,tail[i - 1].y) + 180,0.1 + (0.6 * Sin(i * 30)),0.05
        Next
        
        MidHandle blob
        ' Draw the eyes. These are just at 90 degrees to the head of the tail.
        cv.SetAlpha 0.1
        Local ang:Float = calculateAngle(tail[0].x,tail[0].y,tail[1].x,tail[1].y)
        cv.DrawImage blob,x + (7 * Cos(ang + 50)),y + (7 * Sin(ang + 50)),0,0.6,0.6
        cv.DrawImage blob,x + (7 * Cos(ang + 140)),y + (7 * Sin(ang + 140)),0,0.6,0.6
        cv.SetAlpha 0.5
        cv.DrawImage blob,x + (7 * Cos(ang + 50)),y + (7 * Sin(ang + 50)),0,0.1,0.1
        cv.DrawImage blob,x + (7 * Cos(ang + 140)),y + (7 * Sin(ang + 140)),0,0.1,0.1
    
        ' Draw beaky thing
        cv.SetAlpha 0.8
        blob.SetHandle 0,0.5
        cv.DrawImage blob,x,y,-ang + 275,0.3,0.1
        
        ' Yellow light
        MidHandle blob
        cv.SetAlpha 0.2
        cv.DrawImage blob,x,y,0,4,4
    End Method
End   

' This function calculates and returns the angle between two 2d coordinates
Function calculateAngle:Float(x1:Float,y1:Float,x2:Float,y2:Float)
    Local theX:Float = x1-x2
    Local theY:Float = y1-y2
    Local theAngle:Float =- ATan2(theX,theY)
    Return theAngle
End Function

Function circleoverlap:Bool(x1:Int,y1:Int,r1:Int,x2:Int,y2:Int,r2:Int)
    Local dx:Int = x1-x2
    Local dy:Int = y1-y2
    Local r:Int = r1+r2
    If dx*dx+dy*dy <= r*r Then Return True Else Return False
End

Function dot_product:Float(a:vectorf,b:vectorf)
    Return a.x * b.x + a.y * b.y
End Function

';= Get horizontal size of vector using distance and angle
Function vectorx:Float(distance:Float,angle:Float)
    Return Sin(angle)*distance
End Function
';= Get vertical size of vector using distance and angle
Function vectory:Float(distance:Float,angle:Float)
    Return Sin(angle-90)*distance
End Function
';= Get True length of a vector
Function vectordistance:Float(x:Float,y:Float)
    Return Sqrt(x*x+y*y)
End Function
';= Get True angle of a vector
Function vectorangle:Float(x:Float,y:Float)
    Return -ATan2(x,y)+180
End Function
Screenshot 2020-10-23 at 05.28.30.png
 
This is a good glow effect

Screenshot 2020-10-23 at 05.41.36.png


blob2.png
 
Here's another particle texture to try out, amazingly smooth. And it glows!

Screenshot 2020-10-23 at 05.49.38.png

glow2.png

Cerberus:
Strict
Import mojo2
'  SetHandle :  In mojo the values were pixels,in mojo2 its a Float value ranging from 0.0 to 1.0

Function Main:Int()
New blob_monster()
Return 0
End

Class blob_monster Extends App

Field blobimage:Image
Field theMonster:BlobMonster
Field canv:Canvas

Method OnCreate:Int()
canv = New Canvas
blobimage=Image.Load("glow2.png")
theMonster=New BlobMonster(10,10,blobimage,canv)
SetSwapInterval 1 ; SetUpdateRate 0
Return 0
End

Method OnUpdate:Int()
theMonster.Update()
Return 0
End

Method OnRender:Int()
canv.Clear 0,0,0.1
theMonster.Draw()
canv.Flush
Return 0
End

End

' The overall Game object,handling loading,mouse position,high-level game control and rendering

Class point
Field x:Float,y:Float
End

Function MidHandle:Void(image:Image)
image.SetHandle 0.5,0.5

End

Class BlobMonster

Field x:Float,y:Float
Field speed:Float = 1
' Number of nodes along the body,try changing it to 100
Field segments:Float = 100
' Array to hold the points along the body
Field tail:point[100]
Field time:Float = 0
Field blob:Image
Field cv:Canvas

Method New(inx:Float,iny:Float,inimage:Image,_cv:Canvas)
x = inx
y = iny
Self.cv = _cv
' Give the tail some coordinates,just make them the same as the main x and y for now
For Local i:Int = 0 To segments - 1
tail[i] = New point
tail[i].x = inx
tail[i].y = iny
Next
blob=inimage
End

Method Update:Int()
' Time is a bit misleading,it's used for all sorts of things
time+=speed
' Here the x and y coordinates are updated.
' this uses the following as a basic rule for moving things
' around a point in 2d space:
' x = radius*cos(angle)+xOrigin
' y = raduis*sin(angle)+yOrigin
' this basically is the basis for anything that moves in this example
'
' the 2 lines of code below make the monster move around,but
' you can change this to anything you like,try setting x and y to the mouse
' coordinates for example
y = (15 * Cos(time * -6)) + (DeviceHeight()/2 + (180 * Sin(time * 1.3)))
x = (15 * Sin(time * -6)) + (DeviceWidth()/2 + (200 * Cos(time / 1.5)))
' Put the head of the tail at x,y coords
tail[0].x = x
tail[0].y = y
' Update the tail
' Basically,the points don't move unless they're further that 7 pixels
' From the previous point. this gives the kind of springy effect as the
' Body stretches
For Local i:Int = 1 To segments - 1
' calculate distance between the current point and the previous
Local distX:Float = (tail[i - 1].x - tail[i].x)
Local distY:Float = (tail[i - 1].y - tail[i].y)
Local dist:Float = Sqrt(distX * distX + distY * distY)
' move if too far away
If dist > 7 Then
' the (distX*0.2) bit makes the point move just 20% of the distance. this makes the
' movement smoother,and the point decelerate as it gets closer to the target point.
' try changing it to 1 (i.e 100%) to see what happens
tail[i].x = tail[i].x + (distX * (0.3))
tail[i].y = tail[i].y + (distY * (0.3))
Endif
Next
Return False
End Method

Method Draw:Void()
cv.SetBlendMode BlendMode.Additive ' LIGHTBLEND or additive blending
' Draw the main bit of the body
' Start by setting the images handle (i.e the origin of the image) to it's center
blob.SetHandle(0.5,0.5)
' Begin looping through the segments of the body
For Local i:Int = 0 To segments - 1
' Set the alpha transparency vaue to 0.15,pretty transparent
cv.SetAlpha 0.15
' The (0.5*sin(i*35)) bit basically bulges the size of the images being
' Drawn as it gets closer to the center of the monsters body,and tapers off in size as it gets
' To the end. try changing the 0.5 to a higher number to see the effect.
cv.DrawImage blob,tail[i].x,tail[i].y,0,1 + (0.5 * Sin(i * 35)),1 + (0.5 * Sin(i * 35))

' This next chunk just draws smaller dots in the center of each segment of the body
cv.SetAlpha 0.8
cv.DrawImage blob,tail[i].x,tail[i].y,0,0.1,0.1
Next
' Draw little spikes on tail
' Note that the x and y scales are different
' Move the image handle to halfway down the left edge,this'll make the image
' Appear to the side of the coordinate it is drawn too,rather than the
' Center as we had for the body sections
blob.SetHandle 0,0.5
' Rotate the 1st tail image. basically,we're calculating the angle between
' The last 2 points of the tail,and then adding an extra wobble (the 10*sin(time*10) bit)
' To make the pincer type effect.
cv.DrawImage blob,tail[segments - 1].x,tail[segments - 1].y,10 * Sin(time * 10) + -calculateAngle(tail[segments - 1].x,tail[segments - 1].y,tail[segments - 5].x,tail[segments - 5].y) + 270,0.6,0.1
' Second tail image uses negative time to make it move in the opposite direction
cv.DrawImage blob,tail[segments - 1].x,tail[segments - 1].y,10 * Sin(-time * 10) + -calculateAngle(tail[segments - 1].x,tail[segments - 1].y,tail[segments - 5].x,tail[segments - 5].y) + 270,0.6,0.1
' Draw little fins/arms
cv.SetAlpha 1

' Begin looping through the body sections again. Note that we don't want fins
' On the first and last section because we want other things at those coords.
For Local i:Int = 1 To segments - 2
' Like the bulging body,we want the fins to grow larger in the center,and smaller
' At the end,so the same sort of thing is used here.

' Rotate the image. We want the fins to stick out sideways from the body (the calculateangle() bit)
' And also to move a little on their own. the 33 * Sin(time * 5 + i * 30) makes the
' Fin rotate based in the i index variable,so that all the fins look like they're moving
' One after the other.
cv.DrawImage blob,tail[i].x,tail[i].y,33 * Sin(time * 5 + i * 30) + -calculateAngle(tail[i].x,tail[i].y,tail[i - 1].x,tail[i - 1].y),0.1 + (0.6 * Sin(i * 30)),0.05
' Rotate the opposte fin,note that the signs have changes (-time and -i*30)
' To reflect the rotations of the other fin
cv.DrawImage blob,tail[i].x,tail[i].y,33 * Sin(-time * 5 - i * 30) + -calculateAngle(tail[i].x,tail[i].y,tail[i - 1].x,tail[i - 1].y) + 180,0.1 + (0.6 * Sin(i * 30)),0.05
Next

MidHandle blob
' Draw the eyes. These are just at 90 degrees to the head of the tail.
cv.SetAlpha 0.1
Local ang:Float = calculateAngle(tail[0].x,tail[0].y,tail[1].x,tail[1].y)
cv.DrawImage blob,x + (7 * Cos(ang + 50)),y + (7 * Sin(ang + 50)),0,0.6,0.6
cv.DrawImage blob,x + (7 * Cos(ang + 140)),y + (7 * Sin(ang + 140)),0,0.6,0.6
cv.SetAlpha 0.5
cv.DrawImage blob,x + (7 * Cos(ang + 50)),y + (7 * Sin(ang + 50)),0,0.1,0.1
cv.DrawImage blob,x + (7 * Cos(ang + 140)),y + (7 * Sin(ang + 140)),0,0.1,0.1

' Draw beaky thing
cv.SetAlpha 0.8
blob.SetHandle 0,0.5
cv.DrawImage blob,x,y,-ang + 275,0.3,0.1

' Yellow light
MidHandle blob
cv.SetAlpha 0.2
cv.DrawImage blob,x,y,0,4,4
End Method
End

' This function calculates and returns the angle between two 2d coordinates
Function calculateAngle:Float(x1:Float,y1:Float,x2:Float,y2:Float)
Local theX:Float = x1-x2
Local theY:Float = y1-y2
Local theAngle:Float =- ATan2(theX,theY)
Return theAngle
End Function

Function circleoverlap:Bool(x1:Int,y1:Int,r1:Int,x2:Int,y2:Int,r2:Int)
Local dx:Int = x1-x2
Local dy:Int = y1-y2
Local r:Int = r1+r2
If dx*dx+dy*dy <= r*r Then Return True Else Return False
End

Function dot_product:Float(a:vectorf,b:vectorf)
    Return a.x * b.x + a.y * b.y
End Function

';= Get horizontal size of vector using distance and angle
Function vectorx:Float(distance:Float,angle:Float)
Return Sin(angle)*distance
End Function
';= Get vertical size of vector using distance and angle
Function vectory:Float(distance:Float,angle:Float)
Return Sin(angle-90)*distance
End Function
';= Get True length of a vector
Function vectordistance:Float(x:Float,y:Float)
Return Sqrt(x*x+y*y)
End Function
';= Get True angle of a vector
Function vectorangle:Float(x:Float,y:Float)
Return -ATan2(x,y)+180
End Function
 
Last edited:
What is wrong with you? That cage is by far too small for that species. :p

It's great to see this running smoothly with mojo2!
 
Back
Top Bottom