Collision avec l'intérieur d'une shape

le pro masterchief Messages postés 57 Date d'inscription vendredi 4 novembre 2005 Statut Membre Dernière intervention 9 avril 2008 - 18 févr. 2007 à 17:55
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 - 20 févr. 2007 à 08:26
Bonjour, je dois créer une animation de boule qui rebondissent ensemble dans un shape, les balles doivent rebondir sur les paroie intérieure d'une shape ovale. J'avoue que je ne sais pas vraiment comment m'y prendre. Pour les collision entre les boule ça je suis capable mais pas avec la shape.
Les boule sont des picturebox et je suis sous vb6
Merci de m'aider.

11 réponses

jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
18 févr. 2007 à 18:22
Bonjour,

S'agissant d'une Shape (qui est un contrôle inerte) , je ne vois pas d'autres ressources  qu'un calcul trigonométrique, fait sur les bases suivantes :

- tu connais les coordonnées x et y du centre d'une balle
- la construction de ta forme ovale devrait par ailleurs te permettre d'en établir l'équation de courbe
- le rayon de la boule devrait te permettre de définir une 2ème courbe ovale, invisible, concentrique avec la première et à une distance de celle-ci (vers l'intérieur) égale au rayon de la boule... et d'en déterliner l'équation.

Il te faut ensuite, bien entendu, déterminer si le centre de ta boule coincide avec un point de cette dernière courbe.

Comme tu le vois, il s'agit avant tout d'un problème mathématique (trigonométrie).
Ce n'est que lorsque tu auras résolu ce problème (équations et comparaisons) sur papier que tu pourras commencer à parler de VB.

Il te faut donc nécessairement commencer par l'établissement de la deuxième équation puis par établir le raisonnement mathématique relatif à la vérification de ce qu'un point coincide ou non avec la courbe représentant cette équation.

Puis (et seulement alors) aller vers VB pour écrire tout celà
Nous t'y aiderons lorsque tu auras passé cette étape purement trigonométrique.
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
18 févr. 2007 à 18:37
Il reste que si tu n'utilisais pas une "Shape" et que tu acceptais de la remplacer par une ellipse (mais ce serait alors une ellipse et pas un ovale), les choses seraient largement facilitées (utilisation des fonctions PtInRect , PtInRegion, SetPixelV  et  CreateEllipticRgnIndirect de la librairie Lib gdi32 de l'Api de Windows, accompagnées de la fonction SetRect de la librairie user32
Car tout celà t'éviterait de longs calculs trigonométriques
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
18 févr. 2007 à 18:49
Mais si tu es débutant et non encore à l'aise avec l'utilisation des fonctions de l'Api de Windows, tu peux chercher une astuce de remplacement ...

En voilà une :

1) en lieu et place d'une Shape, dessiner ton ovale dans une couleur de remplissage identificatrice (soit sur ta Form, soit dans une PictureBox
2) ajouter aux coordonnées x et y du centre de la boule la valeur de son rayon
3) verifier que le pixel correspondant aux valeurs ainsi obtenues est bien de la couleur prédéfinie (et alors la boule est à l'intérieur) ou, au contraire, d'e la couleur de l' "entourage" (et alors la boule est à l'extérieur). La fonction Point de VB te permet de relever la couleur d'un pixel...

(astuce à cent sous...mais bonne)

Rien, de surcroît, ne t'empêche de ne faire varier que d'un point une seules des composantes RGB, de telle façon que bul ne saurait voir la différence entre le remplissage de ton ovale et la couleur qui l'entoure (on n'en verrait que la bordure).

Pour dessiner cet ovale : fonction Circle de VB
0
le pro masterchief Messages postés 57 Date d'inscription vendredi 4 novembre 2005 Statut Membre Dernière intervention 9 avril 2008
18 févr. 2007 à 20:45
Ok merci je vais y penser. Je vais plus me trourner vers la fonction circle. Sachez que je ne suis pas débutant. A+
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
18 févr. 2007 à 20:54
Reviens si tu n'y parviens pas !
En nous montrant toutefois ce que tu as essayé ...s'il te plait
Sache simplement que je viens de m'amuser à vérifier la faisabilité du "truc" (le dernier exposé) et... j'y suis très rapidement parvenu sans problèmes. J'ai juste ajouté un autre petit "truc jmfien" (que tu devrais également trouver facilement car il ne fait appel à aucune connaissance de VB mais au seul mécanisme de la pensée) pour éviter des vérifications et des calculs ralentisseurs (qui ne seraient pas les mêmes en fonction du sens de déplacement de la boule).
Le tout demande environ 8 minutes de concentration, pastis en main
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
18 févr. 2007 à 22:02
Bon...
une heure, c'est beaucoup pour si peu... et je commence à avoir sommeil, là...

Allez, on va bâcler et boucler cette "affaire :

Une form Form1
Sur ta form : une picturebox nommée picture1 et un Timer Timer1
A l'intérieur de ta Form : une shape nommée boule

Code :

