Collision_2D, deuxième épisode...

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Collision_2D, deuxième épisode...

Message par Huitbit »

Hello,

En ce moment, je m'amuse avec quelques modèles physiques issus de la mécanique du solide.
Voici une petite démo(sans prétention et sans commentaires :oops: ) où une petite boule se jette avec une vitesse aléatoire sur une grosse boule et s'accroche solidement !
Laissez tourner la démo pour voir différentes situations!

La physique, c'est magique ! :P
Imaginez un p'tit bonhomme suffisamment costaud (Chuck Norris ? :lol: ) à la place de la boule qui sauterait d'obstacles en obstacles !

Quand il y aura beaucoup d'épisodes "Collision_2D", je ferai un récapitulatif des lois physiques utilisées si ça intéresse quelqu'un :wink:

Code : Tout sélectionner

;collision_2
;auteur Huitbit
;pb v4.20
;*********************************
Enumeration
  #spr_decor
  #spr_1
  #spr_2
  #systeme_isole
  #chute_libre
  #pendule_pesant
EndEnumeration

#largeur_ecran=1024
#hauteur_ecran=768

#g=0.5
#dt=1

;boule n°1
#r_1=32
#m_1=1
x_1.f =0: y_1.f=128-2*#r_1
x_1_centre.f=x_1+#r_1 : y_1_centre.f=y_1+#r_1
vx_1.f=2+Random(16): vy_1.f=0

;boule n°2
#r_2=128
#m_2=4
x_2.f=512 : y_2.f=256
x_2_centre.f=x_2+#r_2 : y_2_centre.f=y_2+#r_2
vx_2.f=-2 : vy_2.f=2

#d_carre=(#r_1+#r_2)*(#r_1+#r_2)
#J=0.5*#m_1*#r_1*#r_1+#m_1*#d_carre+0.5*#m_2*#r_2*#r_2
omega.f

test.s=""
contact.b=0
modele.b
nom_modele.s
temps_d_arret.w
angle1.f
angle2.f

Macro test_variation_distance(x1c,y1c,vx1,vy1,x2c,y2c,vx2,vy2)
If (x1c-x2c)*(vx1-vx2)+(y1c-y2c)*(vy1-vy2)<0
  test="Rapprochement"
Else
  test="Eloignement"
EndIf
EndMacro

