Simaluteur planétaire

Programmation avancée de jeux en PureBasic
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Simaluteur planétaire

Message 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)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Dräc
Messages : 526
Inscription : dim. 29/août/2004 0:45

Message par Dräc »

Amusant :)
garzul
Messages : 683
Inscription : mer. 26/mai/2004 0:33

Message par garzul »

Vraiment cool :)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Bon et quand est ce que le système solaire partira en cou...lle lui ??? :lol: en tout cas tres sympa
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

ça fait de Jolis dessins :D
Aranoth
Messages : 293
Inscription : sam. 24/janv./2004 12:00
Localisation : Toulouse (31)
Contact :

Message 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
Débutant en programmation, notament en C++ ?
Vous souhaitez apprendre ?
jnspunk
Messages : 6
Inscription : ven. 15/oct./2004 22:15

Message 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)
Avatar de l’utilisateur
Ouaf-Ouaf
Messages : 212
Inscription : dim. 11/juil./2004 9:07

^^

Message 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.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message 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.
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

@soldat :lol: fait gaffe tu commence a faire des programme (DD)
(Dobro Delirium) , la folie est contagieuse !! :lol:
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message 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)
Répondre