Private Sub Form_Activate()
  Me.Move Screen.Width / 3, Screen.Height / 3, Screen.Width / 3, Screen.Height / 3
  With Picture1
     .Move 0, 0, 5000, 5000
     .BackColor = RGB(255, 255, 254)
     .AutoRedraw = True
     .FillColor = RGB(255, 255, 255)
     .FillStyle = 0
   End With
   Timer1.Enabled = True
   Picture1.Circle (2000, 2000), 1500, RGB(255, 0, 0), , , 1.5
   boule.Move 2500, 1500, 300, 300
   Timer1.Interval = 10
End Sub



Private Sub Timer1_Timer()
  boule.Move boule.Left - 3, boule.Top + 2
  If boum(Picture1, boule, vbWhite) Then
     Timer1.Enabled = False
     MsgBox "boum"
     Exit Sub
  End If
End Sub



Private Function boum(controle As PictureBox, maboule As Shape, couleur As Long) As Boolean
   X1 = maboule.Left + (maboule.Width / 2)
   Y1 = maboule.Top
   X2 = maboule.Left + maboule.Width
   Y2 = maboule.Top + (maboule.Height / 2)
   X3 = X1
   Y3 = Y1 + maboule.Height
   X4 = maboule.Left
   Y4 = Y2
  If controle.Point(X1, Y1) <> couleur Then boum = True: Exit Function
  If controle.Point(X2, Y2) <> couleur Then boum = True: Exit Function
  If controle.Point(X3, Y3) <> couleur Then boum = True: Exit Function
  If controle.Point(X4, Y4) <> couleur Then boum = True
End Function


Bonne nuit.














 
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
19 févr. 2007 à 14:07
Plus là !!!

Bon ...
Tiens donc, ami :

Si tu es capable de comprendre ce mécanisme (que tu dois lancer et attendre la sortie de la boule....),
tu es apte à traiter de collisions et de confinements...
Si tel n'est pas le cas, laisse tomber...

Private versgauche As Integer, versdroite As Integer, sensx As Single, sensy As Single, kx As Single, ky As Single
Private Sub Form_Activate()
  Randomize
  Me.Move Screen.Width / 3, Screen.Height / 3, Screen.Width / 3, Screen.Height / 3
  With Picture1
     .Move 0, 0, 5000, 5000
     .BackColor = RGB(255, 255, 254)
     .AutoRedraw = True
     .FillColor = RGB(255, 255, 255)
     .FillStyle = 0
   End With
   Timer1.Enabled = True
   Picture1.Circle (2000, 2000), 1500, RGB(255, 0, 0), , , 1.5
   boule.Move 2100, 700, 300, 300
   Timer1.Interval = 20
   versgauche = 120
   vershaut = 120
   sensx = -1
   sensy = 1
   kx = 1.3
   ky = 1.5
End Sub


Private Sub Timer1_Timer()
  boule.Move boule.Left + (versgauche + kx) * sensx, boule.Top + (vershaut + ky) * sensy
  DoEvents
  If boum(Picture1, boule, vbWhite) Then
     While boum(Picture1, boule, vbWhite)
       boule.Move boule.Left - Int((versgauche + kx) * sensx / 10), boule.Top - Int((vershaut + ky) * sensy / 10)
       DoEvents
     Wend
     sensx = -sensx
     sensy = sensy
     kx = Int((2 * Rnd) + 1) / 10
     ky = Int((20 * Rnd) + 1) ' / 3
  End If
End Sub


Private Function boum(controle As PictureBox, maboule As Shape, couleur As Long) As Boolean
   X1 = maboule.Left + (maboule.Width / 2)
   Y1 = maboule.Top
   X2 = maboule.Left + maboule.Width
   Y2 = maboule.Top + (maboule.Height / 2)
   X3 = X1
   Y3 = Y1 + maboule.Height
   X4 = maboule.Left
   Y4 = Y2
  If controle.Point(X1, Y1) <> couleur Then boum = True: Exit Function
  If controle.Point(X2, Y2) <> couleur Then boum = True: Exit Function
  If controle.Point(X3, Y3) <> couleur Then boum = True: Exit Function
  If controle.Point(X4, Y4) <> couleur Then boum = True
End Function
0
le pro masterchief Messages postés 57 Date d'inscription vendredi 4 novembre 2005 Statut Membre Dernière intervention 9 avril 2008
19 févr. 2007 à 22:26
Ok merci j'ai remplacé cela par des picture box ayant la même apparence qu'une ligne.

Avec quatre picture box jai formé un rectangle. Le picturebox du haut en forme de ligne ce nomme donc "haut" celui en bas "bas" et même chose pour la gauche et la droite.

Pour l'instant je fais uniquement rebondir les boule dans la boîte et non les boules entre eux.

Dim trajetX(70) As Long 'représente le nombre de left qui est incrémenter (un peu comme la vitesse)

Dim trajetY(70) As Long 'représente le nombre de top qui est incrémenter (un peu comme la vitesse)

