Fractales

Programmation d'applications complexes
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Fractales

Message par bombseb »

Salut,

J'avais envie d'explorer les mondes fractalesques alors j'ai adapté en pure basic un algo en C. et j'en ai profité pour rajouter quelques fonctions supplémentaire :
- Aperçu de la fractale (1 pixel sur 2)
- déplacement dans la fractale avec les touches fléchées
- zoom in (q) et zoom out (w)

il me semble avoir vu quelques bugs dans le deplacement...

Code : Tout sélectionner

If InitSprite () = 0 
   MessageRequester ("Erreur", "Impossible d'initialiser directx", #PB_MessageRequester_Ok) 
   End 
EndIf 

; ; ---------- Mode fenetré ---------- 
; #WindowWidth    = 400 
; #WindowHeight   = 300 
; hWnd = OpenWindow(0, 0, 0, #WindowWidth, #WindowHeight, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Test") 
; If hwnd = 0 
;   MessageRequester ("Erreur", "Impossible d'ouvrir l'écran", #PB_MessageRequester_Ok) 
;   End 
; EndIf 
; 
; If OpenWindowedScreen(hWnd, 0, 0, #WindowWidth, #WindowHeight, 1, 0, 0) = 0 
;   MessageRequester ("Erreur", "Impossible d'ouvrir l'écran", #PB_MessageRequester_Ok) 
;   End 
; EndIf 
; ; ---------------------------------- 

; *** OU ***

;------------------------ Plein écran  ------------------------- 
#WindowWidth    = 640 
#WindowHeight   = 480 
If OpenScreen(640, 480, 32, "Starfield") = 0 
   MessageRequester ("Erreur", "Impossible d'ouvrir l'écran", #PB_MessageRequester_Ok) 
   End 
EndIf 

; ;Récupère l'adresse du buffer invisible 
; StartDrawing(ScreenOutput()) 
; *AdresseEcran=DrawingBuffer() 
; Pitch=DrawingBufferPitch()/SizeOf(long) 
; StopDrawing() 
; 
; ;Affiche le buffer invisible 
; FlipBuffers() 
;---------------------------------------------------------------- 


InitKeyboard () 
KeyboardMode(1)

ClearScreen (0,0,0) 
FlipBuffers () 
ClearScreen (0,0,0) 


; ------------------------ FRACTALE -----------------------
nx = 640 ; hauteur et
ny = 480 ; largeur en pixels

cx.f = 0.5 ; coordonnées du
cy.f = 0.5  ; plan complexe

largeur.f = 4.0 ; largeur complexe    pas de zoom = 4
Ratio = 1 ; pour la prévisu

Dim color(3)  ; tableau de couleurs
iter = 500     ; nombre de fois que la suite doit converger

Repeat

  xmin.f = cx.f - largeur / 2.0           ; calcul des bornes 
  ymax.f = cy + largeur / 2.0 * ny / nx ;     du plan 
  pas.f = largeur / nx ; calculs du pas d'incrementation
  
    ClearScreen(0,0,0)
  If StartDrawing (ScreenOutput ())
    For j = 0 To ny-1
      b.f = ymax - j * pas
      
      For i = 0 To nx-1
        a.f = i * pas + xmin
        x.f = 0 
        y.f = 0 
        n   = 0
        
        While ((x*x + y*y) < 4) And (n < iter)
          x1.f = x*x - y*y + a
          y.f  = 2*x*y + b
          x.f  = x1
          n    = n + 1
        Wend
        
        color(0) = 255 - 255 / (Sqr (Sqr (n)) + 1)
        color(1) = Pow (n, 0.85)
        color(3) = 255 / (Sqr (n) + 1)
        
        If n > (iter - 1)
          color (0) = 0 
          color (1) = 0 
          color (2) = 0
        EndIf
    ;     *Ptr.long = *AdresseEcran + (i+j*Pitch) * SizeOf(Long) 
    ;     *Ptr\l = RGB (color(3), color(2), color(1))
  
        Plot (i*Ratio,j*Ratio, RGB (color(1), color(2), color(3)))
      Next
    Next

       StopDrawing ()
  EndIf

  FlipBuffers ()

  
  Repeat
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Escape)
      Goto fin
      ;Break 2
    EndIf

    nx = 320 ; hauteur et
    ny = 240 ; largeur en pixels
    Ratio = 2
    iter = 100
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Up)
      cy.f = cy.f / 0.99
      Break
    Else
      ExamineKeyboard()
      If KeyboardPushed(#PB_Key_Down)
        cy.f = cy.f * 0.99
        Break
      Else
        ExamineKeyboard()
        If KeyboardPushed(#PB_Key_Left)
          cx.f = cx.f * 0.99
          Break
        Else
          ExamineKeyboard()
          If KeyboardPushed(#PB_Key_Right)
            cx.f = cx.f / 0.99
            Break
          Else
            ExamineKeyboard()
            If KeyboardPushed(#PB_Key_W)
              largeur.f = largeur.f / 0.99
              Break
            Else
              ExamineKeyboard()
              If KeyboardPushed(#PB_Key_Q)
                largeur.f = largeur.f * 0.99
                Break
              Else
                nx = 640 ; hauteur et
                ny = 480 ; largeur en pixels
                Ratio = 1
                iter = 500
                Break
              EndIf                
            EndIf                
          EndIf                
        EndIf                
      EndIf                
    EndIf                
    
  ForEver
;  ClearScreen (0,0,0)
  
ForEver 

; ----- FIN DU PROG -----
Fin:
End
; -----------------------
(J'avoue avoir codé la gestion du clavier comme un barbare, d'ailleur si il y a mieux j'aimerais bien savoir)
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

déjà un examinekeyboard suffit pour la boucle, je teste (après avoir check le code) et je te corrige la partie clavier

Dri ;)
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Message par bombseb »

ah cool !

en fait le bug c'est :
on ne peut pas se deplacer en dessous de zéro (pour cx et cy)
normal vu que je fait cx*0.99 et cy*0.99 donc ca ne peut pas passer en dessous de zero

pour ca il faudrait faire une soustraction sur cx ou cy en fonction de la valeur de la variable largeur
parceque si on ne tient pas compte de la variable largeur (le zoom koi) le deplacement se fait par incréments trop grand lorsque on est en fort grossissement (tu me suis ?)

sinon pour le examinekeyboard il m'a semblé avoir essayé d'en mettre un seul dans la boucle mais ca n'a pas marché... enfin j'ai pas trop cherché non plus

par contre je me demandait : on ne peut pas faire un select en fonction de la touche pressée sur le clavier ? parceque la j'ai été obligé de faire plein de IF imbriqué c'est pas tres lisible...
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

ca rame à mort
chez moi ca rame moins comme ca mais j'ai pas regardé le code en détail

Code : Tout sélectionner

If InitSprite () = 0
   MessageRequester ("Erreur", "Impossible d'initialiser directx", #PB_MessageRequester_Ok)
   End
EndIf

; ; ---------- Mode fenetré ----------
; #WindowWidth    = 400
; #WindowHeight   = 300
; hWnd = OpenWindow(0, 0, 0, #WindowWidth, #WindowHeight, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Mandelbrot")
; If hwnd = 0
;   MessageRequester ("Erreur", "Impossible d'ouvrir l'écran", #PB_MessageRequester_Ok)
;   End
; EndIf
;
; If OpenWindowedScreen(hWnd, 0, 0, #WindowWidth, #WindowHeight, 1, 0, 0) = 0
;   MessageRequester ("Erreur", "Impossible d'ouvrir l'écran", #PB_MessageRequester_Ok)
;   End
; EndIf
; ; ----------------------------------

; *** OU ***

;------------------------ Plein écran  -------------------------
#WindowWidth    = 640
#WindowHeight   = 480
If OpenScreen(640, 480, 32, "Mandelbrot") = 0
   MessageRequester ("Erreur", "Impossible d'ouvrir l'écran", #PB_MessageRequester_Ok)
   End
EndIf

;Récupère l'adresse du buffer invisible
If StartDrawing(ScreenOutput())
  *AdresseEcran=DrawingBuffer()
  Pitch=DrawingBufferPitch() / SizeOf(long)
  StopDrawing()
EndIf

;Affiche le buffer invisible
FlipBuffers()
;----------------------------------------------------------------


InitKeyboard()
KeyboardMode(1)

ClearScreen(0,0,0)
FlipBuffers()
ClearScreen(0,0,0)


; ------------------------ FRACTALE -----------------------
nx = 640 ; hauteur et
ny = 480 ; largeur en pixels

cx.f = 0.5 ; coordonnées du
cy.f = 0.5 ; plan complexe

largeur.f = 4.0 ; largeur complexe    pas de zoom = 4
Ratio = 1 ; pour la prévisu

Dim color(3)  ; tableau de couleurs
iter = 500     ; nombre de fois que la suite doit converger

Repeat
  ClearScreen(0,0,0)
  ExamineKeyboard()
  
  If dessine = 1
    xmin.f = cx.f - largeur / 2.0           ; calcul des bornes
    ymax.f = cy + largeur / 2.0 * ny / nx ;     du plan
    pas.f = largeur / nx ; calculs du pas d'incrementation
      
    If StartDrawing( ScreenOutput () )
      For j = 0 To ny-1
        b.f = ymax - j * pas
       
        For i = 0 To nx-1
          a.f = i * pas + xmin
          x.f = 0
          y.f = 0
          n   = 0
         
          While ((x*x + y*y) < 4) And (n < iter)
            x1.f = x*x - y*y + a
            y.f  = 2*x*y + b
            x.f  = x1
            n    = n + 1
          Wend
         
          color(0) = 255 - 255 / (Sqr (Sqr (n)) + 1)
          color(1) = Pow (n, 0.85)
          color(3) = 255 / (Sqr (n) + 1)
         
          If n > (iter - 1)
            color (0) = 0
            color (1) = 0
            color (2) = 0
          EndIf
          *Ptr.long = *AdresseEcran + (i+j*Pitch) * SizeOf(Long)
          *Ptr\l = RGB (color(3), color(2), color(1))
   
          ;Plot (i*Ratio,j*Ratio, RGB (color(1), color(2), color(3)))
        Next
      Next
      
      StopDrawing ()
    EndIf
    dessine = 0
  EndIf
  
  nx = 320 ; hauteur et
  ny = 240 ; largeur en pixels
  Ratio = 2
  iter = 100
  
  dessine = 1
  
  If     KeyboardPushed(#PB_Key_Up)
    cy.f = cy.f / 0.99
  ElseIf KeyboardPushed(#PB_Key_Down)
    cy.f = cy.f * 0.99
  ElseIf KeyboardPushed(#PB_Key_Left)
    cx.f = cx.f * 0.99
  ElseIf KeyboardPushed(#PB_Key_Right)
    cx.f = cx.f / 0.99
  ElseIf KeyboardPushed(#PB_Key_W)
    largeur.f = largeur.f / 0.99
  ElseIf KeyboardPushed(#PB_Key_Q)
    largeur.f = largeur.f * 0.99
  Else
    nx = 640 ; hauteur et
    ny = 480 ; largeur en pixels
    Ratio = 1
    iter = 500
    dessine = 0
  EndIf
  FlipBuffers ()
Until KeyboardPushed(#PB_Key_Escape)
Dri ;)
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Message par bombseb »

merci pour tes modifs


je suis en train d'essayer de calculer qu'un pixel sur 2 et d'interpoler le reste... (pour faire un zoom en temps réel dans ma démo)

mais c'est loin d'être gagné
:cry:
Répondre