Basic Univers
; Author : Ar-S
; Description : feu d'artifice (Graphique)

;/----------------------------------------------------------------------------
;/
;/ Touche HAUT et BAS pour rotation de l'axe X
;/        GAUCHE et DROITE pour rotation de l'axe Y
;/        INSER et SUPPR pour rotation axe Z
;/        PAGE SUIVANTE et PAGE PRECEDENTE pour le Zoom
;/        HOME pour réinitialiser
;/        P pour pause => peut toujours faire des rotation pendant la pose
;/        + et - du pavet numerique pour la vitesse
;/
;/-----------------------------------------------------------------------------

;{- initialisation programe
If InitSprite()= 0 Or InitKeyboard() = 0 Or InitSound() = 0 Or OpenScreen(1024 , 768 , 32 , "Feux d'artifice") = 0
  MessageRequester("Feux d'artifice" , "Erreur DirectX", #MB_ICONINFORMATION | #MB_OK)
  End
EndIf

; InitSprite():InitKeyboard():InitSound()
; OpenWindow(1,10,10,1000,750,#PB_Window_SystemMenu,"Test")
; OpenWindowedScreen( WindowID(),10,10,1024,768,1,10,10)
;}

Structure donnees
  x.f
  y.f
  z.f
  rayon.f
  altitude.f
  red.f
  green.f
  blue.f
  petit.f
  vitesse.f
  compteur.l
EndStructure

nbpetard.l = 10

;{- variables

Global Dim petards.donnees(nbpetard)
Global petards.donnees
Global  scrx.l, scrx2.l, scrxc.l, scry.l, scry2.l, scryc.l
Global wx.l, wy.l, wz.l, Constant.f, zoom.f
Global n.l, cx.f, cy.f, cz.f

scrx = 1024: scrx2 = scrx/2: scrxc = scrx - 3
scry = 768: scry2 = scry/2: scryc = scry - 3
vitesse.f = 1
zoom = 1
pause.b = 1
gravite.f = 0
wx = 0 : wy = 0 : wz = 0
;}
;{- table des cos
Global Dim _sin.f(360)
Global Dim _cos.f(360)
Global Dim _xcos.f(720)
Global Dim _ysin.f(720)
Global Dim _zsin.f(720)
For i = 0 To 360
  _sin(i) = Sin(i*#PI/180)
  _cos(i) = Cos(i*#PI/180)
Next
For i = 0 To 719
  _xcos(i) = Cos(i)
  _ysin(i) = Sin(i) * Sin(Sqr(i))
  _zsin(i) = Sin(i) * Cos(Sqr(i))
Next i
;}

Procedure _plot(x.f, y.f, z.f, rgb.l)
 
  x - scrx2 : y - scry2 : z - scry2
 
  x1.f = x * _cos(wz) - y * _sin(wz) ; Rotation sur l'axe Z
  y1.f = x * _sin(wz) + y * _cos(wz)
  y2.f = y1 * _cos(wx) - z * _sin(wx) ; Rotation sur l'axe X
  z1.f = y1 * _sin(wx) + z * _cos(wx)
  ; z2.f = z1 * _cos(wy) - x1 * _sin(wy) ; Rotation sur l'axe Y
  x2.f = z1 * _sin(wy) + x1 * _cos(wy)
  xx.f = scrx2 + x2*zoom
  yy.f = scry2 + y2*zoom
 
  If xx > 2 And xx < scrxc And yy > 2 And yy < scryc
    Plot(xx, yy, rgb)
    If petards(n)\petit > 50 And zoom >0.4
      Plot(xx + 1, yy, rgb - $323232)
      Plot(xx - 1, yy, rgb - $323232)
      Plot(xx, yy + 1, rgb - $323232)
      Plot(xx, yy - 1, rgb - $323232)
    EndIf
    If petards(n)\petit > 100 And zoom >0.7
      Plot(xx + 1, yy - 1, rgb - $646464)
      Plot(xx - 1, yy - 1, rgb - $646464)
      Plot(xx + 1, yy + 1, rgb - $646464)
      Plot(xx - 1, yy + 1, rgb - $646464)
    EndIf
    If zoom>4 And petards(n)\petit > 100
      Plot(xx - 1, yy + 2, rgb - $646464)
      Plot(xx, yy + 2, rgb - $646464)
      Plot(xx + 1, yy + 2, rgb - $646464)
      Plot(xx - 1, yy - 2, rgb - $646464)
      Plot(xx, yy - 2, rgb - $646464)
      Plot(xx + 1, yy - 2, rgb - $646464)
      Plot(xx + 2, yy + 1, rgb - $646464)
      Plot(xx + 2, yy, rgb - $646464)
      Plot(xx + 2, yy - 1, rgb - $646464)
      Plot(xx - 2, yy + 1, rgb - $646464)
      Plot(xx - 2, yy, rgb - $646464)
      Plot(xx - 2, yy - 1, rgb - $646464)
    EndIf
    If zoom>6 And petards(n)\petit > 100
      Plot(xx - 2, yy + 2, rgb - $646464)
      Plot(xx + 2, yy + 2, rgb - $646464)
      Plot(xx + 2, yy - 2, rgb - $646464)
      Plot(xx - 2, yy - 2, rgb - $646464)
      Plot(xx - 3, yy, rgb - $646464)
      Plot(xx, yy + 3, rgb - $646464)
      Plot(xx + 3, yy, rgb - $646464)
      Plot(xx, yy - 3, rgb - $646464)
    EndIf
  EndIf
 
EndProcedure
Procedure _LineXY(x.f, y.f, z.f, xx.f, yy.f, zz.f, rgb.l)
 
  x - scrx2: y - scry2: z - scry2
  xx - scrx2: yy - scry2: zz - scry2
 
  x1.f = x * _cos(wz) - y * _sin(wz) ; Rotation sur l'axe Z
  y1.f = x * _sin(wz) + y * _cos(wz)
  y2.f = y1 * _cos(wx) - z * _sin(wx) ; Rotation sur l'axe X
  z1.f = y1 * _sin(wx) + z * _cos(wx)
  ; z2.f = z1 * _cos(wy) - x1 * _sin(wy) ; Rotation sur l'axe Y
  x2.f = z1 * _sin(wy) + x1 * _cos(wy)
  xl1.f = scrx2 + x2*zoom
  yl1.f = scry2 + y2*zoom
 
  x1.f = xx * _cos(wz) - yy * _sin(wz) ; Rotation sur l'axe Z
  y1.f = xx * _sin(wz) + yy * _cos(wz)
  y2.f = y1 * _cos(wx) - zz * _sin(wx) ; Rotation sur l'axe X
  z1.f = y1 * _sin(wx) + zz * _cos(wx)
; z2.f = z1 * _cos(wy) - x1 * _sin(wy) ; Rotation sur l'axe Y
  x2.f = z1 * _sin(wy) + x1 * _cos(wy)
  xl2.f = scrx2 + x2*zoom
  yl2.f = scry2 + y2*zoom
 
  Line(xl1, yl1, xl2 - xl1, yl2 - yl1, rgb)
 
EndProcedure
Procedure _DrawText(x.f, y.f, z.f, texte.s, r.l, g.l, b.l)
 
  x - scrx2: y - scry2: z - scry2
 
  x1.f = x * _cos(wz) - y * _sin(wz) ; Rotation sur l'axe Z
  y1.f = x * _sin(wz) + y * _cos(wz)
  y2.f = y1 * _cos(wx) - z * _sin(wx) ; Rotation sur l'axe X
  z1.f = y1 * _sin(wx) + z * _cos(wx)
  ; z2.f = z1 * _cos(wy) - x1 * _sin(wy) ; Rotation sur l'axe Y
  x2.f = z1 * _sin(wy) + x1 * _cos(wy)
  xl1.f = scrx2 + x2*zoom
  yl1.f = scry2 + y2*zoom
 
  If zoom > 0.045
    ; LoadFont (0, "verdana", 12*zoom)
    ; DrawingFont(FontID(0))
    DrawText(xl1, yl1, texte)
  EndIf
 
EndProcedure

;{- boucle principale
Repeat
 
  ClearScreen(0)
  If StartDrawing(ScreenOutput())
    FrontColor(RGB(255, 0, 0))
    DrawingMode(1|4)
   
    ;{- repere 3d
    ; axe de rotation
    c = 3 : ry = 0 : Pas = scry/6
    Repeat
      c - 1
      ry + Pas
    Until ry>scry
   
    c =- 4 : rx = 0 : Pas = scrx/8
    Repeat
      c + 1
      rx + Pas
    Until rx>scrx
   
   
    For n = 0 To nbpetard - 1
     
      ;{- initiliastion de la structure
      If petards(n)\ red < 50 Or petards(n)\green  < 50 Or petards(n)\blue < 50
        petards(n)\x = scrx/4 + Random(scrx2)
        petards(n)\y = scryc
        petards(n)\z = scry2 - scry/8 + Random(scry/4)
        petards(n)\rayon = 20
        petards(n)\altitude = scry/8 + Random(scry/4)
        petards(n)\red = 200 + Random(55)
        petards(n)\green = 200 + Random(55)
        petards(n)\blue = 200 + Random(55)
        petards(n)\vitesse = 4
        If petards(n)\red < petards(n)\green
          petards(n)\petit = petards(n)\red
        Else
          petards(n)\petit = petards(n)\green
        EndIf
        If petards(n)\petit > petards(n)\blue
          petards(n)\petit = petards(n)\blue
        EndIf
        petards(n)\compteur = 0
      EndIf
      ;}
      ;{- explosion petard
      If petards(n)\altitude = 65535
        rgb = RGB(petards(n)\red, petards(n)\green, petards(n)\blue)
        pr = 720 - petards(n)\rayon
        nbpoint = pr*zoom
        If nbpoint> 720: nbpoint = 720: EndIf
        For Angle = 0 To nbpoint
          x.f = petards(n)\x + petards(n)\rayon * _xcos(Angle)
          y.f = petards(n)\y + petards(n)\rayon * _ysin(Angle)
          z.f = petards(n)\z + petards(n)\rayon * _zsin(Angle)
          If x > 1 And x < scrx And y>1 And yAnd z>1 And z_plot(x, y, z, rgb)
          EndIf
        Next Angle
        If pause
          petards(n)\red - 0.5
          petards(n)\green - 0.5
          petards(n)\blue - 0.5
          petards(n)\petit - 0.5
          petards(n)\rayon + petards(n)\vitesse/2
          petards(n)\compteur + 1
          ang =(petards(n)\compteur/3 + 250)
          If ang>360: ang = 360: EndIf
          gravite =_cos(ang)*zoom
          petards(n)\vitesse - gravite/45
          petards(n)\y + gravite*2
        EndIf
      EndIf
      ;}
      ;{- decolage fusee
      If petards(n)\y > petards(n)\altitude
        vibration =_xcos(Random(10))
        x1 = petards(n)\x
        y1 = petards(n)\y
        z1 = petards(n)\z
        ; Plot(x1,y1,$FFFF)
        _plot(x1, y1, z1, $FFFF)
        If pause
          a = petards(n)\y/8
          gravite =_cos(a)*16
          petards(n)\x + vibration
          petards(n)\y - petards(n)\vitesse*4 + gravite
          petards(n)\z + vibration
        EndIf
      Else
        petards(n)\altitude = 65535
      EndIf
      ;}
     
    Next
   
    StopDrawing()
  EndIf
  FlipBuffers()
  ; FlipBuffers(0)
  ExamineKeyboard()
 
  ;{- gestion des touches
  If KeyboardPushed(#PB_Key_PageUp)
    zoom * 1.02
    If zoom>10: zoom = 10: EndIf
  EndIf
  If KeyboardPushed(#PB_Key_PageDown)
    zoom * 0.98
    If zoom<0.001: zoom = 0.001: EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Up)
    wx - vitesse
    If wx < 0 : wx = 359 - vitesse : EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Down)
    wx + vitesse
    If wx > 359 : wx = vitesse : EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Right)
    wy - vitesse
    If wy < 0 : wy = 359 - vitesse : EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Left)
    wy + vitesse
    If wy > 359 : wy = vitesse : EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Delete)
    wz - vitesse
    If wz < 0 : wz = 359 - vitesse : EndIf
  EndIf
  If KeyboardPushed(#PB_Key_Insert)
    wz + vitesse
    If wz > 359 : wz = vitesse : EndIf
  EndIf
  If KeyboardReleased(#PB_Key_Home)
    wx = 0 : wy = 0 :  wz = 0 : zoom = 1
  EndIf
  If KeyboardReleased(#PB_Key_Add)
    vitesse + 1
    If vitesse = 6 : vitesse = 5 : EndIf
  EndIf
  If KeyboardReleased(#PB_Key_Subtract)
    vitesse - 1
    If vitesse = 0 : vitesse = 1 : EndIf
  EndIf
  If KeyboardReleased(#PB_Key_P)
    If pause
      pause = 0
    Else
      pause = 1
    EndIf
  EndIf
  ;}
   
  ; Event.l = WindowEvent() ; pour WindowedScreen
Until KeyboardPushed(#PB_Key_Escape) ; Or Event = #PB_Event_CloseWindow ; pour WindowedScreen
End
;}