Quel est le mouvement d'un ensemble de particules lorsque elles sont soumises à leur propre force d'attraction ou répulsion ?
Ce bout de code datant de 2000 (wai à l'époque du lycée et des cours de physique, ouaouh) ... simule ces particules avec un champs d'attraction ou répulsion soit uniforme, soit dépendant de la "masse" de chaque particule (plus elle est "sombre", plus c'est faible)
En jouant sur la force de répultion/attraction et la friction (force de freinage) du milieu, on obtient.... bah, un écran de veille.
on peut dire qu'il s'agit de pseudo-gravitation (car uniforme)
compilez le code pour de meilleur performances (8x plus rapide...)
Source / Exemple :
'voir zip
'fragment : kernel de calcul de l'attraction mutuelle
Type PARTICULE
CoordX As Double
CoordY As Double
MvX As Double
MvY As Double
Coul As Long 'peut egalement servir de masse
End Type
Public Const Pi As Double = 3.1415926535893
Public Spot(2048) As PARTICULE 'l'objet "spot"
'voir zip pour code de génération des coordonnées.
Sub Material(Signe As Double)
'Par rapport à Repluse(), Material() gère la masse (couleur)
'Material() à été optimisé en intégrant la boucle de calcul de tout les spots
'calcul de var globale
Friction = Fri / 200 + 1
Rebond = Bounce / 20 + 1
MaterialMasse = TotSpot * 1024
Who = 1
Do While Who <= TotSpot
With Spot(Who)
cdx = .CoordX
cdy = .CoordY
Plx = 0
Ply = 0
'Determination des vecteurs forces que chaque spot
'applique au spot actuel Who&
ic = 1
Do While ic <= TotSpot
If ic <> Who Then 'esquive du calcul sur lui-même
'Calcul de la distance
Dist = PytagoreEx(Spot(ic).CoordX - cdx, Spot(ic).CoordY - cdy)
'Calcul de la force exercée
'(en rapport avec la masse decroissant avec la distance)
Fc = Signe / (Dist + 0.01) * Coef + (Spot(ic).Coul / MaterialMasse) * Signe
'Calcul de l'angle de la force (radian)
If cdx - Spot(ic).CoordX <> 0 Then
Ang = Atn(Abs((cdy - Spot(ic).CoordY) / (cdx - Spot(ic).CoordX)))
'Atn() ne renvoi qu'un angle entre 0 et pi/2, il faut donc calculer les autres
If cdx >= Spot(ic).CoordX Then
If cdy < Spot(ic).CoordY Then
Ang = -Ang '- Pi / 2
End If
Else
If cdy < Spot(ic).CoordY Then
Ang = Abs(Ang) - Pi
Else
Ang = Pi - Ang
End If
End If
Else
Ang = 0
End If
'Calcul Des coordonnées cartésiennes du vecteur force:
Fcx = Cos(Ang) * Fc
Fcy = Sin(Ang) * Fc
'Cumule des forces: influence sur le spot
'Le vecteur résultant est Pl(PlX,PlY)
Plx = Plx + Fcx
Ply = Ply + Fcy
End If
ic = ic + 1
Loop
'La force obtenu influe sur l'angle du déplacement et la
'vitesse de déplacement actuel du spot.
'Et maintenant le nouveau vecteur Nv(NvX,NvY) avec la friction:
Nvx = (.MvX + Plx) / Friction
Nvy = (.MvY + Ply) / Friction
'On le met en mémoire
.MvX = Nvx
.MvY = Nvy
'Puis on recalcule les nouvelles coordonnées du spot:
'(déplacement)
.CoordX = cdx + Nvx
.CoordY = cdy + Nvy
'Test si le spot est hors de l'écran:
If .CoordY > SizeY - 1 Or .CoordY < 1 Then
'nouveau vecteur (rebondit sur Y)
.MvY = -.MvY / Rebond
'et on recalcul la position de façon à ce que le spot soit DANS la zone...
.CoordY = .CoordY - Nvy
End If
If .CoordX > SizeX - 1 Or .CoordX < 1 Then
'nouveau vecteur (rebondit sur X)
.MvX = -.MvX / Rebond
'et on recalcul la position de façon à ce que le spot soit DANS la zone...
.CoordX = .CoordX - Nvx
End If
End With
Who = Who + 1
Loop
'Il ne reste plus qu'à l'afficher
End Sub
Private Function PytagoreEx(Val1 As Double, Val2 As Double) As Double
PytagoreEx = Sqr(Val1 * Val1 + Val2 * Val2)
End Function
Conclusion :
Il serai interessant d'utiliser ce "code de déplacement" pour calculer le déplacement de... point sprites sous directx ? ;)
bug : en dessous d'une répultion à 7, le comportement devient méchament stable. Je laisse ce bug néanmoins, car ça permet de faire des jolie effets
comportement interessant :
mode Attraction et Utiliser masse
plus de 128 points
repulsion : 8
friction : 150
vous pouvez changer en temps réel ces variables, ainsi que la taille de la fenêtre.
Essayer un maximum de configuration, et cocher la case "trace" pour faire des zoli zimaz comme sur le screenshot (cé ti pa zoli ! non?)
Là j'ai testé une config exploitant le bug précité, provoquant un point singulier où tout les points se réunissent, puis hop mode répultion et kaboum :)
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.