Page 1 sur 4

[2D] Kill Birds

Publié : mar. 11/mars/2014 15:57
par falsam
Kill Birds (Raz le bol des Flappy Bird Like) : Un tir mode bourrain qui met en oeuvre les animations 2D d'un sprite grâce à l'utilisation conjointe de ClipSprite() et d'une liste chainée.

Image

Code, images et son dans ce fichier compressé.
:arrow: Télécharger killbirds.zip (Sources 455 Ko)

Utilisez la souris pour déplacer le viseur et le bouton gauche de la souris pour tirer.

Code : Tout sélectionner

;Kill Birds

EnableExplicit

Enumeration
  #font                ; Font pour l'affichage du score
  
  #mainform                 
  #background
  #ground
  
  #scorepanel
  #scoretext
  
  #bird                ;Oiseau  
  #sight               ;Viseur
  #explosion               
  
  #gunshoot            ;Son tir
  
EndEnumeration

Global Event          ; Evénement fenetre principale                   

;Structure type d'un sprite qui servira pour chaque oiseau et chaque explosion.
Structure Sprite 
  Actif.b              ; Actif
  
  x.i                  ; Position en X du sprite
  y.i                  ; Position en Y du sprite
    
  Animation.i          ; Animation en cours
  CurrentFrame.i       ; Indique quelle image de l'animation est actuellement en cours 
  
  FrameWidth.i         ; Largeur de chaque image de l'animation
  FrameHeight.i        ; hauteur de chaque image de l'animation
  FrameMax.i           ; Nombre d'image maximum pour une animation
  
  FrameRate.i          ; Transition entre deux images (Ms)
  FrameTimeLife.i      ; Indique la durée d'affichage de l'image en cours
    
  VelocityX.i          ; Vitesse déplacement en X
  VelocityY.i          ; Vitesse déplacement en Y
    
  SpriteWidth.i        ; Largeur du sprite 
  SpriteHeight.i       ; Hauteur du sprite 
  
  Life.i               ; Nombre de vie d'un sprite (Aucune utilité dans ce code)            
  
  Died.b               ; Exemple: Quand l'oiseau est touché il tombe
  Opacity.i            ; Exemple: Quand un oiseau est mort, l'opacité du sprite est réduite de moitié  
  
EndStructure 

Global NewList birds.Sprite(), CountBirds=30, AnimLeft=0, AnimRight=1, AnimDown = 2
Global explosion.sprite, AnimExplosion=0