'Dans le form load j'attribue une trajectoire aléatoire à chaque boule

For i = 1 To 70
Randomize
trajetX(i) = Int(Rnd * 200) - 200
picboule(i - 1).Left = picboule(i - 1).Left + trajetX(i)
Randomize
trajetY(i) = Int(Rnd * 200) - 200


picboule(i - 1).Top = picboule(i - 1).Top + trajetY(i)
Next i

'J'anime les boule et les fait rebondir avec la boite j'ai en tout 70 boule index de 0 à 69
'la fonction collision renvoi true si les deux controle en argument se touche
For i = 1 To 70
DoEvents

 picboule(i - 1).Left = picboule(i - 1).Left + trajetX(i)


 picboule(i - 1).Top = picboule(i - 1).Top + trajetY(i) If Collision(picboule(i - 1), gauche) True Or Collision(picboule(i - 1), droit) True Then trajetX(i) = -trajetX(i) If Collision(picboule(i - 1), haut) True Or Collision(picboule(i - 1), bas) True Then trajetY(i) = -trajetY(i)
 

Next i

Mais je veux aussi faire rebondir les balles entre eux mais j'ai un problème parce que jusque là jai tester la colision d'objet bien différent étant le rectangle et les boule mais pour les boule entre eux c'est plus difficile. J'avais pensé faire une boucle imbriqué que je testerai la collision de deux boule mais ça na pas marché. Si possible rester avec la fonction Collision(controle1 as control,controle2 as control) car elle est très simple.
Merci
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
19 févr. 2007 à 22:51
Le principe que je t'ai montré est valable dans tous les cas de figure : boule contre paroi, boule contre boule (les 2 se déplaçant ou pas...) puisque tu ne te sers que de la différence de couleurs pour savoir s'il y a collision ! Et tu pourrais même faire bouger la paroi (celà ne changerait absolument rien au principe !).
Si tu étais astucieux, tu pourrais même te servir de l'une des composantes R,G,B de tes boules pour savoir laquelle a été frappée
Mais, comme tu le vois, tout celà n'a rien à voir avec VB à proprement parler mais tout avec la seule agilité de ta pensée ... pour déterminer une stratégie...
Je te conseille vivement de tracer un cercle au sol, d'y faire "circuler" des billes, de raisonner... et d'en tirer les meilleures  conclusions.
Aucun code informatique, dans quelque langage que ce soit, ne t'affranchira de cette précieuse étape.

Restera ensuite, par contre, à calculer la nouvelle trajectoire de chaque boule après collision, suivant l'angle de collision, le(s) point(s) (car il y en a 2) de collision, la force de la collision en fonction de(s) vitesse(s) d'une boule contre la paroi ou de 2 boules s'entrechoquant, les effets de "ripping" induits en fonction des points de collision, etc...

J'espère que tu es très fort en mathémétiques, en cinétique et en dunamique.

Un "détail" : à moins que tes boules ne soient supposées avoir toutes le même poids, les mêmes dimensions et être faîtes dans la même matière, ces poids, dimensions et matuères devront également entrer en ligne de compte, ainsi que la nature supposée de leur plan d'évolution (sur du sable, ce n'est pas la même chose que sur du verre, par exemple, et ce ne sera pas non plus la même chose sur du feutre et sur du lin...) et la résistance à la déformation des parois de la "boîte".

Bon travail...
0
le pro masterchief Messages postés 57 Date d'inscription vendredi 4 novembre 2005 Statut Membre Dernière intervention 9 avril 2008
20 févr. 2007 à 00:25
Oui mais le problème cest que pour tester la collision entre toute les balle en même temps je fais exemple  If Collision(picboule(i - 1), picboule(i - 1), ) = True mais évidement les deux boule sont identique. Il faudrait passer par argument toute les boule pour pouvoir les vérifier. C'est ça qui est le problème. Parce que le shape j'ai abandonné ce concept.
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
20 févr. 2007 à 08:26
Non,
Si tu as bien compris le principe que je t'ai exposé, il te suffit de faire une boucle sur toutes les boules , une par une et pas par paires (qu'est-ce qui empêcherait, par ailleurs, des doubles, voire triple collisions ?)
Tu sais qu'une collision a été faite par une boule du simple fait que l'un de ses points de son périmètre "survole" un pixel d'une autre couleur que celle du fond de ta "boîte", tout simplement. Tu n'as de cette façon pas à tester toutes les combinaisons de tes boules prises 2 à 2... Ton test ne se fait que sur une boule à la fois, dans ta boucle sur la totalité de tes boules.

Pour savoir maintenant quelle boule a été touchée par la boule testée dans ta boucle, j'ai fait une allusion assez claire (une des composantes R,G,B de chaque boule peut servir à son identification.
A toi de savoir en profiter...
Mais c'est là ton jeu et ton application.
Je t'ai conduit aussi loin qu'il m'était possible sur le seul chemin qui me paraisse "jouable".
Le reste est maintenant ton affaire.
0
Rejoignez-nous