Page 1 sur 1

Simaluteur planétaire

Publié : mar. 11/janv./2005 0:22
par Le Soldat Inconnu
Salut,

Je me suis amusé à faire un simulateur de gravité dans lequel j'ai placé des planètes.
je leur ai donné une masse et une vitesse de départ.
Ensuite, le logiciel prend le relais grace à la loi de la gravité. j'obtients un système planétaire :D

Laissez les planètes éloignées faire plusieurs tours et vous allez voir le système plantéaire partir en vrac, c'est rigolo :wink:

Cette version n'est pas définitive, j'ai un problème de précision (quand 2 planètes sont trop proches, elle prennent des accélérations monstrueuses, il faut que je fasse tous mes calculs de gravité par intégration, vive les math et la bavasse)

Code : Tout sélectionner

Structure InfoGravite
  ID.l
  x.f
  y.f
  Vx.f
  Vy.f
  m.f
  Etat.b
EndStructure

NewList Gravite.InfoGravite()

Procedure AddGravityObject(ID, x.f, y.f, Vitesse_X.f, Vitesse_Y.f, Masse.f, Etat.b)
  AddElement(Gravite())
  Gravite()\ID = ID
  Gravite()\x = x
  Gravite()\y = y
  Gravite()\Vx = Vitesse_X
  Gravite()\Vy = Vitesse_Y
  Gravite()\m = Masse
  Gravite()\Etat = Etat
EndProcedure

Procedure RemoveGravityObject()
  DeleteElement(Gravite())
EndProcedure

Procedure GetGravityObjectPos(*Position.POINT)
  *Position\x = Gravite()\x
  *Position\y = Gravite()\y
EndProcedure

Procedure SetGravityObjectPos(*Position.POINT)
  Gravite()\x = *Position\x
  Gravite()\y = *Position\y
EndProcedure

Procedure.l GetGravityObjectID()
  ProcedureReturn Gravite()\ID
EndProcedure

Procedure.l NextGravityObject()
  ProcedureReturn NextElement(Gravite())
EndProcedure

Procedure MoveGravityObject()
  ForEach Gravite()
    *Objet.InfoGravite = @Gravite()
    ForEach Gravite()
      If *Objet <> @Gravite() ; Si on a un élément différent de celui sélectionné
        
        ; Calcul de la direction
        Dx.f = (Gravite()\x - *Objet\x) ; Distance en X
        Dy.f = (Gravite()\y - *Objet\y) ; Distance en y
        D2.f = Dx * Dx + Dy * Dy ; Distance au carré
        If D2 <> 0
          D.f = Sqr(D2)
          Dx = Dx / D ; Vecteur direction
          Dy = Dy / D
          
          ; Calcul de la gravité et donc de l'évolution de la vitesse
          ; Gravité = k * Masse / Distance²
          G1.f = *Objet\m / D2
          G2.f = Gravite()\m / D2
          *Objet\Vx + G2 * Dx
          *Objet\Vy + G2 * Dy
          Gravite()\Vx - G1 * Dx
          Gravite()\Vy - G1 * Dy
        EndIf
      EndIf
    Next
    ChangeCurrentElement(Gravite(), *Objet)
  Next
  
  ; On calcul les nouvelles positions
  ForEach Gravite()
    If Gravite()\Etat = 0
      Gravite()\x + Gravite()\Vx ; On déplace l'objet
      Gravite()\y + Gravite()\Vy
    EndIf
  Next
  
  ResetList(Gravite())
EndProcedure



#Ecran_Largeur = 1024
#Ecran_Hauteur = 768

; On ouvre l'openscreen
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  MessageRequester("Erreur", "Impossible d'initialiser la souris ,le clavier ou l'écran. Vérifiez la présence de DirectX 7 ou supérieur.", 0)
  End
EndIf

