[2D] Gravity & Bounce

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

[2D] Gravity & Bounce

Message par falsam »

Un code trés simple pour visualiser un cube soumis à une gravité qui rebondit quand il touche le bas de l'écran.
Barre d'espace pour une nouvelle impulsion.

Code : Tout sélectionner

;Gravity & Bounce V1.0

EnableExplicit

Global Event  
Global Image  

;Sprite structure
Structure newSprite
  id.i
  x.i
  y.i
  speedX.f
  speedY.f
  gravity.f
  gravitySpeed.f
  bounce.f
  impulse.f
EndStructure

;Square
Global square.newSprite

;Init 
InitSprite() : InitKeyboard()
UsePNGImageDecoder() : UsePNGImageEncoder()

;Screen 
OpenWindow(0, 0, 0, 800, 600, "Gravity & Bounce", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600)

;Create a awesome spite sheet ^^
Image = CreateImage(#PB_Any, 32, 32, 24, RGB(255, 255, 255))
SaveImage(Image, "WhiteSquare.png", #PB_ImagePlugin_PNG)

;Setup square
With square
  \id = LoadSprite(#PB_Any, "WhiteSquare.png")
  \x = 10
  \y = 100
  \speedX = 1
  \gravity = 0.09
  \bounce = 0.5
  \impulse = 5
EndWith 

Repeat  
  Repeat
    Event = WindowEvent()
    Select Event    
      Case #PB_Event_CloseWindow
        End
    EndSelect  
  Until Event = 0 
  
  FlipBuffers()
  ClearScreen(RGB(135, 206, 235))
  
  ;Display Sprites
  With square
    DisplaySprite(\id, \x, \y)
  EndWith
  
  ;New position
  With square
    \gravitySpeed + \gravity
    \x  + \speedX
    \y + \speedY + \gravitySpeed
  EndWith
  
  ;Hit bottom
  With square
    If \y > ScreenHeight() - SpriteHeight(\id)
      \y = ScreenHeight() - SpriteHeight(\id)
      \gravitySpeed = -\gravitySpeed * \bounce
      \speedX = 0
    EndIf
  EndWith  
  
  ;Pulse up 
  ExamineKeyboard()
  If KeyboardReleased(#PB_Key_Up) And square\speedX = 0 
    square\gravitySpeed - square\impulse
    square\speedX  = 1
  EndIf
  
Until KeyboardPushed(#PB_Key_Escape)
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: [2D] Gravity & Bounce

Message par falsam »

Ajoutons un gestionnaire de collision.

Le même code mais avec une gestion de collision minimaliste car je ne gère pas les collisions frontales.

Code : Tout sélectionner

;Gravity & Bounce V1.0

EnableExplicit

Global Event  
Global Image  

;Sprite structure
Structure newSprite
  id.i
  
  x.i
  y.i
  
  speedX.f
  speedY.f
  gravity.f
  gravitySpeed.f
  bounce.f
  impulse.f  
EndStructure

;Square
Global square.newSprite
Global ground.newSprite
Global NewMap scene.newSprite()

;Init 
InitSprite() : InitKeyboard()
UsePNGImageDecoder() : UsePNGImageEncoder()

;Screen 
OpenWindow(0, 0, 0, 800, 600, "Gravity & Bounce", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600)

;Create a awesome spite sheet ^^
Image = CreateImage(#PB_Any, 32, 32, 24, RGB(255, 255, 255))
SaveImage(Image, "WhiteSquare.png", #PB_ImagePlugin_PNG)

;Setup square
With square
  \id = LoadSprite(#PB_Any, "WhiteSquare.png")
  \x = 10
  \y = 100
  \speedX = 1
  \gravity = 0.09
  \bounce = 0.5
  \impulse = 5
EndWith 

;Setup Scene
AddMapElement(scene(), "ground")
scene()\id = CopySprite(square\id, #PB_Any)
scene()\x = 0
scene()\y = ScreenHeight() -20
ZoomSprite(scene()\id, ScreenWidth(), 20)

AddMapElement(scene(), "block1")
scene()\id = CopySprite(square\id, #PB_Any)
scene()\x = 200
scene()\y = 560
ZoomSprite(scene()\id, 600, 20)

AddMapElement(scene(), "block2")
scene()\id = CopySprite(square\id, #PB_Any)
scene()\x = 300
scene()\y = 500
ZoomSprite(scene()\id, 100, 80)

AddMapElement(scene(), "block3")
scene()\id = CopySprite(square\id, #PB_Any)
scene()\x = 400
scene()\y = 400
ZoomSprite(scene()\id, 200, 180)

Repeat  
  Repeat
    Event = WindowEvent()
    Select Event    
      Case #PB_Event_CloseWindow
        End
    EndSelect  
  Until Event = 0 
  
  FlipBuffers()
  ClearScreen(RGB(135, 206, 235))
  
  ;Display Scene
  ForEach Scene()
    DisplaySprite(scene()\id, scene()\x, scene()\y)
  Next
  
  ;Display square
  With square 
    DisplaySprite(\id, \x, \y)
  EndWith

  
  ;New square position
  With square
    \gravitySpeed + \gravity
    \x  + \speedX
    \y + \speedY + \gravitySpeed
  EndWith
  
  ;Hit with object
  ForEach scene()  
    If SpriteCollision(square\id, square\x, square\y, scene()\id, scene()\x, scene()\y)
      square\y = scene()\y - SpriteHeight(square\id)
      square\gravitySpeed = -square\gravitySpeed * square\bounce
      square\speedX = 0
    EndIf
  Next
  
  ;Pulse up 
  ExamineKeyboard()
  If KeyboardReleased(#PB_Key_Space) And square\speedX = 0 
    square\gravitySpeed - square\impulse
    square\speedX  = 1
  EndIf
  
Until KeyboardPushed(#PB_Key_Escape)
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: [2D] Gravity & Bounce

Message par falsam »

Avec le code précédent il n'était pas possible de déplacer le carré avec les fléches et je ne testais pas les collisions frontales.

C'est chose fait avec ce nouveau code.

Code : Tout sélectionner

;Gravity & Bounce V1.5

EnableExplicit

Global Event  
Global Image  

;Sprite structure
Structure newSprite
  id.i
  
  x.i
  y.i
  
  direction.i
  velocityX.f
  speedX.f
  speedY.f
  gravity.f
  gravitySpeed.f
  bounce.f
  impulse.f
  collide.b
  collideY.f
EndStructure

;Square
Global square.newSprite
Global ground.newSprite
Global NewMap scene.newSprite()

;Init 
InitSprite() : InitKeyboard()
UsePNGImageDecoder() : UsePNGImageEncoder()

;Screen 
OpenWindow(0, 0, 0, 800, 600, "Gravity & Bounce", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600)

;Create a awesome spite sheet ^^
Image = CreateImage(#PB_Any, 32, 32, 24, RGB(255, 255, 255))
SaveImage(Image, "WhiteSquare.png", #PB_ImagePlugin_PNG)

;Setup square
With square
  \id = LoadSprite(#PB_Any, "WhiteSquare.png")
  \x = 10
  \y = 100
  \direction = 1 ;Default Right
  \velocityX = 2
  \speedX = \velocityX
  \gravity = 0.09
  \bounce = 0.5
  \impulse = 5
  
  ;Change color
  StartDrawing(SpriteOutput(\id))
  Box(0, 0, 32, 32, RGB(255, 0, 0))
  StopDrawing()
EndWith 

;Setup Scene
AddMapElement(scene(), "ground")
scene()\id = LoadSprite(#PB_Any, "WhiteSquare.png")
scene()\x = 0
scene()\y = ScreenHeight() -20
ZoomSprite(scene()\id, ScreenWidth(), 20)

AddMapElement(scene(), "block1")
scene()\id = LoadSprite(#PB_Any, "WhiteSquare.png")
scene()\x = 200
scene()\y = 560
ZoomSprite(scene()\id, 600, 20)

AddMapElement(scene(), "block2")
scene()\id = LoadSprite(#PB_Any, "WhiteSquare.png")
scene()\x = 300
scene()\y = 500
ZoomSprite(scene()\id, 100, 80)

AddMapElement(scene(), "block3")
scene()\id = LoadSprite(#PB_Any, "WhiteSquare.png")
scene()\x = 400
scene()\y = 450
ZoomSprite(scene()\id, 200, 110)

AddMapElement(scene(), "Wall left")
scene()\id = LoadSprite(#PB_Any, "WhiteSquare.png")
scene()\x = 0
scene()\y = 200
ZoomSprite(scene()\id, 20, 400)

AddMapElement(scene(), "Wall Right")
scene()\id = LoadSprite(#PB_Any, "WhiteSquare.png")
scene()\x = 780
scene()\y = 200
ZoomSprite(scene()\id, 20, 400)

Repeat  
  Repeat
    Event = WindowEvent()
    Select Event    
      Case #PB_Event_CloseWindow
        End
    EndSelect  
  Until Event = 0 
  
  FlipBuffers()
  ClearScreen(RGB(135, 206, 235))
  
  ;Display Scene
  ForEach Scene()
    DisplaySprite(scene()\id, scene()\x, scene()\y)
  Next
  
  ;Display square
  With square 
    DisplaySprite(\id, \x, \y)
  EndWith
  
  ;Hit with object
  ForEach scene()
    If SpriteCollision(square\id, square\x, square\y, scene()\id, scene()\x, scene()\y) And square\collide = #False
      
      ;Horizontal displacement = 0
      square\speedX = 0
     
      If square\x - scene()\x  <= 0 And MapKey(Scene()) <> "ground" And square\direction = 1
        ;Right vertical collision
        square\x = scene()\x - (SpriteWidth(square\id))
        square\speedX = square\velocityX * -1
      ElseIf (scene()\x + SpriteWidth(scene()\id)) - square\x  <= Abs(Int(square\velocityX)) And MapKey(Scene()) <> "ground"
        ;Left vertical collision
        square\x = scene()\x + SpriteWidth(scene()\id) 
        square\speedX = square\velocityX 
        
      Else
        ;Horizontal collision
        square\y = scene()\y - SpriteHeight(square\id)
        square\collideY = square\y        
        square\collide = #True
      EndIf 
    EndIf
    
  Next
  
  ;New square position
  With square
    
    \gravitySpeed + \gravity
    \x  + \speedX
    \y + \speedY + \gravitySpeed    
    
    ;Bouce if collision
    If \collide = #True
      If \y >= \collideY 
        \y = \collideY 
        \gravitySpeed = - (\gravitySpeed * \bounce)
      EndIf
    EndIf     
    
    ;Out of bound
    If \x < 0 Or \x > ScreenWidth() - SpriteWidth(\id)
      \speedX * -1  
    EndIf
  EndWith
  
  ;Pulse up 
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_Space) And square\collide = #True ;square\speedX = 0 
    square\gravitySpeed - square\impulse
    square\speedX = square\velocityX * square\direction
    square\collide = #False
  EndIf
  
  ;Move to left : Gravity speed must be = 0
  If square\collide = #True
    If KeyboardPushed(#PB_Key_Left)
      square\direction = -1
      square\speedX = square\velocityX * square\direction 
      square\collide = #False
      
      ;Move to left : Gravity speed must be = 0  
    ElseIf KeyboardPushed(#PB_Key_Right)
      square\direction = 1
      square\speedX = square\velocityX * square\direction
      square\collide = #False
      
    EndIf
  EndIf 
Until KeyboardPushed(#PB_Key_Escape)
- Flèches gauche ou droit pour déplacer le carré.
- Barre d'espace pour l'impulsion.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: [2D] Gravity & Bounce

Message par falsam »

Modification de mon code précédent : http://www.purebasic.fr/french/viewtopi ... 25#p185825
- Suite à une remarque de GallyHC sur le tchat de PureBasic, Le rebond est traité en dehors du test de collision.

je ne suis pas satisfait du code associé au rebond car je n'arrive pas à obtenir une vitesse de gravitation égale à zero ce qui pourrait provoquer un léger scintillement verticale du sprite.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
venom
Messages : 3071
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: [2D] Gravity & Bounce

Message par venom »

Bonjour Falsam,

Comment modifier ton premier code pour activé la gravité a un moment donner ? (pas au lancement du code)

je souhaiterais pouvoir déplacer le cube horizontalement avant de lui faire subir une gravité via une autre touche.

Je trifouille ton code depuis 2 jours, pas moyen :? :D (J'y arrive mais uniquement si la gravité c'est produite 1 fois au démarrage.)

Merci
ps: je ne connais pas trop les structures. :oops:





@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: [2D] Gravity & Bounce

Message par falsam »

venom a écrit :Comment modifier ton premier code pour activé la gravité a un moment donner ? (pas au lancement du code)
■ Ligne 42 tu initialises la gravité à 0.

Code : Tout sélectionner

;Setup square
With square
  ...
  \gravity = 0.09
  ...  
EndWith 
■ Ensuite tu vas devoir définir un déclencheur pour activer la gravité: Par exemple la barre d'espace.

Code : Tout sélectionner

If KeyboardReleased(#PB_Key_Space) 
    square\gravity  = 0.09
EndIf
■ Le code complet (Touche Espace pour lâcher le carré)

Code : Tout sélectionner

;Gravity & Bounce V1.0

EnableExplicit

Global Event  
Global Image  

;Structure d'un sprite
Structure newSprite
  id.i
  x.i
  y.i
  speedX.f
  speedY.f
  gravity.f
  gravitySpeed.f
  bounce.f
  impulse.f
EndStructure

;Un carré associé à la structrure d'un sprite
Global square.newSprite

;Init 
InitSprite() : InitKeyboard()
UsePNGImageDecoder() : UsePNGImageEncoder()

;Screen 
OpenWindow(0, 0, 0, 800, 600, "Gravity & Bounce", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600)

;Création du sprite ^^
Image = CreateImage(#PB_Any, 32, 32, 24, RGB(255, 255, 255))
SaveImage(Image, "WhiteSquare.png", #PB_ImagePlugin_PNG)

;Setup square
With square
  \id = LoadSprite(#PB_Any, "WhiteSquare.png")
  \x = 10
  \y = 100
  \speedX = 1
  \gravity = 0.0
  \bounce = 0.5
  \impulse = 5
EndWith 

Repeat  
  Repeat
    Event = WindowEvent()
    Select Event    
      Case #PB_Event_CloseWindow
        End
    EndSelect  
  Until Event = 0 
  
  FlipBuffers()
  ClearScreen(RGB(135, 206, 235))
  
  ;Affichage du sprite
  With square
    DisplaySprite(\id, \x, \y)
  EndWith
  
  ;Nouvelle position du carré
  With square
    \gravitySpeed + \gravity        
    \x  + \speedX                   
    \y + \speedY + \gravitySpeed    
  EndWith
  
  ;Le carré touche le sol
  With square
    If \y > ScreenHeight() - SpriteHeight(\id)
      \y = ScreenHeight() - SpriteHeight(\id)
      \gravitySpeed = -\gravitySpeed * \bounce
      \speedX = 0
    EndIf
  EndWith  
  
  ;Impulsion vers le haut 
  ExamineKeyboard()
  If KeyboardReleased(#PB_Key_Up) And square\speedX = 0 
    square\gravitySpeed - square\impulse
    square\speedX  = 1
  EndIf
  
  ;Ajout gravité
  If KeyboardReleased(#PB_Key_Space) 
    square\gravity  = 0.09
  EndIf
  
Until KeyboardPushed(#PB_Key_Escape)
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
venom
Messages : 3071
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: [2D] Gravity & Bounce

Message par venom »

Arf... C'était si simple :arrow: j'ai honte. J'ai pourtant essayé plein de chose mais ça sa ne ma pas traversé l'esprit.

Merci falsam






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
ICE
Messages : 42
Inscription : jeu. 18/nov./2010 15:26

Re: [2D] Gravity & Bounce

Message par ICE »

Sorry for my english:
Here the Chipmunk2D port to [2D]Gravity&Bounce:
Image

what can you do:
- Mouse is working (mouse picking)
- Player (red square) can be controled with left/right arrow key and space
- Debug draw (press the "D" for on/off)

Executable:
http://www.morty-productions.de/icesoft ... ipmunk.zip (133.5 KB)
Répondre