Page 1 sur 1

[2D] Gravity & Bounce

Publié : mar. 16/août/2016 19:36
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)

Re: [2D] Gravity & Bounce

Publié : mar. 16/août/2016 22:10
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)

Re: [2D] Gravity & Bounce

Publié : mer. 17/août/2016 11:22
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.

Re: [2D] Gravity & Bounce

Publié : mer. 17/août/2016 16:31
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.

Re: [2D] Gravity & Bounce

Publié : mer. 18/janv./2017 23:20
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:





@++

Re: [2D] Gravity & Bounce

Publié : jeu. 19/janv./2017 11:05
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)

Re: [2D] Gravity & Bounce

Publié : jeu. 19/janv./2017 18:08
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






@++

Re: [2D] Gravity & Bounce

Publié : lun. 14/août/2017 7:03
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)