If OpenScreen(#Ecran_Largeur, #Ecran_Hauteur, 32, "Gravité") = 0
  MessageRequester("Erreur", "Impossible d'ouvrir l'écran.", 0)
  End
EndIf

CreateSprite(0, 5, 5)
StartDrawing(SpriteOutput(0))
  Circle(2, 2, 2, $FFFFFF)
StopDrawing()

CreateSprite(1, #Ecran_Largeur, #Ecran_Hauteur)


; Pour ajouter des planète, c'est ici :

; AddGravityObject(ID, x.f, y.f, Vitesse_X.f, Vitesse_Y.f, Masse.f, Etat.b)
; ID : Identifiant de la planete
; x.f, y.f : Position de départ
; Vitesse_X.f, Vitesse_Y.f : Vitesse de départ
; Masse : mAsse de la planète (plus la planète est lourde et plus elle attire les autres
; Etat : Si = 1, la planète est fixe

AddGravityObject(0, 500, 350, 0, 0, 200, 0)
AddGravityObject(1, 200, 350, 0, 1, 10, 0)
AddGravityObject(2, 210, 350, 0, 0, 0.001, 0)
AddGravityObject(3, 800, 350, 0, -1, 10, 0)
AddGravityObject(4, 540, 350, 0, 3, 0.001, 0)

Repeat
  ClearScreen(0, 0, 0)

  ; On lit les évènements clavier et souris
  ExamineMouse()
  ExamineKeyboard()
  
  ; Position de la souris
  x = MouseX()
  y = MouseY()
  
  DisplaySprite(1, 0, 0)
  
  MoveGravityObject()
  While NextGravityObject()
    GetGravityObjectPos(@Objet.POINT)
    DisplaySprite(0, Objet\x - 2, Objet\y - 2)
    
    ; Traits des trajectoires
    StartDrawing(SpriteOutput(1))
      Box(Objet\x, Objet\y, 1, 1, $767676)
    StopDrawing()
    
    ; Deboguage
    StartDrawing(ScreenOutput())
      Locate(0, 15 * GetGravityObjectID())
      DrawText(Str(Objet\x) + ", " + Str(Objet\y))
    StopDrawing()
    
  Wend
  
  FlipBuffers()
  
  If IsScreenActive() = 0
    End
  EndIf
  
Until KeyboardPushed(#PB_Key_Escape)

Publié : mar. 11/janv./2005 0:38
par Dräc
Amusant :)

Publié : mar. 11/janv./2005 7:12
par garzul
Vraiment cool :)

Publié : mar. 11/janv./2005 10:29
par Thyphoon
Bon et quand est ce que le système solaire partira en cou...lle lui ??? :lol: en tout cas tres sympa

Publié : mar. 11/janv./2005 18:09
par Oliv
ça fait de Jolis dessins :D

Publié : mer. 12/janv./2005 15:52
par Aranoth
joli !


Sauf qu'au bout d'un moment, la petite lune qui tourne autour de la planete, bah...elle décolle et pars en vrille dans le décor

Publié : mer. 26/janv./2005 21:34
par jnspunk
Essayez d' ajouter ça, ça fait une trajectoire pas comme les autres :D
AddGravityObject(5, 840, 350, 0, -0.51, 0.001, 0)

^^

Publié : mer. 26/janv./2005 22:12
par Ouaf-Ouaf
Yess avec cette planète ca deviens carrement trippant 8) .
Je vais m'amuser a en tester d'autres
C'est marrant le côté un peu innatendu que peux avoir un programme.

Publié : mer. 26/janv./2005 23:37
par Le Soldat Inconnu
je pense avoir trouvé la solution au prob d'intégration, mais c'est chaud, vive les maths

pour voir le prob actuel, testez ceci :

Code : Tout sélectionner

AddGravityObject(0, 500, 350, 0, 0, 200, 1) 
AddGravityObject(1, 200, 350, 0, 1, 10, 0) 
AddGravityObject(2, 210, 350, 0, 0, 0.001, 0) 
AddGravityObject(3, 800, 350, 0, 0, 10, 0) 
AddGravityObject(4, 540, 350, 0, 3, 0.001, 0) 
normalement, la plantée 4 doit osciller autour du soleil suivant une trajectoire rectiligne (comme si le soleil était le filet et la planète une balle renvoyée par 2 joueurs de ping pong) mais elle prend de la vitesse en s'approchant, et ne la perd pas du à un problème de précision de calcul.

Publié : jeu. 27/janv./2005 11:11
par Backup
@soldat :lol: fait gaffe tu commence a faire des programme (DD)
(Dobro Delirium) , la folie est contagieuse !! :lol:

Publié : ven. 04/mai/2007 13:52
par Thyphoon
Version PB 4

Code : Tout sélectionner

Structure InfoGravite
  ID.l
  x.f
  y.f
  Vx.f
  Vy.f
  m.f
  Etat.b
EndStructure

Global NewList Gravite.InfoGravite()

Procedure AddGravityObject(ID, x.f, y.f, Vitesse_X.f, Vitesse_Y.f, Masse.f, Etat.b)
  AddElement(Gravite())
  Gravite()\ID = ID
  Gravite()\x = x
  Gravite()\y = y
  Gravite()\Vx = Vitesse_X
  Gravite()\Vy = Vitesse_Y
  Gravite()\m = Masse
  Gravite()\Etat = Etat
EndProcedure

Procedure RemoveGravityObject()
  DeleteElement(Gravite())
EndProcedure

Procedure GetGravityObjectPos(*Position.POINT)
  *Position\x = Gravite()\x
  *Position\y = Gravite()\y
EndProcedure

Procedure SetGravityObjectPos(*Position.POINT)
  Gravite()\x = *Position\x
  Gravite()\y = *Position\y
EndProcedure

Procedure.l GetGravityObjectID()
  ProcedureReturn Gravite()\ID
EndProcedure

Procedure.l NextGravityObject()
  ProcedureReturn NextElement(Gravite())
EndProcedure

Procedure MoveGravityObject()
  ForEach Gravite()
    *Objet.InfoGravite = @Gravite()
    ForEach Gravite()
      If *Objet <> @Gravite() ; Si on a un élément différent de celui sélectionné
       
        ; Calcul de la direction
        Dx.f = (Gravite()\x - *Objet\x) ; Distance en X
        Dy.f = (Gravite()\y - *Objet\y) ; Distance en y
        D2.f = Dx * Dx + Dy * Dy ; Distance au carré
        If D2 <> 0
          D.f = Sqr(D2)
          Dx = Dx / D ; Vecteur direction
          Dy = Dy / D
         
          ; Calcul de la gravité et donc de l'évolution de la vitesse
          ; Gravité = k * Masse / Distance²
          G1.f = *Objet\m / D2
          G2.f = Gravite()\m / D2
          *Objet\Vx + G2 * Dx
          *Objet\Vy + G2 * Dy
          Gravite()\Vx - G1 * Dx
          Gravite()\Vy - G1 * Dy
        EndIf
      EndIf
    Next
    ChangeCurrentElement(Gravite(), *Objet)
  Next
 
  ; On calcul les nouvelles positions
  ForEach Gravite()
    If Gravite()\Etat = 0
      Gravite()\x + Gravite()\Vx ; On déplace l'objet
      Gravite()\y + Gravite()\Vy
    EndIf
  Next
 
  ResetList(Gravite())
EndProcedure



#Ecran_Largeur = 1024
#Ecran_Hauteur = 768

; On ouvre l'openscreen
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  MessageRequester("Erreur", "Impossible d'initialiser la souris ,le clavier ou l'écran. Vérifiez la présence de DirectX 7 ou supérieur.", 0)
  End
EndIf

If OpenScreen(#Ecran_Largeur, #Ecran_Hauteur, 32, "Gravité") = 0
  MessageRequester("Erreur", "Impossible d'ouvrir l'écran.", 0)
  End
EndIf

CreateSprite(0, 5, 5)
StartDrawing(SpriteOutput(0))
  Circle(2, 2, 2, $FFFFFF)
StopDrawing()

CreateSprite(1, #Ecran_Largeur, #Ecran_Hauteur)


; Pour ajouter des planète, c'est ici :

; AddGravityObject(ID, x.f, y.f, Vitesse_X.f, Vitesse_Y.f, Masse.f, Etat.b)
; ID : Identifiant de la planete
; x.f, y.f : Position de départ
; Vitesse_X.f, Vitesse_Y.f : Vitesse de départ
; Masse : mAsse de la planète (plus la planète est lourde et plus elle attire les autres
; Etat : Si = 1, la planète est fixe

AddGravityObject(0, 500, 350, 0, 0, 200, 0)
AddGravityObject(1, 200, 350, 0, 1, 10, 0)
AddGravityObject(2, 210, 350, 0, 0, 0.001, 0)
AddGravityObject(3, 800, 350, 0, -1, 10, 0)
AddGravityObject(4, 540, 350, 0, 3, 0.001, 0)

Repeat
  ClearScreen(0)

  ; On lit les évènements clavier et souris
  ExamineMouse()
  ExamineKeyboard()
 
  ; Position de la souris
  x = MouseX()
  y = MouseY()
 
  DisplaySprite(1, 0, 0)
 
  MoveGravityObject()
  While NextGravityObject()
    GetGravityObjectPos(@Objet.POINT)
    DisplaySprite(0, Objet\x - 2, Objet\y - 2)
   
    ; Traits des trajectoires
    StartDrawing(SpriteOutput(1))
      Box(Objet\x, Objet\y, 1, 1, $767676)
    StopDrawing()
   
    ; Deboguage
    StartDrawing(ScreenOutput())

      DrawText(0, 15 * GetGravityObjectID(),Str(Objet\x) + ", " + Str(Objet\y))
    StopDrawing()
   
  Wend
 
  FlipBuffers()
 
  If IsScreenActive() = 0
    End
  EndIf
 
Until KeyboardPushed(#PB_Key_Escape)