Ok, try this code instead. Download the file anyway for the sprite:
'Code by R.Garcia 2013
' This is an example of checking collisions between objects with complex shapes defined
' by multiple circle collisions. The objects must have at least two collision circles,
' one that covers all the object, and then as many circles as needed to define the shape of the object.
' Three-Four circles are usually enough for me, but performance depends on how many circles are used.
' For SURE this code can be optimized and better written, as I'm a noobie with Monkey Language
' and not an expert programmer ;D
Strict
Import mojo
Global MyGame:Game
Global Actors:Actor[50] 'All "Actors" (or entities or objects,as you wish to call them) are stored here
Global Imagen:Image 'Sprite used in the example
'============================================================================================================
Function Main:Int () 'The "Main" function
MyGame=New Game()
Return 0
End
'============================================================================================================
Class Game Extends App
Field fpsShow:FpsCounter
Method OnCreate:Int ()
SetUpdateRate (60)
Imagen=LoadImage("helikop.png",1,1)
Imagen.SetHandle(50,50)
For Local i:Int=0 Until 50 'Generating 50 Actors
Actors[i]=New Actor()
Actors[i].id=i
Actors[i].X=Rnd(10,630)
Actors[i].Y=Rnd(10,470)
Next
fpsShow=New FpsCounter 'FPS displayer
Return 0
End
Method OnUpdate:Int ()
Actors[0].X=MouseX() 'This Actor will follow the mouse
Actors[0].Y=MouseY()
For Local i:Int = 0 Until Actors.Length()
'Updating the "Actors"
Actors[i].Update()
next
'Collisions
For Local i:Int = 0 Until (Actors.Length()-1)
'Each actor checks collision versus the other actors and then is ignored in the next checkings
For Local k:Int=i+1 Until (Actors.Length())
'At first we check the "big" collision circle that encapsulates the Actor.
'If there isn't collision, the next collision checkings are skipped.
'This speeds up the collision routine.
Local dx:Float = Actors[k].colCircles [0][0]-Actors[i].colCircles [0][0]
Local dy:Float = Actors[k].colCircles [0][1]-Actors[i].colCircles [0][1]
Local radii:Float = Actors[k].colCircles [0][2]+Actors[i].colCircles [0][2]
If ((dx*dx)+(dy*dy)<radii*radii)
'Now we calculate collisions between all the other collision circles of the actors.
For Local ii:Int=1 Until Actors[i].colCircles.Length
For Local kk:Int=1 Until Actors[k].colCircles.Length
Local sdx:Float = Actors[k].colCircles [kk][0]-Actors[i].colCircles [ii][0]
Local sdy:Float = Actors[k].colCircles [kk][1]-Actors[i].colCircles [ii][1]
Local sradii:Float = Actors[k].colCircles [kk][2]+Actors[i].colCircles [ii][2]
If ((sdx*sdx)+(sdy*sdy)<sradii*sradii)
'In case of collision, we can insert here the subsequent actions to be taken.
'As this is an example, it only change the color of the collision circle.
Actors[i].colCircles [ii][5]=1
Actors[k].colCircles [kk][5]=1
Endif
Next
Next
Endif
Next
Next
Return 0
End
Method OnRender:Int()
Cls (25,25,25)
For Local i:Int = 0 Until Actors.Length()
Actors[i].Render()
Next
fpsShow.Update()
fpsShow.Render()
Return 0
End
End
'============================================================================================================
Class Actor
Field id:Int
Field X:Float
Field Y:Float
Field Xant:Float
Field Yant:Float
Field direccion:Float
Field dirAnterior:Float
Field cosQuad:Int=1
Field sinQuad:Int=1
Field colCircles:Float[][]
Field velocidad:Float
Method New()
Xant=X
Yant=Y
direccion=0
dirAnterior=1
velocidad=0.1
colCircles=colCircles.Resize(5) ' Number of circles that will define the Actor (The first is the encapsulating circle)
For Local i:Int = 0 Until colCircles.Length() ' Resizing the table that will store the collision circle's data
colCircles[i]=New Float[6] ' Data of each circle : X from center,Y from center, radius, precalculated distance, precalculated angle, collision check
Next
colCircles [0] = [X+10,Y,50,0,0,0] 'These are the data of the circles. A graphical editor could be useful to define them.
colCircles [1] = [X+8,Y+6,22,0,0,0]
colCircles [2] = [X+16,Y-24,24,0,0,0]
colCircles [3] = [X+16,Y+36,4,0,0,0]
colCircles [4] = [X+44,Y-24,4,0,0,0]
For Local i:Int = 0 Until colCircles.Length() ' Precalculating distance and angle
colCircles [i][3]=Sqrt((Pow(colCircles [i][0]-X,2))+(Pow(colCircles [i][1]-Y,2)))
colCircles [i][4]=ATan2(colCircles [i][0]-X,colCircles [i][1]-Y)
Next
End
Method Update:Int ()
'Actor's movement
X-=(velocidad*Cos(direccion))
Y+=(velocidad*Sin(direccion))
direccion+=0.1
'Maintaining angle between 0-360 degrees
If direccion>=360
direccion=direccion-360
Elseif direccion<0
direccion=direccion+360
Endif
'Calculating the rotation of the collision circles
'This should be done only if the angle of the actor has changed form the last update.
If dirAnterior<>direccion Then
dirAnterior=direccion 'Storing last direction
For Local i:Int = 0 Until colCircles.Length()
Local distancia:Float = colCircles [i][3]
Local angulo:Float = colCircles [i][4]
Local x:Float=distancia*Cos(direccion+angulo)
Local y:Float=distancia*Sin(direccion+angulo)*-1
colCircles [i][0] = x+X
colCircles [i][1] = y+Y
Next
Else
For Local i:Int = 0 Until colCircles.Length()
Local distX:Float = X-Xant
Local distY:Float = Y-Yant
colCircles [i][0] = colCircles [i][0]+distX
colCircles [i][1] = colCircles [i][1]+distY
Next
EndIf
Xant=X
Yant=Y
Return 0
End
Method Render:Int ()
DrawImage(Imagen,X,Y,direccion,1.0,1.0,0)
For Local i:Int = 0 Until colCircles.Length()
If i=0 'First collision circle
SetColor (100,50,50)
SetAlpha (0.25)
Elseif Self.colCircles [i][5]=0 'Not collided circle
SetColor (50,100,50)
Else
SetColor (50,50,100) 'Collided circle
Endif
SetAlpha (0.5)
DrawCircle (colCircles[i][0], colCircles[i][1], colCircles[i][2])
Next
SetColor (255,255,255)
SetAlpha (1)
For Local i:Int = 0 Until colCircles.Length()
Self.colCircles [i][5]=0 'Marking all circles as "uncollided"
Next
Return 0
End
End
'===============================================================================================================================
Class FpsCounter
Field fpsCount:Int
Field startTime:Int
Field CurrentRate:Int
Method Update:Void()
If (Millisecs() - startTime) >= 1000
CurrentRate = fpsCount
fpsCount = 0
startTime = Millisecs()
Else
fpsCount += 1
End
End
Method Render:Void()
SetColor (255, 255, 255)
SetAlpha (1)
DrawText ("FPS >> " + CurrentRate, 4, 4)
End
End
'===============================================================================================================================
|