Particules soumise a attraction

Description

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 :)

Codes Sources

A voir également

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.