Page 1 sur 2

Une chenille sur votre écran

Publié : ven. 06/août/2004 13:59
par Le Soldat Inconnu
suite au post suivant
http://purebasic.hmt-forum.com/viewtopic.php?t=1209

j'ai réalisé une chenille qui se ballade sous windows.

j'ai plusieur solution à proposer.

la première consite à faire une copie d'écran de la zone de l'écran sur laquel la chenille se déplace
en clair, quand je déplace la chenille d'1 pixel vers la droite, je fais une copie d'écran de la bande de 1 px situé à droite de la fenêtre ou je dessine la chenille.
je décale l'image de fond de la fenêtre d'un pixel vers la gauche et je colle la copie d'écran à droite de la fenêtre
ensuite, je déplcae la fenêtre d'un pixel vers la droite

on obtient donc dans le fond de la fenêtre une image correspond à ce qui est sous la chenille (à condition que ce qui est sous la chenille nne change pas d'apparence)

voici le code correspondant : (il n'est pas très commenté alos si vous avez besion d'explication, n'hésitez pas à demandé)

Code : Tout sélectionner

Structure Position
  x.l
  y.l
  a.l
EndStructure

#Pi.f = 3.14159265

#Longueur = 20 ; Longueur de la chenille (Obligatoirement un nombre paire)

#Rayon = 2
#NbImage = 34 ; Nombre d'image de l'animation (Obligatoirement un nombre paire)
#Amplitude.f = #Pi / 180 / #NbImage * 75 ; Amplitude de la chenille, seul le dernier nombre peut-être changé

#Vitesse = 30 ; Vitesse de l'animation

#Tampon = 100 ; Zone en dehors de l'écran dans laquelle la chenille ne fait pas demi-tour

#TailleX = #Longueur * #Rayon + #Rayon ; Largeur de la fenêtre
#TailleY = 16 ; Hauteur de la fenêtre, à ajuster manuellement

#Fond = 0 ; Image de fond de la fenêtre
#Image_Finale = 1 ; Image finale de la chenille
#Fond_Temp = 2

Dim Chenille.Position(#NbImage, #Longueur)
Dim Avance.l(#NbImage)

Global Etat, PosX, PosY, Pas, Sens

Procedure Calcul() ; Calcul des positions de la chenille
  Protected Px.f, Py.f, Angle.f, Av.f
  
  ; On initialise l'avance à la longeur de départ de la chenille
  Av = #Longueur * #Rayon
  
  Debug "_______________"
  Debug "La chenille se plie"
  
  ; Phase de pliage de la chenille
  For Etat = 0 To #NbImage / 2 - 1
    Debug "=============="
    Px = 0
    Py = 0
    Angle = 0
    
    For n = 0 To #Longueur / 2 - 1
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 360 / 2 / #Pi / 15) * 15
      Angle = Angle + Etat * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
      Debug StrF(Px, 1) + "  |  " + StrF(Py, 1) + "  <  " + StrF(Angle, 2) + "  >  " + Str(Chenille(Etat, n)\a)
    Next
    
    For n = #Longueur / 2 To #Longueur - 1
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 360 / 2 / #Pi / 15) * 15
      Angle = Angle - Etat * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
      Debug StrF(Px, 1) + "  |  " + StrF(Py, 1) + "   <  " + StrF(Angle, 2) + "  >  " + Str(Chenille(Etat, n)\a)
    Next
    
    Avance(Etat) = Int(Av - Px)
    Av = Av - Avance(Etat)
    Debug "Avance = " + Str(Avance(Etat))
    
  Next
  
  Debug "_______________"
  Debug "La chenille se déplie"
  
  ; Phase de dépliage de la chenille
  For Etat = #NbImage / 2 To #NbImage
    Debug "=============="
    Px = 0
    Py = 0
    Angle = 0
    
    For n = 0 To #Longueur / 2 - 1
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 360 / 2 / #Pi / 15) * 15
      Angle = Angle + (#NbImage - Etat) * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
      Debug StrF(Px, 1) + "  |  " + StrF(Py, 1) + "  <  " + StrF(Angle, 2) + "  >  " + Str(Chenille(Etat, n)\a)
    Next
    
    For n = #Longueur / 2 To #Longueur - 1
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 360 / 2 / #Pi / 15) * 15
      Angle = Angle - (#NbImage - Etat) * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
      Debug StrF(Px, 1) + "  |  " + StrF(Py, 1) + "   <  " + StrF(Angle, 2) + "  >  " + Str(Chenille(Etat, n)\a)
    Next
    
    Avance(Etat) = 0
    
  Next
  
EndProcedure

Procedure Image_Plafond() ; Création de l'image pour la chenille marchant en haut de l'écran
  UseImage(#Image_Finale)
  StartDrawing(ImageOutput())
    
    DrawImage(UseImage(#Fond), 0, 0)
    ; Box(0, 0, #TailleX, #TailleY, 0)
    
    ; Dessin de la chenille
    For n = 1 To #Longueur - 1
      Circle(#Rayon + Chenille(Etat, n)\x, #Rayon + Chenille(Etat, n)\y, #Rayon, $4AD274)
    Next
    
  StopDrawing()
EndProcedure

Procedure Image_Plancher() ; Création de l'image pour la chenille marchant en bas de l'écran
  UseImage(#Image_Finale)
  StartDrawing(ImageOutput())
    
    DrawImage(UseImage(#Fond), 0, 0)
    
    ; Dessin de la chenille
    For n = 1 To #Longueur - 1
      Circle(#Rayon + Chenille(Etat, n)\x, #TailleY - #Rayon - Chenille(Etat, n)\y, #Rayon, $4AD274)
    Next
    
  StopDrawing()
EndProcedure

Procedure Deplace_Ecran(x, y)
    CopyImage(#Fond, #Fond_Temp)
    DC = GetDC_(0)
    UseImage(#Fond)
    Dessin = StartDrawing(ImageOutput())
      Box(0, 0, #TailleX, #TailleY, 0)
      BitBlt_(Dessin, 0, 0, #TailleX, #TailleY, DC, WindowX() + x, WindowY() + y, #SRCPAINT)
      DrawImage(UseImage(#Fond_Temp), -x, -y)
    StopDrawing()
    ReleaseDC_(0, DC)
EndProcedure

Procedure Affiche()
  Protected x, y
  Etat + Pas
  If Etat > #NbImage
    Etat = 0
  ElseIf Etat < 0
    Etat = #NbImage
  EndIf
  
  x = WindowX()
  y = WindowY()
  If x > GetSystemMetrics_(#SM_CXSCREEN) + #Tampon Or x < - #TailleX - #Tampon
    Pas = -Pas
    y = 0
    Sens = 0
  EndIf
  
  If x >= -#TailleX And x <= GetSystemMetrics_(#SM_CXSCREEN)
    If Pas <> 0
      x + Avance(Etat) * Pas ; On fait avancer la chenille
      
      If y = 0
        ; Pour faire tomber la chenille du haut de l'écran
        If Etat = 0 And Random(20) = 0
          Pas = 0
          Sens = 1 ; On charge les images de la chenille qui marche sur le sol
          y - #TailleY + 2 * #Rayon + 1 ; On déplace la fen en conséquence
        EndIf
      Else
        ; Pour faire tomber la chenille d'une fenêtre
        WinID = WindowFromPoint_(x + 2 * #Rayon, y + #TailleY) ; On regarde l'Id de la fenêtre sous la chenille
        If GetParent_(WinID) <> 0 ; On regarde si il s'agit d'une fenêtre ou d'un gadget
          Pas = 0 ; Si on n'est plus sur une fenêtre, on fait tomber la chenille
        EndIf
        WinID = WindowFromPoint_(x + #TailleY - 2 * #Rayon, y + #TailleY)
        If GetParent_(WinID) <> 0
          Pas = 0
        EndIf
      EndIf
      
    Else
      y + 3 ; On fait tomber la chenille
      If Etat <> 0
        Etat - 1
      EndIf
      If y >= GetSystemMetrics_(#SM_CYSCREEN) - #TailleY ; On est en bas de l'écran
        Pas = Random(1) * 2 - 1 ; On lance la chenille dans un sens au hazard
        y = GetSystemMetrics_(#SM_CYSCREEN) - #TailleY
      EndIf
      WinID = WindowFromPoint_(x + 2 * #Rayon, y + #TailleY)
      If GetParent_(WinID) = 0 ; si il y a une fenêtre sous la chenille
        GetWindowRect_(WinID, @Pos.RECT)
        If y >= Pos\top - #TailleY And y < Pos\top - #TailleY + 3 ; Si la chenille est au dessus du haut de la fenêtre
          Pas = Random(1) * 2 - 1
          y = Pos\top - #TailleY
        EndIf
      EndIf
      WinID = WindowFromPoint_(x + #TailleX - 2 * #Rayon, y + #TailleY)
      If GetParent_(WinID) = 0
        GetWindowRect_(WinID, @Pos.RECT)
        If y >= Pos\top - #TailleY And y < Pos\top - #TailleY + 3
          Pas = Random(1) * 2 - 1
          y = Pos\top - #TailleY
        EndIf
      EndIf
    EndIf
  Else
    x + Avance(Etat) * Pas ; On fait avancer la chenille
  EndIf
  
  Deplace_Ecran(x - WindowX(), y - WindowY())
  If Sens
    Image_Plancher()
  Else
    Image_Plafond()
  EndIf
   
  ; On affiche la nouvelle image
  StartDrawing(ScreenOutput())
    DrawImage(UseImage(#Image_Finale), 0, 0)
  StopDrawing()
  FlipBuffers()
  
  MoveWindow(x, y) ; On déplace la fenêtre
  
EndProcedure



;- Debut du programme

OpenWindow(0, -#TailleX, 0, #TailleX, #TailleY, #PB_Window_BorderLess | #WS_SYSMENU, "Chenille")
; CreateGadgetList(WindowID())
SetWindowPos_(WindowID(), -1, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_NOMOVE)
InitSprite()
OpenWindowedScreen(WindowID(), 0, 0, #TailleX, #TailleY, 0, 0, 0)

CreateImage(#Fond, #TailleX, #TailleY)
CreateImage(#Image_Finale, #TailleX, #TailleY)

Calcul()
Pas = 1

; On lance le Timer qui va définir la vitesse de l'animation
Etat = 0
Sens = 0
Timer = SetTimer_(WindowID(), 0, #Vitesse, @Affiche())

Repeat
  Event = WaitWindowEvent()
  
  
Until Event = #PB_Event_CloseWindow

; On tue le timer
KillTimer_(WindowID(), Timer)

Publié : ven. 06/août/2004 14:08
par Le Soldat Inconnu
l'autre solution consiste à utiliser SkinWin (Librairie de Danilo) qui permet de faire un masque sur une fenêtre à partir d'une image
cette solution est la mieux au niveaux rendu mais également la plus gourmande en ressource.

ici, le principe est de créer toutes les images composants l'animation de la chenille à l'avance
ensuite, on affiche l'image de l'animation souhaité et on crée le masque avec skinwin

pour faire fonctionner ce code, vous avez besion des librairie suivante :
- SkinWin (de Danilo)
http://www.purearea.net/pb/download/use ... _I_021.zip

- ColorEffect
http://perso.wanadoo.fr/lesoldatinconnu/


Pour quitter le programme, passer la souris au dessus de la chenille

Code : Tout sélectionner

Structure Position
  x.l
  y.l
  a.l
EndStructure

#Pi.f = 3.14159265

#Longueur = 20 ; Longueur de la chenille (Obligatoirement un nombre paire)

#Rayon = 2
#NbImage = 34 ; Nombre d'image de l'animation (Obligatoirement un nombre paire)
#Amplitude.f = #Pi / 180 / #NbImage * 75 ; Amplitude de la chenille, seul le dernier nombre peut-être changé

#Vitesse = 30 ; Vitesse de l'animation

#Tampon = 100 ; Zone en dehors de l'écran dans laquelle la chenille ne fait pas demi-tour

#TailleX = #Longueur * #Rayon + #Rayon ; Largeur de la fenêtre
#TailleY = 21 ; Hauteur de la fenêtre, à ajuster manuellement

Dim Chenille.Position(#NbImage, #Longueur)
Dim Avance.l(#NbImage)
Dim Couleur.l(48, 2 * #Rayon + 1, 2 * #Rayon + 1)

Global Etat, PosX, PosY, Pas

Procedure Calcul() ; Calcul des positions de la chenille
  Protected Px.f, Py.f, Angle.f, Av.f
  
  ; On initialise l'avance à la longeur de départ de la chenille
  Av = #Longueur * #Rayon
  
  ; Phase de pliage de la chenille
  For Etat = 0 To #NbImage / 2 - 1 ; Pour chaque image de l'animation de la chenille
    Px = 0
    Py = 0
    Angle = 0
    
    ; la chenille est dessinée à l'aide de rond, on cherche donc à calculé le centre de ces ronds
    For n = 0 To #Longueur / 2 - 1 ; on cacul les centres de chaque rond qui va composer la chenille pour la moitié de celle-ci
      Chenille(Etat, n)\x = Px ; on enregistre la position du centre en X
      Chenille(Etat, n)\y = Py ; on enregistre la position du centre en Y
      Chenille(Etat, n)\a = Int(Angle * 180 / #Pi / 15) ; On enregistre l'angle de la chenille, ceci va servir à la coloristion de celle-ci
      
      ; On fait varier un angle en fonction de l'image de l'animation (variable Etat)
      ; Cette angle varie de manière à donner une forme arrondi à la chenille 
      ; de l'Etat 0 qui donne une droite (l'angle est toujours égal à 0)
      ; à l'Etat maximum qui donne la courbure maximum à la chenille
      Angle = Angle + Etat * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      
      ; On calcul la position du rond suivant en se décalant du rond prédent d'un segment de longueur #Rayon et avec un angle "Angle"
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
    Next
    
    For n = #Longueur / 2 To #Longueur - 1 ; On fait de même pour la seconde moitié de la chenille, seul l'angle varie dans le sens inverse
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 180 / #Pi / 15)
      Angle = Angle - Etat * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
    Next
    
    Avance(Etat) = Int(Av - Px)
    Av = Av - Avance(Etat)
    
  Next
  
  ; Phase de dépliage de la chenille
  ; Cette phase est identique à la précédente à l'exeption que l'on par de l'Etat maximum (chenille plié au max) pour aller vers l'Etat minimum (chenille droite)
  For Etat = #NbImage / 2 To #NbImage
    Px = 0
    Py = 0
    Angle = 0
    
    For n = 0 To #Longueur / 2 - 1
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 180 / #Pi / 15)
      Angle = Angle + (#NbImage - Etat) * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
    Next
    
    For n = #Longueur / 2 To #Longueur - 1
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 180 / #Pi / 15)
      Angle = Angle - (#NbImage - Etat) * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
    Next
    
    Avance(Etat) = 0
    
  Next
  
EndProcedure

Procedure Rond_Couleur()
  ; On génère des carré de couleur dégradé suivant plusieur angle pour colorer la chenille
  For Angle = -180 To 180 Step 15 ; On fait varier l'angle de -180° à 180) avec un pas de 15°
    
    ; Pour chaque point de la matrice Couleur()
    ; Couleur(Angle, x, y) = couleur du point x, y de l'image ficitive (enregistré sous forme de matrice) avec un dégradé d'angle "Angle"
    For n = -#Rayon To #Rayon
      For nn = -#Rayon To #Rayon
        Angle_Rad.f = Angle * #Pi / 180 ; On calcul l'angle en radian
        ; On fait une rotation des coordonnée du point n, nn afin de trouver la distance y suivant l'axe Y du repère incliné de l'Angle
        ; Cette distance va servir à savoir si il faut foncer ou éclaicir la couleuyr du point par rapport à la couleur du centre de l'image n=0, nn=0
        y = -n * Sin(Angle_Rad) + nn * Cos(Angle_Rad)
        ; on enregistre la couleur obtenu dans la matrice
        Couleur(Angle / 15 + 12, n + #Rayon, nn + #Rayon) = ColorLuminosity($EC387, 1 + y / 7)
      Next
    Next
    
  Next
EndProcedure

Procedure Image_Plafond() ; Création des images et des masques pour la chenille marchant en haut de l'écran
  Protected Etat
  For Etat = 0 To #NbImage ; pour toutes les images qui composent l'animation de la chenille
    UseImage(Etat)
    StartDrawing(ImageOutput())
      
      ; Dessin de la chenille
      Box(0, 0, #TailleX, #TailleY, $2ABA8B) ; Fond en vert
      ; Cette couleur doit tout de même être la plus proche possible de la chenille pour ne pas avoir de point de différente couleur lors du changement d'image
      For Pos = 1 To #Longueur - 1 ; pour tous les cercle qui compose la chenille
        Circle(#Rayon + Chenille(Etat, Pos)\x, #Rayon + Chenille(Etat, Pos)\y, #Rayon, 0) ; On dessine un cercle en Noir
        ; Ensuite, on colorise ce cercle à l'aide de la matrice Couleur et en fonction de l'angle d'inclinaison du centre du cercle
        For n = -#Rayon To #Rayon
          For nn = -#Rayon To #Rayon
            If Point(#Rayon + Chenille(Etat, Pos)\x + n, #Rayon + Chenille(Etat, Pos)\y + nn) = 0 ; Si le point est noir donc si on est au dessus du cercle que l'on vient de dessiner
              ; On applique la couleur au pixel en fonction de l'angle d'après la matrice Couleur()
              Plot(#Rayon + Chenille(Etat, Pos)\x + n, #Rayon + Chenille(Etat, Pos)\y + nn, Couleur(Chenille(Etat, Pos)\a + 12, n + #Rayon, #Rayon - nn))
            EndIf
          Next
        Next
      Next
      
    StopDrawing()
  Next
EndProcedure

Procedure Image_Plancher() ; Création des images et des masques pour la chenille marchant en haut de l'écran
  Protected Etat
  For Etat = 0 To #NbImage
    UseImage(Etat)
    StartDrawing(ImageOutput())
      
      ; Dessin de la chenille
      Box(0, 0, #TailleX, #TailleY, $2ABA8B) ; Fond en vert différent de celui de la chenille
      ; Cette couleur doit tout de même être la plus proche possible de la chenille pour ne pas avoir de point de différente couleur lors du changement d'image
      For Pos = 1 To #Longueur - 1
        Circle(#Rayon + Chenille(Etat, Pos)\x, #TailleY - #Rayon - Chenille(Etat, Pos)\y, #Rayon, 0)
        For n = -#Rayon To #Rayon
          For nn = -#Rayon To #Rayon
            If Point(#Rayon + Chenille(Etat, Pos)\x + n, #TailleY - #Rayon - Chenille(Etat, Pos)\y + nn) = 0
              Plot(#Rayon + Chenille(Etat, Pos)\x + n, #TailleY - #Rayon - Chenille(Etat, Pos)\y + nn, Couleur(Chenille(Etat, Pos)\a + 12, n + #Rayon, nn + #Rayon))
            EndIf
          Next
        Next
      Next
      
    StopDrawing()
  Next
EndProcedure

Procedure Affiche()
  Protected x, y
  
  x = WindowX() ; on récupère la position x, y de la fenêtre
  y = WindowY()
  
  Etat + Pas
  If Etat > #NbImage
    Etat = 0
    Debug Str(x) + ", " + Str(y)
  ElseIf Etat < 0
    Etat = #NbImage
    Debug Str(x) + ", " + Str(y)
  EndIf
  
  If x > GetSystemMetrics_(#SM_CXSCREEN) + #Tampon Or x < - #TailleX - #Tampon ; Si la chenille est sorti de l'écran + une marge #Tampon
    Pas = -Pas ; On fait faire demi-tour à la chenille
    y = 0 ; on la mets au plafond (en haut de l'écran) si celle -ci est tombée
    Image_Plafond() ; on charge les images correspondant à la chenille qui marche au plafond
  EndIf
  
  If x >= -#TailleX And x <= GetSystemMetrics_(#SM_CXSCREEN) ; Si la chenille est visible à l'écran
    If Pas <> 0 ; Si la chenille avance
      x + Avance(Etat) * Pas ; On fait avancer la chenille
      
       If y = 0 ; Si on est au plafond
        
        ; Pour faire tomber la chenille du haut de l'écran
        If Etat = 0 And Random(20) = 0
          Pas = 0
          Image_Plancher() ; On charge les images de la chenille qui marche sur le sol
          y - #TailleY + 2 * #Rayon + 1 ; On déplace la fen en conséquence
        EndIf
        
      ElseIf y <> GetSystemMetrics_(#SM_CYSCREEN) - #TailleY ; Sinon, on est sur une fenêtre
      
        ; Pour faire tomber la chenille d'une fenêtre
        WinID = WindowFromPoint_(x + 2 * #Rayon, y + #TailleY) ; On regarde l'Id de la fenêtre sous l'extrémité gauche de la chenille
        If GetParent_(WinID) <> 0 ; On regarde si il s'agit d'une fenêtre ou d'un gadget
          Pas = 0 ; Si on n'est plus sur une fenêtre, on fait tomber la chenille
        EndIf
        WinID = WindowFromPoint_(x + #TailleY - 2 * #Rayon, y + #TailleY) ; De même pour l'extrémité droite de la chenille
        If GetParent_(WinID) <> 0
          Pas = 0
        EndIf
        
      EndIf
      
    Else ; Sinon, la chenille tombe
      
      y + 3 ; On fait tomber la chenille
      If Etat <> 0 ; on fait revenir progressivement l'état de la chenille à 0 pour que celle-ci soit droite
        Etat - 1
      EndIf
      
      If y >= GetSystemMetrics_(#SM_CYSCREEN) - #TailleY ; Si on est en bas de l'écran
        Pas = Random(1) * 2 - 1 ; On lance la chenille dans un sens au hazard
        y = GetSystemMetrics_(#SM_CYSCREEN) - #TailleY ; on place la chenille sur le bas de l'écran exactement
      EndIf
      
      WinID = WindowFromPoint_(x + 2 * #Rayon, y + #TailleY)
      If GetParent_(WinID) = 0 ; si il y a une fenêtre sous la chenille
        GetWindowRect_(WinID, @Pos.RECT) ; on récupère la position de la fenêtre
        If y >= Pos\top - #TailleY And y < Pos\top - #TailleY + 3 ; Si la chenille est au dessus du haut de la fenêtre
          Pas = Random(1) * 2 - 1 ; On lance la chenille dans un sens au hazard
          y = Pos\top - #TailleY ; on place la chenille sur le haut de la fenêtre exactement
        EndIf
      EndIf

    EndIf
    
    SkinWin(WindowID(), UseImage(Etat)) ; On affiche la nouvelle image de la chenille et on met en place le masque
    
  Else ; Si la chenille n'est pas visible à l'écran, on ne fait que la déplacé
    x + Avance(Etat) * Pas ; On fait avancer la chenille
  EndIf
  
  MoveWindow(x, y) ; On déplace la fenêtre
  UpdateWindow_(WindowID()) ; on actualise l'affichage
EndProcedure



;- Debut du programme

; Création de la fenêtre
OpenWindow(1, 0, 0, 200, 200, #PB_Window_Invisible, "Chenille")
OpenWindow(0, 0, 0, #TailleX, #TailleY, #PB_Window_BorderLess | #WS_SYSMENU, "Chenille", WindowID(1))
SetWindowPos_(WindowID(0), -1, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_NOMOVE)

For n = 0 To #NbImage ; On crée toute les images de l'animation
  CreateImage(n, #TailleX, #TailleY)
Next

Calcul() ; Cacul de la position de chaque cercle qui compose la chenille pour toutes les positions de celle-ci
Rond_Couleur() ; Calcul des images de remplissage de la chenille
Image_Plafond() ; Dessin des images de la chenille marchant au plafond
Pas = 1 ; Pas d'avance de la chenille

; On lance le Timer qui va définir la vitesse de l'animation
Etat = 0
Timer = SetTimer_(WindowID(0), 0, #Vitesse, 0)

; Création du PopopMenu
CreatePopupMenu(0)
MenuItem(0, "Quitter")
MenuBar()
MenuItem(1, "Information")

Repeat
  Event = WaitWindowEvent()
  
  If Event = #WM_MOUSEMOVE ; Si la souris est au dessus de la chenille
    DisplayPopupMenu(0, WindowID()) ; on affiche le PopupMenu
  
  ElseIf Event = #PB_EventMenu
    Select EventMenuID() ; menu et barre d'outils
      Case 0
        Event = #PB_Event_CloseWindow
      Case 1
        MessageRequester("Information", "Concepteur : Le Soldat Inconnu [Bouguin Régis]" + Chr(10) + "Programmé sur PureBasic" + Chr(10) + Chr(10) + "http://perso.wanadoo.fr/lesoldatinconnu/", 4 * 16)
    EndSelect
  
  ElseIf Event = #WM_TIMER ; On passe à l'image suivante si le Timer se déclanche
    Affiche()
  EndIf
  
Until Event = #PB_Event_CloseWindow

; On tue le timer
KillTimer_(WindowID(0), Timer)

Publié : ven. 06/août/2004 14:43
par Anonyme2
J'ai testé la première, j'aime bien le déplacement de la chenille et aussi la chute (tu pourrais mettre des sons ?)

Publié : ven. 06/août/2004 14:50
par Le Soldat Inconnu
des sons ?? ça parle une chenille ? :mrgreen:
non, tu veux mettre des sons à quel moment ?

Publié : ven. 06/août/2004 14:52
par Anonyme2
par exemple lorsqu'elle tombe ou lorsqu'elle rencontre un coin (bon, c'est juste pour rire)

Publié : ven. 06/août/2004 15:02
par Oliv
très marrant mais ce que l'on attend c'est l'araignée :D :D

Publié : ven. 06/août/2004 15:12
par Le Soldat Inconnu
au fait quand la chenille chute, elle ne s'arrête pas forcément en bas de l'écran mais se pose également sur le haut des fenêtres qu'elle rencontre :D

pour l'araigné, le principe étant le même, y'a plus trop de diffilculé, faut juste s'amuser à dessiner les pattes qui bouge, c'est ça le plus dure.

Publié : sam. 02/oct./2004 15:19
par Le Soldat Inconnu
dernière version plus stable (l'autre, au bout d'un moment, ça plantait l'affichage à cause de skinwin)
pour quitter, il faut cliquer sur la chenille

Image

Code : Tout sélectionner

Structure Position
  x.l
  y.l
  a.l
EndStructure

#Longueur = 20 ; Longueur de la chenille (Obligatoirement un nombre paire)

#Rayon = 3
#NbImage = 34 ; Nombre d'image de l'animation (Obligatoirement un nombre paire)
#Amplitude.f = #Pi / 180 / #NbImage * 75 ; Amplitude de la chenille, seul le dernier nombre peut-être changé

#Vitesse = 25 ; Vitesse de l'animation

#Tampon = 100 ; Zone en dehors de l'écran dans laquelle la chenille ne fait pas demi-tour

#TailleX = #Longueur * #Rayon + #Rayon ; Largeur de la fenêtre
#TailleY = 25 ; Hauteur de la fenêtre, à ajuster manuellement

#Fond = 0 ; Image de fond de la fenêtre
#Fond_Temp = 1

Dim Chenille.Position(#NbImage, #Longueur)
Dim Avance.l(#NbImage)
Dim Couleur.l(48, 2 * #Rayon + 1, 2 * #Rayon + 1)

Global Etat, PosX, PosY, Pas


Procedure Calcul() ; Calcul des positions de la chenille
  Protected Px.f, Py.f, Angle.f, Av.f
  
  ; On initialise l'avance à la longeur de départ de la chenille
  Av = #Longueur * #Rayon
  
  ; Phase de pliage de la chenille
  For Etat = 0 To #NbImage / 2 - 1 ; Pour chaque image de l'animation de la chenille
    Px = 0
    Py = 0
    Angle = 0
    
    ; la chenille est dessinée à l'aide de rond, on cherche donc à calculé le centre de ces ronds
    For n = 0 To #Longueur / 2 - 1 ; on cacul les centres de chaque rond qui va composer la chenille pour la moitié de celle-ci
      Chenille(Etat, n)\x = Px ; on enregistre la position du centre en X
      Chenille(Etat, n)\y = Py ; on enregistre la position du centre en Y
      Chenille(Etat, n)\a = Int(Angle * 180 / #Pi / 15) ; On enregistre l'angle de la chenille, ceci va servir à la coloristion de celle-ci
      
      ; On fait varier un angle en fonction de l'image de l'animation (variable Etat)
      ; Cette angle varie de manière à donner une forme arrondi à la chenille 
      ; de l'Etat 0 qui donne une droite (l'angle est toujours égal à 0)
      ; à l'Etat maximum qui donne la courbure maximum à la chenille
      Angle = Angle + Etat * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      
      ; On calcul la position du rond suivant en se décalant du rond prédent d'un segment de longueur #Rayon et avec un angle "Angle"
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
    Next
    
    For n = #Longueur / 2 To #Longueur - 1 ; On fait de même pour la seconde moitié de la chenille, seul l'angle varie dans le sens inverse
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 180 / #Pi / 15)
      Angle = Angle - Etat * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
    Next
    
    Avance(Etat) = Int(Av - Px)
    Av = Av - Avance(Etat)
    
  Next
  
  ; Phase de dépliage de la chenille
  ; Cette phase est identique à la précédente à l'exeption que l'on par de l'Etat maximum (chenille plié au max) pour aller vers l'Etat minimum (chenille droite)
  For Etat = #NbImage / 2 To #NbImage
    Px = 0
    Py = 0
    Angle = 0
    
    For n = 0 To #Longueur / 2 - 1
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 180 / #Pi / 15)
      Angle = Angle + (#NbImage - Etat) * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
    Next
    
    For n = #Longueur / 2 To #Longueur - 1
      Chenille(Etat, n)\x = Px
      Chenille(Etat, n)\y = Py
      Chenille(Etat, n)\a = Int(Angle * 180 / #Pi / 15)
      Angle = Angle - (#NbImage - Etat) * Sin(n * 4 * #Pi / #Longueur) * #Amplitude
      Px = Px + #Rayon * Cos(Angle)
      Py = Py + #Rayon * Sin(Angle)
    Next
    
    Avance(Etat) = 0
    
  Next
  
EndProcedure

Procedure Rond_Couleur()
  ; On génère des carré de couleur dégradé suivant plusieur angle pour colorer la chenille
  For Angle = -180 To 180 Step 15 ; On fait varier l'angle de -180° à 180) avec un pas de 15°
    
    ; Pour chaque point de la matrice Couleur()
    ; Couleur(Angle, x, y) = couleur du point x, y de l'image ficitive (enregistré sous forme de matrice) avec un dégradé d'angle "Angle"
    For n = -#Rayon To #Rayon
      For nn = -#Rayon To #Rayon
        Angle_Rad.f = -Angle * #Pi / 180 ; On calcul l'angle en radian
        ; On fait une rotation des coordonnée du point n, nn afin de trouver la distance y suivant l'axe Y du repère incliné de l'Angle
        ; Cette distance va servir à savoir si il faut foncer ou éclaicir la couleuyr du point par rapport à la couleur du centre de l'image n=0, nn=0
        y = -n * Sin(Angle_Rad) + nn * Cos(Angle_Rad)
        ; On enregistre la couleur obtenu dans la matrice
        Couleur(Angle / 15 + 24, n + #Rayon, nn + #Rayon) = ColorLuminosity($EC387, 1 + y / 7)
      Next
    Next
    
  Next
EndProcedure

Procedure Image_Plafond() ; Création des images et des masques pour la chenille marchant en haut de l'écran
  Protected Etat
  Debug "Image_Plafond()"
  For Etat = 0 To #NbImage ; pour toutes les images qui composent l'animation de la chenille
    StartDrawing(SpriteOutput(Etat))
      ; Dessin de la chenille
      Box(0, 0, #TailleX, #TailleY, $2ABA8B) ; Fond en vert 
      ; Cette couleur doit tout de même être la plus proche possible de la chenille pour ne pas avoir de point de différente couleur lors du changement d'image
      For Pos = 1 To #Longueur - 1 ; pour tous les cercle qui compose la chenille
        Circle(#Rayon + Chenille(Etat, Pos)\x, #Rayon + Chenille(Etat, Pos)\y, #Rayon, 0) ; On dessine un cercle en Noir
        ; Ensuite, on colorise ce cercle à l'aide de la matrice Couleur et en fonction de l'angle d'inclinaison du centre du cercle
        For n = -#Rayon To #Rayon
          For nn = -#Rayon To #Rayon
            If Point(#Rayon + Chenille(Etat, Pos)\x + n, #Rayon + Chenille(Etat, Pos)\y + nn) = 0 ; Si le point est noir donc si on est au dessus du cercle que l'on vient de dessiner
              ; On applique la couleur au pixel en fonction de l'angle d'après la matrice Couleur()
              Plot(#Rayon + Chenille(Etat, Pos)\x + n, #Rayon + Chenille(Etat, Pos)\y + nn, Couleur(Chenille(Etat, Pos)\a + 24, n + #Rayon, #Rayon - nn))
            EndIf
          Next
        Next
      Next
      ; SaveSprite(Etat, "Image "+ Str(Etat) + ".bmp")
    StopDrawing()
  Next
EndProcedure

Procedure Image_Plancher() ; Création des images et des masques pour la chenille marchant en haut de l'écran
  Protected Etat
  Debug "Image_Plancher()"
  For Etat = 0 To #NbImage
    StartDrawing(SpriteOutput(Etat))
      ; Dessin de la chenille
      Box(0, 0, #TailleX, #TailleY, $2ABA8B) ; Fond en vert différent de celui de la chenille
      ; Cette couleur doit tout de même être la plus proche possible de la chenille pour ne pas avoir de point de différente couleur lors du changement d'image
      For Pos = 1 To #Longueur - 1
        Circle(#Rayon + Chenille(Etat, Pos)\x, #TailleY - #Rayon - Chenille(Etat, Pos)\y, #Rayon, 0)
        For n = -#Rayon To #Rayon
          For nn = -#Rayon To #Rayon
            If Point(#Rayon + Chenille(Etat, Pos)\x + n, #TailleY - #Rayon - Chenille(Etat, Pos)\y + nn) = 0
              Plot(#Rayon + Chenille(Etat, Pos)\x + n, #TailleY - #Rayon - Chenille(Etat, Pos)\y + nn, Couleur(Chenille(Etat, Pos)\a + 24, n + #Rayon, nn + #Rayon))
            EndIf
          Next
        Next
      Next
      
    StopDrawing()
    ; SaveSprite(Etat, "Image "+ RSet(Str(Etat), 2, "0") + ".bmp")
  Next
EndProcedure

Procedure Deplace_Ecran(x, y)
    CopyImage(#Fond, #Fond_Temp)
    DC = GetDC_(0)
    UseImage(#Fond)
    Dessin = StartDrawing(ImageOutput())
      Box(0, 0, #TailleX, #TailleY, 0)
      BitBlt_(Dessin, 0, 0, #TailleX, #TailleY, DC, WindowX() + x, WindowY() + y, #SRCPAINT)
      DrawImage(UseImage(#Fond_Temp), -x, -y)
    StopDrawing()
    ReleaseDC_(0, DC)
EndProcedure

Procedure Affiche()
  Protected x, y
  
  x = WindowX() ; on récupère la position x, y de la fenêtre
  y = WindowY()
  
  Etat + Pas
  If Etat > #NbImage
    Etat = 0
    Debug Str(x) + ", " + Str(y)
  ElseIf Etat < 0
    Etat = #NbImage
    Debug Str(x) + ", " + Str(y)
  EndIf
  
  If (x > GetSystemMetrics_(#SM_CXSCREEN) + #Tampon And Pas > 0) Or (x < - #TailleX - #Tampon And Pas < 0); Si la chenille est sorti de l'écran + une marge #Tampon
    Pas = -Pas ; On fait faire demi-tour à la chenille
    y = 0 ; on la mets au plafond (en haut de l'écran) si celle -ci est tombée
    Image_Plafond() ; on charge les images correspondant à la chenille qui marche au plafond
  EndIf
  
  If x >= -#TailleX And x <= GetSystemMetrics_(#SM_CXSCREEN) ; Si la chenille est visible à l'écran
    If Pas <> 0 ; Si la chenille avance
      x + Avance(Etat) * Pas ; On fait avancer la chenille
      
       If y = 0 ; Si on est au plafond
        
        ; Pour faire tomber la chenille du haut de l'écran
        If Etat = 0 And Random(50) = 0
          Pas = 0
          Image_Plancher() ; On charge les images de la chenille qui marche sur le sol
          y - #TailleY + 2 * #Rayon + 1 ; On déplace la fen en conséquence
        EndIf
        
      ElseIf y <> GetSystemMetrics_(#SM_CYSCREEN) - #TailleY ; Sinon, on est sur une fenêtre
      
        ; Pour faire tomber la chenille d'une fenêtre
        WinID = WindowFromPoint_(x + 2 * #Rayon, y + #TailleY) ; On regarde l'Id de la fenêtre sous l'extrémité gauche de la chenille
        If GetParent_(WinID) <> 0 ; On regarde si il s'agit d'une fenêtre ou d'un gadget
          Pas = 0 ; Si on n'est plus sur une fenêtre, on fait tomber la chenille
        EndIf
        WinID = WindowFromPoint_(x + #TailleY - 2 * #Rayon, y + #TailleY) ; De même pour l'extrémité droite de la chenille
        If GetParent_(WinID) <> 0
          Pas = 0
        EndIf
        
      EndIf
      
    Else ; Sinon, la chenille tombe
      
      y + 3 ; On fait tomber la chenille
      If Etat <> 0 ; on fait revenir progressivement l'état de la chenille à 0 pour que celle-ci soit droite
        Etat - 1
      EndIf
      
      If y >= GetSystemMetrics_(#SM_CYSCREEN) - #TailleY ; Si on est en bas de l'écran
        Pas = Random(1) * 2 - 1 ; On lance la chenille dans un sens au hazard
        y = GetSystemMetrics_(#SM_CYSCREEN) - #TailleY ; on place la chenille sur le bas de l'écran exactement
      EndIf
      
      WinID = WindowFromPoint_(x + 2 * #Rayon, y + #TailleY)
      If GetParent_(WinID) = 0 ; si il y a une fenêtre sous la chenille
        GetWindowRect_(WinID, @Pos.RECT) ; on récupère la position de la fenêtre
        If y >= Pos\top - #TailleY And y < Pos\top - #TailleY + 3 ; Si la chenille est au dessus du haut de la fenêtre
          Pas = Random(1) * 2 - 1 ; On lance la chenille dans un sens au hazard
          y = Pos\top - #TailleY ; On place la chenille sur le haut de la fenêtre exactement
        EndIf
      EndIf

    EndIf
    
    ; On affiche la nouvelle image de la chenille et on met en place le masque
    Deplace_Ecran(x - WindowX(), y - WindowY())
    StartDrawing(ScreenOutput())
      DrawImage(UseImage(#Fond), 0, 0)
    StopDrawing()
    DisplayTransparentSprite(Etat, 0, 0)
    FlipBuffers()
    
  Else ; Si la chenille n'est pas visible à l'écran, on ne fait que la déplacé
    x + Avance(Etat) * Pas ; On fait avancer la chenille
  EndIf
  
  MoveWindow(x, y) ; On déplace la fenêtre
  UpdateWindow_(WindowID()) ; on actualise l'affichage
EndProcedure




;- Debut du programme

OpenWindow(0, -#TailleX, 0, #TailleX, #TailleY, #PB_Window_BorderLess, "Chenille")
MakeToolWindow(WindowID(), 1)
; CreateGadgetList(WindowID())
SetWindowPos_(WindowID(), -1, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_NOMOVE)
InitSprite()
OpenWindowedScreen(WindowID(), 0, 0, #TailleX, #TailleY, 0, 0, 0)

CreateImage(#Fond, #TailleX, #TailleY)

For n = 0 To #NbImage ; On crée toute les images de l'animation
  CreateSprite(n, #TailleX, #TailleY)
  TransparentSpriteColor(n, $8B, $BA, $2A)
Next

Calcul() ; Cacul de la position de chaque cercle qui compose la chenille pour toutes les positions de celle-ci
Rond_Couleur() ; Calcul des images de remplissage de la chenille
Image_Plafond() ; Dessin des images de la chenille marchant au plafond
Pas = 1 ; Pas d'avance de la chenille

; On lance le Timer qui va définir la vitesse de l'animation
Etat = 0
Timer = SetTimer_(WindowID(0), 0, #Vitesse, 0)

; Création du PopopMenu
CreatePopupMenu(0)
MenuItem(0, "Quitter")
MenuBar()
MenuItem(1, "Information")

Repeat
  Event = WaitWindowEvent()
  
  If Event = #WM_LBUTTONUP Or Event = #WM_RBUTTONUP ; Si la souris est au dessus de la chenille
    DisplayPopupMenu(0, WindowID()) ; on affiche le PopupMenu
  
  ElseIf Event = #PB_EventMenu
    Select EventMenuID() ; menu et barre d'outils
      Case 0
        Event = #PB_Event_CloseWindow
      Case 1
        MessageRequester("Information", "Concepteur : LSI Développement [Bouguin Régis]" + Chr(10) + "Programmé sur PureBasic" + Chr(10) + Chr(10) + "http://perso.wanadoo.fr/lesoldatinconnu/", 4 * 16)
    EndSelect
  
  ElseIf Event = #WM_TIMER ; On passe à l'image suivante si le Timer se déclanche
    Affiche()
  EndIf
  
Until Event = #PB_Event_CloseWindow

; On tue le timer
KillTimer_(WindowID(0), Timer)

Publié : sam. 02/oct./2004 16:16
par nico
Je trouve cette version très réussie. :D

Publié : sam. 02/oct./2004 20:42
par Backup
il faut une librairie ??

chez moi ça plante la :

Code : Tout sélectionner

Couleur(Angle / 15 + 24, n + #Rayon, nn + #Rayon) = ColorLuminosity($EC387, 1 + y / 7)
le "ColorLuminosity" ???? 8O

Publié : dim. 03/oct./2004 11:56
par Fred
excellent :)

Publié : dim. 03/oct./2004 14:17
par erix14
Très bien :D

Publié : dim. 03/oct./2004 14:31
par Aranoth
Pareil que Dobro ! il reconnait pas la fonction...

Et aussi j'ai du redéclarer la constante #Pi

Publié : dim. 03/oct./2004 15:08
par Lukky
Moi c'est MakeToolWindow qu'il ne reconnait pas !

JL

Publié : dim. 03/oct./2004 15:39
par Le Soldat Inconnu
ben disons que les librairies nécessaires sont plus haut dans le message :roll:

PureTool de Danilo (voir sur PureArea.net)
ColorEffect de moi (voir sur mon site)
Resident Pi de moi (voir sur mon site)