Intersection de deux cercles
Publié : lun. 19/sept./2005 0:30
J'espère ne pas faire double emploi avec un code antérieur.
Je me suis attaché à réfléchir sur les collisions de sprites.
Pour commencer par exercice de niveau intermédiaire, c'est à dire qui permette d'être plus précis que le SpriteCollision() de base, j'ai choisi d'envisager le test de collision de deux enveloppes circulaires.
Voici une proposition de code à peu près optimisé.
Le programme principal est une simple mise en oeuvre pour montrer le résultat de la procédure.
Si les deux cercles testés sont en contact, ils sont affichés en rouge, sinon ils sont en blanc.
L'utilisation de ce type de calcul dans une gestion de sprites avec enveloppes circulaires (des balles en particulier), est simple. Attention toutefois, la procédure prend en argument les coordonnées des centres et les rayons. Lorsqu'on affiche un sprite, les paramètres d'affichage sont le coin haut gauche et la taille (correspondant au diamètre dans le cas d'une balle).
Je vais laisser ce chapitre ouvert sur mon PC, pour proposer des variantes de tests de collisions si il y a des amateurs.
Petite explication pour l'algorithme utilisé ici : on considère les équations respectives de chacun des cercles, et on travaille sur la différence des équations.
Par le jeu du raisonnement mathématique, on constate que la différence des équations des deux cercles revient à une forme de polynome du second degré. Lorsque l'on calcule les racines de cette équation finale, on en déduit les points d'intersection éventuels des cercles. Si il y a au moins un point d'intersection c'est que les cercles se touchent ou se superposent en tout ou partie.
Je me suis attaché à réfléchir sur les collisions de sprites.
Pour commencer par exercice de niveau intermédiaire, c'est à dire qui permette d'être plus précis que le SpriteCollision() de base, j'ai choisi d'envisager le test de collision de deux enveloppes circulaires.
Voici une proposition de code à peu près optimisé.
Le programme principal est une simple mise en oeuvre pour montrer le résultat de la procédure.
Si les deux cercles testés sont en contact, ils sont affichés en rouge, sinon ils sont en blanc.
L'utilisation de ce type de calcul dans une gestion de sprites avec enveloppes circulaires (des balles en particulier), est simple. Attention toutefois, la procédure prend en argument les coordonnées des centres et les rayons. Lorsqu'on affiche un sprite, les paramètres d'affichage sont le coin haut gauche et la taille (correspondant au diamètre dans le cas d'une balle).
Je vais laisser ce chapitre ouvert sur mon PC, pour proposer des variantes de tests de collisions si il y a des amateurs.
Petite explication pour l'algorithme utilisé ici : on considère les équations respectives de chacun des cercles, et on travaille sur la différence des équations.
Par le jeu du raisonnement mathématique, on constate que la différence des équations des deux cercles revient à une forme de polynome du second degré. Lorsque l'on calcule les racines de cette équation finale, on en déduit les points d'intersection éventuels des cercles. Si il y a au moins un point d'intersection c'est que les cercles se touchent ou se superposent en tout ou partie.
Code : Tout sélectionner
Procedure Circles_Collision(x1.f, y1.f, r1.f, x2.f, y2.f, r2.f)
dx.f = (x1 - x2)
dy.f = (y1 - y2)
If Abs(dx) <= r1 And Abs(dy) <= r1
ProcedureReturn #True
EndIf
If dx = 0 And dy = 0
ProcedureReturn #True
Else
dxdy.f = dx / dy
N.f = (r2 * r2 - r1 * r1 - x2 * x2 + x1 * x1 - y2 * y2 + y1 * y1) / (2 * (y1 - y2))
A.f = dxdy * dxdy + 1
B.f = 2 * y1 * dxdy - 2 * N * dxdy - 2 * x1
C.f = (x1 * x1 + y1 * y1 + N * N - r1 * r1 - 2 * y1 * N)
Delta.f = B * B - 4 * A * C
If Delta < 0
ProcedureReturn #False
Else
ProcedureReturn #True
EndIf
EndIf
EndProcedure
ScreenWidth = GetSystemMetrics_(#SM_CXSCREEN)
ScreenHeight = GetSystemMetrics_(#SM_CYSCREEN)
ScreenDepth = 32
If InitSprite() And InitMouse() And InitKeyboard()
If OpenScreen(ScreenWidth, ScreenHeight, ScreenDepth, "")
Quit = #False
Repeat
FlipBuffers()
ClearScreen(0, 0, 0)
ExamineKeyboard()
ExamineMouse()
MouseX = MouseX()
MouseY = MouseY()
If KeyboardPushed(#PB_Key_Escape) : Quit = #True : EndIf
StartDrawing(ScreenOutput())
DrawingMode(4)
If Circles_Collision(ScreenWidth / 2, ScreenHeight / 2, 200, MouseX, MouseY, 200)
Color = #Red
Else
Color = #White
EndIf
Circle(ScreenWidth / 2, ScreenHeight / 2, 200, Color)
Circle(MouseX, MouseY, 200, Color)
StopDrawing()
Until Quit
EndIf
EndIf
End