Macro test_contact(x1c,y1c,vx1,vy1,x2c,y2c,vx2,vy2)
If (x1c-x2c)*(x1c-x2c)+(y1c-y2c)*(y1c-y2c)<=#d_carre+1  And test="Rapprochement" 
  contact=1
  If modele=#chute_libre
    If x1c>x2c
      angle1=ATan((y1c-y2c)/(x1c-x2c))
    Else
      angle1=ATan((y1c-y2c)/(x1c-x2c))+#PI
    EndIf
    x1c=x2c+(#r_1+#r_2)*Cos(angle1)
    y1c=y2c+(#r_1+#r_2)*Sin(angle1)
    omega=#m_1/#J*((x1c-x2c)*vy1-(y1c-y2c)*vx1)
  EndIf
  temps_d_arret=temps_d_arret+1
  If temps_d_arret>300
    contact=0
    x1c=#r_1 : y1c=128-#r_1
    vx1=2+Random(16): vy1=0
    angle1=0
    angle2=0
    omega=0
    temps_d_arret=0
  EndIf
  
EndIf
EndMacro

Macro test_bord_ecran(xc,yc,vx,vy,r)
If modele=#chute_libre
  If xc+r>#largeur_ecran Or xc<128+r
    vx=-vx
  EndIf
  If yc+r>#hauteur_ecran-32 Or yc<r
    vy=-vy
  EndIf
EndIf
EndMacro

Macro choix_modele
If x_1_centre<128+#r_1 
  modele=#systeme_isole
  nom_modele="système isolé"
Else
  If contact=0
    modele=#chute_libre
    nom_modele="chute libre"
  Else
    modele=#pendule_pesant
    nom_modele="pendule pesant"
  EndIf
EndIf
EndMacro

InitSprite()
InitSprite3D()
InitKeyboard()
OpenWindow(0,0,0,#largeur_ecran,#hauteur_ecran,"Collision_2D",#PB_Window_ScreenCentered|#PB_Window_SystemMenu  )
OpenWindowedScreen(WindowID(0),0,0,#largeur_ecran,#hauteur_ecran,0,0,0)

CreateSprite(#spr_decor, #largeur_ecran,#hauteur_ecran)
StartDrawing(SpriteOutput(#spr_decor))
LineXY(0,128,128,128,RGB(0,0,255))
LineXY(128,128,128,736,RGB(0,0,255))
LineXY(128,736,1024,736,RGB(0,0,255))
StopDrawing()

CreateSprite(#spr_1,#r_1*2,#r_1*2)
StartDrawing(SpriteOutput(#spr_1))
DrawingMode(#PB_2DDrawing_Outlined)
Circle(#r_1,#r_1,#r_1,RGB(255,0,0))
Plot(#r_1,#r_1,RGB(255,255,255))
StopDrawing()

CreateSprite(#spr_2,#r_2*2,#r_2*2,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(#spr_2))
DrawingMode(#PB_2DDrawing_Outlined)
Circle(#r_2,#r_2,#r_2,RGB(0,255,0))
Line(#r_2,#r_2,#r_2,0,RGB(255,255,255))
StopDrawing()
CreateSprite3D(#spr_2,#spr_2)

Repeat
  
  Repeat
    Event = WindowEvent()      
    If  Event = #PB_Event_CloseWindow
      End 
    EndIf
  Until Event = 0
  
  choix_modele
  
  If modele=#systeme_isole
    x_1_centre=x_1_centre+vx_1*#dt
  EndIf
  
  If modele=#chute_libre
    vy_1=vy_1+#g*#dt
    x_1_centre=x_1_centre+vx_1*#dt
    y_1_centre=y_1_centre+vy_1*#dt
  EndIf
  
  If modele=#pendule_pesant
    omega=omega+#m_1/#J*(x_1_centre-x_2_centre)*#g*#dt
    angle1=angle1+omega*#dt
    x_1_centre=x_2_centre+(#r_1+#r_2)*Cos(angle1)
    y_1_centre=y_2_centre+(#r_1+#r_2)*Sin(angle1)
    
  EndIf
  
  test_variation_distance(x_1_centre,y_1_centre,vx_1,vy_1,x_2_centre,y_2_centre,vx_2,vy_2)
  test_contact(x_1_centre,y_1_centre,vx_1,vy_1,x_2_centre,y_2_centre,vx_2,vy_2)
  test_bord_ecran(x_1_centre,y_1_centre,vx_1,vy_1,#r_1)
  test_bord_ecran(x_2_centre,y_2_centre,vx_2,vy_2,#r_2)
  
  DisplaySprite(#spr_decor,0,0)
  DisplayTransparentSprite(#spr_1,x_1_centre-#r_1,y_1_centre-#r_1)
  Start3D()
  angle2=angle2+omega
  RotateSprite3D(#spr_2,angle2*180/#PI,0)
  DisplaySprite3D(#spr_2,x_2_centre-#r_2,y_2_centre-#r_2)
  Stop3D()
  StartDrawing(ScreenOutput())
  DrawText(0,20,"Modèle : "+nom_modele)
  StopDrawing()
  
  Delay(1)
  FlipBuffers() 
ForEver
Hasta la vista !
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Bluffant! :)
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Re: Collision_2D, deuxième épisode...

Message par kelebrindae »

Huitbit a écrit : Quand il y aura beaucoup d'épisodes "Collision_2D", je ferai un récapitulatif des lois physiques utilisées si ça intéresse quelqu'un
Moi, ça m'intéresse beaucoup! Un ch'tit tutorial sur le sujet serait le bienvenue, je pense.
Bravo!
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

balèze !! :D
Anonyme

Message par Anonyme »

Huit bit , t'es un serial coder :D
Un p'tit peu d'explication serais la bienvenue :D

Crois tu que c'est possible de faire un peut comme sonic ? looping , rampe ?? 8O
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

C'est excellent.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
chikun
Messages : 185
Inscription : sam. 21/juin/2008 13:36

Message par chikun »

:D tout simplement génial, j'adore....en plus la chute de l'objet en tenant compte de l'attraction et rebond sur sphere "aimantée" et balancement..
enfin à decortiquer pour ce que je suis en train de preparer :roll: sans grande prétention lol... :wink:

merci
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Message par Huitbit »

Merci !

Je pense que je ferai les tutos au fur et à mesure.

@Cpl.Bator
Avec le super lien donné par djes ça devrait pouvoir se faire.
Car pour l'exemple ci-dessus, j'étais à 100% dans l'inconnu (les gens ne jetent par leurs boules sur des roues qui tournent :lol: ), j'ai juste mis à l'épreuve les lois de la physique.
Alors que ce que tu demandes est traité dans la page :
http://www.myphysicslab.com/RollerSimple.html

Idem il faut que j'essaye la méthode de Runge Kutta pour la résolution des équations différentielles (j'ai vu ça il y a longtemps :roll: mais je ne l'ai jamais utilisé !).

En tout cas il y a de quoi faire !

@chickun
Pour les collisions, j'ai déjà fait un truc.
Pour ton problème tu peux poser r1=r2 et m1=m2(boules identiques) et tu verras bien des collisions avec des angles de 90 ! :wink:

Hasta la vista !
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Explications...

Message par Huitbit »

Hello

J'utilise la notation "bra ket" (voir mécanique quantique) pour représenter les vecteurs ! Le vecteur AB se note |AB>.

On travaille dans un repère (O,x,y,z) d'axes Ox, Oy et Oz avec les vecteurs associés |i>, |j>, |k> .

Allez jeter un coup d'oeil sur wikipédia si les notions de dérivée, vecteur, projection, produit scalaire, produit vectoriel ( exemples : moment d'une force |M> = |r> ^ |F>, moment cinétique |L> = |r> ^ |p>), moment d'inertie J, moment cinétique |L>, vous sont complètement inconnues !

Les explications suivent les différentes étapes de l'animation.

Modèle du système pseudo-isolé :

La somme des forces (le poids |P> et la réaction du sol |R>) qui s'exercent sur la boule (le système) se compensent.
1ère loi de Newton
Si |P> + |R> = |0> => la boule se déplace à vitesse constante (|v> = |constant>=|v0> vecteur vitesse initial)
or |v> = d|OG>/dt
Avec |OG> vecteur position (G centre de gravité de la boule et O, origine du repère).
Si on projette selon les axes Ox et Oy du repère on a :

vx = v0x = dx / dt
vy = v0y = dy / dt

Approximation d'Euler (on transforme la dérivée en une variation)
dx = v0x * dt
dy = v0y * dt

=> x = x + v0x * dt
=> y = y + v0y * dt
Voilà pour la position de la boule1 dans cette phase.

Modèle de la chute libre :

Il n'y a plus de sol => plus de réaction du sol => les forces ne se compensent plus
2ème loi de Newton
|P> = m * |a> avec m masse de la boule et |a> accélération de la boule.
Or |P> = m * |g> avec |g> champ de pesanteur
=> |a> = |g>
or |a> = d|v>/dt et |v> = d|OG>/dt
On projette puis on applique la méthode d'Euler:

vx = vx + gx * dt = vx
vy = vy + gy*dt = vy+g * dt
Car gx = 0 et gy = g (vecteur vertical, vers le bas comme l'axe des y)

x = x + vx * dt
y = y + vy * dt

Collision boule1-boule2

Modèle utilisé : conservation du moment cinétique lors du choc
On appelle G1 et G2 les centres de gravité des boules.
J le moment d'inertie du système après le choc (boule1 et boule2 collées)

Ici J = J(boule1) + J(boule2) + (prise en compte de la distance qui sépare G1 de G2 avec le théorème de Huygens)
(Dans le code, j'ai pris le J d'un cylindre, c'est à dire 0.5*masse*rayon²)

Selon la situation, on peut exprimer le moment cinétique total de différentes manières :
Avant le choc m1 * |G2G1> ^ |v1> (la boule2 est immobile)
Après le choc J * w * |k> avec w vitesse angulaire du nouveau système, |k> vecteur unitaire de l'axe Oz.
A noter w = da / dt avec a, angle de rotation du nouveau système.

On a donc m1 * |G2G1> ^ |v1> = J * w * |k>
=> w * |k> = m1 * |G2G1> ^ |v1> / J
w = m1 * [(x1 – x2) * vy1 – (y1 – y2)*vx1] / J
Cette valeur de w fixera l'état initial du pendule pesant.

Remarque : pour des raisons esthétiques, je replace systématiquement la boule1 à la bonne distance après le choc !
Pour cela je calcule l'angle que fait le rayon |G1G2> avec le vecteur unitaire de l'axe des x (attention au signe avec l'arctangente !)

Code : Tout sélectionner

    If x1c>x2c
      angle1=ATan((y1c-y2c)/(x1c-x2c))
    Else
      angle1=ATan((y1c-y2c)/(x1c-x2c))+#PI
    EndIf
    x1c=x2c+(#r_1+#r_2)*Cos(angle1)
    y1c=y2c+(#r_1+#r_2)*Sin(angle1)
Modèle du pendule pesant :

Principe fondamental de la dynamique pour les solides en rotation
« La somme des moments des forces est égale à la dérivée du moment cinétique »
Ici, la seule force qui ait un moment est le poids |P> (on néglige les forces de frottements depuis le début !)
On a donc :
|GG2 > ^ |P> = J * dw/dt * |k> avec G centre de gravité du nouveau système
|GG2 > ^ (m1+m2) * |g> = J * dw/dt * |k>

Rappel : G est tel que m1 * |GG1> + m2 * |GG2> = |0>
Ce qui donne |GG2> = m1 * |G1G2> / (m1 +m2)

Si on remplace on a
m1 * |G1G2> ^ |g> = J * dw/dt * |k>
m1 * (x2-x1) * g * |k> = J * dw/dt * |k>
dw/dt = m1 * (x2-x1) * g / J

On applique la méthode d'Euler :
w = w + m1 * (x2-x1) * g / J * dt
de même pour l'angle de rotation a = a +w * dt

Et voilà !

On a la variation de l'angle du pendule au cours du temps !

Remarques :
-n'hésitez pas à demander un complément d'informations
-dans le code, dt = 1 cela veut dire que l'on peut remplacer "x = x + v0x * dt" par "x = x +v0x". Je laisse cependant le "dt" car additionner une position avec une vitesse en physique, C'EST MAL :lol: :lol:
-pour les frottements, il n'y a pas grand chose à rajouter, on verra ça dans un autre épisode !

@Cpl.Bator
le prochain code sera du style montagnes russes (looping, etc...) :wink:

Bonus : blagues des profs de mécanique quantique
Le ket psi colle à... :roll: (Note : le ket psi est utilisé pour les fonctions d'onde)
Ne pas laisser son bra ket ouvert 8O
etc...

Hasta la vista !
Dernière modification par Huitbit le ven. 11/juil./2008 17:46, modifié 11 fois.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

C'est vraiment le genre de petit code sympa que j'adore ! Bravo HuitBit !
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

arf !! je n'ai compris que les blagues a la fin :lol:
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Super !

S'il pleut ce week-end je saurai quoi faire, je vais étudier tes explications et triturer ton code pour y mettre des noms de variable plus explicites :)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Re: Collision_2D, deuxième épisode...

Message par beauregard »

Huitbit a écrit :Hello,
En ce moment, je m'amuse avec quelques modèles physiques issus de la mécanique du solide
et c'est impressionnant ! :D La méthode utilisée ne doit pas être très éloignée de celle dont bénéficie SuperMarioGalaxy !!! merci pour ce précieux codeImage
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

Répondre