• 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

Boids!

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,414
Trying to use Cerberus for avoiding obstacles..

Wondering if anyone has a good idea how to create "magnet" food, something that lures the boids towards them?


Screenshot 2022-01-31 at 16.26.33.png

Code:
#MOJO_AUTO_SUSPEND_ENABLED=False
Import mojo2

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

Function Main()
    New MyGame()
End

Class MyGame Extends App

    Field myboid:boid
    Field canvas:Canvas
   
    Method OnCreate()
        canvas = New Canvas()
        SetSwapInterval 1 ; SetUpdateRate 0
        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 OnUpdate()
        myboid.updateall()    
        If TouchDown(0) Then myobstacle.AddLast(New obstacle(TouchX(0),TouchY(0)))
    end
   
    Method OnRender()
        canvas.Clear
        canvas.SetColor 1,1,1
        myboid.drawall(canvas)
        For Local i:=Eachin myobstacle
            i.draw(canvas)
        Next
        canvas.Flush
    end
   
End Class

' -----------------------------------------------

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 draw(canvas:Canvas)
        canvas.SetColor 0,1,0
        canvas.DrawCircle x,y,radius
    end  
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 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 update()
        getfriends()
        If friendlist.Count > 0
            vx = 0 ; vy = 0
            cohesion() ; obstacle() ; distance() ; align()
        Else
            obstacle()
        End If      
        ' Clamp 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 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 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 distance()
        For Local i:=Eachin friendlist
            Local diffx:Float=x-i.x,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 align()
        Local sumvx:Float,sumvy:Float
        For Local i:=Eachin friendlist
            sumvx += i.vx ; sumvy += i.vy
        Next
        sumvx = sumvx /  friendlist.Count ; sumvy = sumvy / friendlist.Count
        vx = vx + (sumvx - vx) / alignspeed ; vy = vy + (sumvy - vy) / alignspeed
    end
   
    Method move()
        x = x + vx ; y = y + vy
        angle = smoothrotate(x,y,angle,x+vx,y+vy,smoothturn)
        x = x + Cos(angle) * speed ; y = y + Sin(angle) * speed
        If x < 0 Then x = x + 640
        If y < 0 Then y = y + 480
        If x > 640 Then x = x - 640
        If y > 480 Then y = y - 480
    end
   
    Method getfriends()
        friendlist.Clear()
            For Local i:=Eachin boidlist
            Local diffx:Float=x-i.x,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 updateall()
        For Local i:=Eachin boidlist
            i.update
        Next
    end
   
    Method drawall(canvas:Canvas)
        For Local i:=Eachin boidlist
            i.draw(canvas)
        Next
    end
   
    Method draw(canvas:Canvas)
        canvas.SetColor 1,1,1
        canvas.DrawCircle x,y,10
    end
   
    Function smoothrotate:Float(sourceX:Float,sourceY:Float,sourceAngle:Float,destX:Float,destY:Float,smooth:Float)
        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

End Class
 
I didn't try your code, but I would measure the distance between the food and the boid. If it is below a threshold value, I would make the boid move towards the food. If the boid has a direction, I would determine the shortest angle to towards the food and then make it move forward while turning into to that direction.
 
I didn't try your code, but I would measure the distance between the food and the boid. If it is below a threshold value, I would make the boid move towards the food. If the boid has a direction, I would determine the shortest angle to towards the food and then make it move forward while turning into to that direction.
That sounds like a good idea! I was first about to introduce some kind of gravity but what you said makes lots more sense as you never
know what's behind a corner. Some kind of distance would be good and to add eye-contact to add to the interest. Maybe some kind of trail of smell, that would make the gameplay more fun. I'll see what I can do!
 
Back
Top Bottom