- Joined
- Jan 2, 2020
- Messages
- 1,345
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?
Wondering if anyone has a good idea how to create "magnet" food, something that lures the boids towards them?
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