Global Shoot.b        ; Il y a eu un tir (#True)
Global ShootTimeLife  ; Durée de vie d'un tir (En Ms)
Global LastShoot      ; Quand à eu lieu le dernier tir (en Ms) 
Global ShootLife.b    ; Un tir est actif

Global Ground         ;En quel position se trouve le sol

Global WMouseX.i, WMouseY.i, MouseRelease.b

Procedure Init()
  Protected cr.b = #True
  
  LoadFont(#font, "Arial", 25)
  UseJPEGImageDecoder()
  UsePNGImageDecoder()
  
  If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 And InitSound() = 0
    MessageRequester("Error", "Sprite system can't be initialized", 0)
    cr=#False
  EndIf
  
  ProcedureReturn cr
EndProcedure

;Creation des oiseaux
Procedure BirdsCreate(Value)
  Protected n, Scale
  For n =1 To Value
    Scale = Random(100, 30)
    
    AddElement(birds())
    birds()\Actif = #True
    birds()\died = #False
    birds()\Animation = AnimLeft
    birds()\CurrentFrame = Random(3, 0)
    birds()\FrameMax = 4
    birds()\FrameWidth = 64
    birds()\FrameHeight = 64
    birds()\FrameTimeLife = ElapsedMilliseconds()
    birds()\FrameRate = 130 
    birds()\x = Random(700, 100)
    birds()\y = Random(400, 50)
    birds()\VelocityX = Random(5, 1)*-1
    birds()\VelocityY = Random(2, 1)
    birds()\SpriteWidth = birds()\FrameWidth * Scale/100
    birds()\SpriteHeight = birds()\FrameHeight * Scale/100
    birds()\Opacity = 255
    
  Next
EndProcedure

;Les plumes voles (Sprite de 10 images de 200x200 - Frame rate 130ms)  
Procedure ExplosionCreate()
  explosion\Animation = AnimExplosion
  explosion\CurrentFrame=0
  explosion\FrameMax = 10
  explosion\FrameWidth = 200
  explosion\FrameHeight = 200
  explosion\FrameTimeLife = ElapsedMilliseconds()
  explosion\FrameRate = 130
EndProcedure

;Mise à jour du jeu
Procedure GameUpdate()
  
  DisplaySprite(#background, 0, 0)
  DisplaySprite(#ground, 0, 500) 
  
  ForEach birds()
    
    ;- Animation de chaque oiseau (Quel cirque!!!)
    If ElapsedMilliseconds()-birds()\FrameTimeLife > birds()\FrameRate

      birds()\FrameTimeLife = ElapsedMilliseconds()
           
      If birds()\CurrentFrame < birds()\FrameMax-1
        birds()\CurrentFrame+1  
      Else
        birds()\CurrentFrame=0  
      EndIf  
    EndIf

    ClipSprite(#bird, birds()\CurrentFrame * birds()\FrameWidth, birds()\Animation * birds()\FrameHeight, birds()\FrameWidth , birds()\FrameHeight)
    ZoomSprite(#bird, birds()\SpriteWidth, birds()\SpriteHeight)
    DisplayTransparentSprite(#bird, birds()\x, birds()\y, birds()\Opacity)  
    
    ;- Joueur tire    
    If MouseButton(#PB_MouseButton_Left) And Shoot = #False
      Shoot = #True
      ShootLife = #True
      PlaySound(#gunshoot)
    EndIf
    
    If MouseButton(#PB_MouseButton_Left) = 0
      Shoot = #False
    EndIf
    
    ;- Collision entre le viseur et un oiseau au moment du tir (ShootLife = #True)
    ;  L'oiseau doit etre actif (birds()\Actif = #True)
    ;  L'oiseau n'est pas encore touché (birds()\died = #False) 
    If SpriteCollision(#sight, MouseX(), MouseY(), #bird, birds()\x, birds()\y) And birds()\died = #False And birds()\Actif = #True
      If ShootLife = #True ;On vient de tirer
        birds()\died = #True ;L'oiseau est touché
        CountBirds-1 ;Un oiseau de moins (Je deteste les Flappy Birds like :p)
        explosion\Actif = #True ;Initialisation des plumes qui volent.
        
        ;Coordonnées de l'explosion par rapport au point x,y central de l'oiseau.
        explosion\x = birds()\x - birds()\FrameWidth
        explosion\y = birds()\y - birds()\FrameHeight
      EndIf
    EndIf  
        
    ;- Animation explosion (Les plumes voles) 
    If explosion\Actif = #True
      ClipSprite(#explosion, explosion\CurrentFrame * explosion\FrameWidth, explosion\Animation * explosion\FrameHeight, explosion\FrameWidth , explosion\FrameHeight)
      DisplayTransparentSprite(#explosion, explosion\x, explosion\y, 255)
      If ElapsedMilliseconds()-explosion\FrameTimeLife > explosion\FrameRate
        Explosion\FrameTimeLife = ElapsedMilliseconds()
           
        If explosion\CurrentFrame < explosion\FrameMax-1
          explosion\CurrentFrame+1  
        Else
          explosion\CurrentFrame=0  
          explosion\Actif = #False
        EndIf    
      EndIf        
    EndIf 
    
    ;-Controle vélocité et rebond des oiseaux dans les limites de la surface de jeu
    If birds()\Actif = #True
      birds()\x + birds()\VelocityX
    
      If birds()\x < 0 Or birds()\x > 800
        birds()\VelocityX *-1
        If birds()\VelocityX > 0
          birds()\Animation = AnimRight  
        Else
          birds()\Animation = AnimLeft
        EndIf  
      EndIf
    Else
      birds()\y - birds()\VelocityY
    EndIf
    
    ;-Un oiseau est touché
    If birds()\Died = #True And birds()\Actif = #True
      birds()\Animation = AnimDown
      birds()\y + (birds()\VelocityY)*3 ;Il tombe 3 fois plus vite
      
      ;Il touche le sol
      If birds()\y > Ground
        birds()\y = ground
        birds()\Actif = #False ;Il devient inactif
        birds()\Opacity = 128
      EndIf
    EndIf
    
  Next
  
  ;- Controle durée de vie d'un tir
  If ShootLife=#True
    If ElapsedMilliseconds()-LastShoot > ShootTimeLife
      LastShoot = ElapsedMilliseconds()
      ShootLife = #False
    EndIf
  EndIf 
  
  ;Affiche le viseur
  DisplayTransparentSprite(#sight, MouseX(), MouseY(), 255)    
  
  ;Affichage du score
  DisplayTransparentSprite(#scorepanel, 650, 480)
  CreateSprite(#scoretext, 120, 60)
  StartDrawing(SpriteOutput(#scoretext))
  Box(0, 0, 120, 60, RGB(54, 54, 54))
  DrawingFont(FontID(#font))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawText(10, 10, Str(CountBirds), RGB(255, 69, 0))
  StopDrawing()
  RotateSprite(#scoretext, -5, #PB_Absolute)
  TransparentSpriteColor(#scoretext, RGB(54, 54, 54))
  DisplayTransparentSprite(#scoretext, 685, 475, 255)    
  
EndProcedure

Procedure GameStart()
  
  ShootTimeLife = 500 ;Durée de vie d'un tir en ms
  Ground = 450 ;Position vertical du sol
  
  If OpenWindow(#mainform, 0, 0, 800, 600, "Kill Birds", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
    If OpenWindowedScreen(WindowID(#mainform), 0, 0, 800, 600)
      
      ;Son tir
      LoadSound(#gunshoot, "data/sounds/gunshot.wav")
      
      ;Creation de l'animation explosion
      ExplosionCreate()
      
      ;Image de fond et sol
      LoadSprite(#background, "data/images/background.jpg")
      LoadSprite(#ground, "data/images/ground.jpg")
      
      ;Panneau de score
      LoadSprite(#scorepanel, "data/images/panel1.png", #PB_Sprite_AlphaBlending)
      ZoomSprite(#scorepanel, 120, 60)
      
      ;L'oiseau
      LoadSprite(#bird, "data/images/bird.png", #PB_Sprite_AlphaBlending)
            
      ;Viseur
      LoadSprite(#sight, "data/images/sight.png", #PB_Sprite_AlphaBlending)
      ZoomSprite(#sight, 50, 50)
      
      ;Explosion
      LoadSprite(#explosion, "data/images/iceblaster.png", #PB_Sprite_AlphaBlending)
            
      ;Oiseaux
      BirdsCreate(CountBirds)
      
      ;-Boucle evenementielle
      Repeat  
        Repeat
          event = WindowEvent()
          Select event  
            Case #PB_Event_CloseWindow
            End
          EndSelect  
        Until event=0
    
        FlipBuffers()
        ClearScreen(RGB(0,0,0))
                
        ExamineKeyboard()
        ExamineMouse()
        GameUpdate()
        
        ;- U.T.: Pointeur de la souris en dehors des limites du jeu
        WMouseX = WindowMouseX(#Mainform)
        WMouseY = WindowMouseY(#Mainform)
    
        If MouseRelease = #True
          MouseRelease = #False
        EndIf
    
        MouseLocate(WMouseX, WMouseY)
        If WMouseX > 0 And WMouseX < WindowWidth(#Mainform, #PB_Window_InnerCoordinate)-1 And 
          WMouseY > 0 And WmouseY < WindowHeight(#Mainform, #PB_Window_InnerCoordinate)-1
          ReleaseMouse(#False)    
        Else
          MouseRelease = #True
          ReleaseMouse(#True)   
        EndIf
        ;Fin U.T.

    Until KeyboardPushed(#PB_Key_Escape)
  
    Else
      MessageRequester("Oops", "Erreur lors de la création de la fenêtre 2D", 0)
    EndIf  
  EndIf
EndProcedure

If Init()
  GameStart()
Else
  MessageRequester("Oops !", "Impossible d'intialiser l'environnement 2D")
EndIf

End
L'animation d'un sprite n'est pas simple comparé à d'autres langages. Je vais même finir par aimer certains framework JavaScript dédié au 2D :)

Re: [2D] Kill Birds

Publié : mar. 11/mars/2014 18:30
par jmg49
:P génial !!

Merci du partage, moi j'aime bien ça défoule !

graphiquement joli, ça bouge rapidement .

Re: [2D] Kill Birds

Publié : mar. 11/mars/2014 18:43
par majikeyric
joli et très propre :)

Re: [2D] Kill Birds

Publié : mar. 11/mars/2014 20:10
par Fig
Très propre, bon boulot ! 8O

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 0:07
par Ar-S
Merci pour ce partage :) C'est beau !

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 0:31
par Mindphazer
Fonctionne très bien sur Mac !

Merci et bravo

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 7:29
par Fred
Cool :)

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 9:30
par blendman
Chouette ;)

Elles viennent d'où tes images, c'est joli.

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 9:45
par Backup
ce jeux me rappel crack'ed Eggs sur Atari :)
http://www.youtube.com/watch?v=WvjSLsNMV9k

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 11:01
par falsam
Je ne m'attendais pas à autant de réaction positive d'autant plus que c'est mon premier test 2D avec Pure basic.

@blendman: N'ayant pas ton talent de dessinateur, je me suis procuré ces images sur le net à partir de sources open-source. Le fond d'écran et le sol viennent du framework pixi.js par exemple :)

Je ne serais pas contre l'ajout d'un forum ressources média (Images, sons, etc ...)

@Dobro: Merci pour ce lien. Peut être que je mettrais des pommes :mrgreen:

@Fred: Concernant la transparence, j'ai noté tes observations sur un autre post et je vais modifier le code en conséquence. Merci :)

@Mindphazer, Ar-S, Fig, majikeyric, jmg49: Merci :)

En tout cas ça change du Flappy Bird .....

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 12:13
par Fig
falsam a écrit :Je ne serais pas contre l'ajout d'un forum ressources média (Images, sons, etc ...)
Ce serait une très bonne idée...

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 12:48
par nico
Très beau, bravo. :)

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 13:25
par falsam
Merci Nico :)

La gestion des image avec canal alpha étant en fait pris en charge, j'ai modifié le code.
Code et téléchargement mis à jour dans le premier message.

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 14:00
par Mindphazer
falsam a écrit :Merci Nico :)

La gestion des image avec canal alpha étant en fait pris en charge, j'ai modifié le code.
Code et téléchargement mis à jour dans le premier message.
Hum...
Pas sur Mac, visiblement.
Du coup maintenant, les piafs sont tous affichés sur un carré noir

Re: [2D] Kill Birds

Publié : mer. 12/mars/2014 15:07
par falsam
L'animation des sprites n'a peut être pas été compris par tout le monde.

Rappel : La planche du sprite représentant l'oiseau est composée de 4 rangée d'animations.

Image

-La première rangée représente l'animation déplacement à gauche
-La seconde rangée représente l'animation déplacement à droite
-La quatrième rangée représente l'animation de face

Nota: Je ne me sert pas de la 3eme rangée.

Le code qui suit contient toutes les explications. Il affiche un oiseau que vous pouvez contrôler avec les flèches gauche ou droite.

Code : Tout sélectionner

EnableExplicit

Enumeration  
  #mainform                 
  #background
  #ground
    
  #bird       
  
  #soundforest
EndEnumeration

Global Event          

;Structure type d'un sprite: Les informations obligatoires sont précédés d'un *
Structure Sprite 
  Actif.b              ; Actif
  
  x.i                  ; * Position en X du sprite
  y.i                  ; * Position en Y du sprite
    
  Animation.i          ; * Animation en cours
  CurrentFrame.i       ; Indique quelle image de l'animation est actuellement en cours 
  
  FrameWidth.i         ; * Largeur de chaque image de l'animation
  FrameHeight.i        ; * hauteur de chaque image de l'animation
  FrameMax.i           ; * Nombre d'image maximum pour une animation
  
  FrameRate.i          ; * Transition entre deux images (Ms)
  FrameTimeLife.i      ; Indique la durée d'affichage de l'image en cours
    
  VelocityX.i          ; Vitesse déplacement en X
  VelocityY.i          ; Vitesse déplacement en Y
    
  SpriteWidth.i        ; * Largeur du sprite 
  SpriteHeight.i       ; * Hauteur du sprite 
  
  Life.i               ; Nombre de vie d'un sprite (Aucune utilité dans ce code)            
  
  Opacity.i            ; * Opacité (0 à 255)
  
EndStructure 

;On instance la struture sprite à l'oiseau.
Global bird.Sprite

;Définition de l'animation
;Chaque variable détermine le numéro de la rangée de l'image qui sera pris en compte pour l'animation
;0 Sera la premiere rangée.

Global AnimationLeft  = 0 ;1er rangée de l'image
Global AnimationRight = 1 ;2eme rangée de l'image 
Global AnimationFace  = 3 ;4eme rangéee de l'image

;Une rangée sera multipliée par la hauteur d'une image frame pour determiner ou commence la rangée suivante.

Procedure Init()
  Protected cr.b = #True
  
  UseJPEGImageDecoder()
  UsePNGImageDecoder()
  
  If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 And InitSound() = 0
    MessageRequester("Error", "Sprite system can't be initialized", 0)
    cr=#False
  EndIf
  
  ProcedureReturn cr
EndProcedure

;Mise à jour du jeu
Procedure GameUpdate()
  
  DisplaySprite(#background, 0, 0)
  DisplaySprite(#ground, 0, 500) 
  
  ;Mise à jour de l'oiseau 
  If ElapsedMilliseconds() - bird\FrameTimeLife > bird\FrameRate
    bird\FrameTimeLife = ElapsedMilliseconds()
           
    If bird\CurrentFrame < bird\FrameMax-1
      bird\CurrentFrame+1  
    Else
      bird\CurrentFrame=0  
    EndIf  
  EndIf
 
  ClipSprite(#bird, bird\CurrentFrame * bird\FrameWidth, bird\Animation * bird\FrameHeight, bird\FrameWidth ,bird\FrameHeight)
  ZoomSprite(#bird, bird\SpriteWidth, bird\SpriteHeight)
  DisplayTransparentSprite(#bird, bird\x, bird\y, bird\Opacity)  
 
  
  ;A gauche
  If KeyboardPushed(#PB_Key_Left)
    bird\Animation = AnimationLeft ;L'animation change
    bird\x - bird\VelocityX ;La position x change 
  EndIf
    
  ;A droite:
  If KeyboardPushed(#PB_Key_Right)
    bird\Animation = AnimationRight ;L'animation change
    bird\x + bird\VelocityX ;La position x change 
  EndIf
  
  
  ;Si on relache une des deux touches Left or Right
  If KeyboardReleased(#PB_Key_Left) Or KeyboardReleased(#PB_Key_Right)
    bird\Animation = AnimationFace
  EndIf
  
    
EndProcedure

Procedure GameStart()
  
  If OpenWindow(#mainform, 0, 0, 800, 600, "Kill Birds", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
    If OpenWindowedScreen(WindowID(#mainform), 0, 0, 800, 600)
      
      ;Ambience foret
      LoadSound(#soundforest, "data/sounds/ambientforest.wav")
      PlaySound(#soundforest, #PB_Sound_Loop) 
            
      ;Image de fond et sol
      LoadSprite(#background, "data/images/background.jpg")
      LoadSprite(#ground, "data/images/ground.jpg")
            
      ;L'oiseau
      LoadSprite(#bird, "data/images/bird.png", #PB_Sprite_AlphaBlending)
      
      ;Caractéristique de l'animation
      ;Chaque image fait 64x64 pixels et il y a 4 images par ligne
      bird\FrameWidth = 64
      bird\FrameHeight = 64
      bird\FrameMax = 4
      bird\FrameRate = 130
      
      ;Animation au depart du jeu
      bird\Animation = AnimationFace
      
      ;Vélocité du sprite 
      bird\VelocityX = 5
      
      ;Coordonnées x,y et taille du sprite
      bird\x = 400
      bird\y = 200 
      bird\SpriteWidth = 80
      bird\SpriteHeight = 80
      
      bird\Opacity = 255
      
      ;-Boucle evenementielle
      Repeat  
        Repeat
          event = WindowEvent()
          Select event  
            Case #PB_Event_CloseWindow
            End
          EndSelect  
        Until event=0
    
        FlipBuffers()
        ClearScreen(RGB(0,0,0))
                
        ExamineKeyboard()
        ExamineMouse()
        GameUpdate()

    Until KeyboardPushed(#PB_Key_Escape)
  
    Else
      MessageRequester("Oops", "Erreur lors de la création de la fenêtre 2D", 0)
    EndIf  
  EndIf
EndProcedure

If Init()
  GameStart()
Else
  MessageRequester("Oops !", "Impossible d'intialiser l'environnement 2D")
EndIf

End
Ce code est inclus dans le fichier téléchargeable depuis le premier message.