Page 1 sur 1

[OK]Aide pour algorithme saut de sprite...

Publié : lun. 15/août/2016 16:09
par Ar-S
Bonjour,

Je voudrais réaliser un petit saut de sprite.. J'ai regardé les exemples (d'anablast entre autre) mais je ne pige pas.
Idem sur les tutos trouvés du net, ces histoires de vélocité, gravité, accélération ça me déprime.
Auriez vous un algo simple et assez propre de saut ?
Si une bonne âme peut faire un petit tuto là dessus ce sera utile.

Avec un timer ce serait gérable mais j'aimerai une méthode via elapsemillisecond()

Voilà mon code, ne pas tenir compte du code commenté, c'est un mix d'essais foireux.
D'avance merci

Code : Tout sélectionner

If InitSprite() = 0 Or InitKeyboard() = 0
  MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire aux sprites !", 0)
  End
EndIf

Declare   CheckFrontiere()
Declare   CreaSprite()

Enumeration
  #win
  #CB1
EndEnumeration



#DROITE = 1
#GAUCHE = 2
#NOMOVE = 0

Structure CB
  X.i     ; Position X
  Xini.i  ; Position initial en X (repère pour pour saut)
  Y.i     ; Position Vertical
  dir.b   ; direction
  vd.b    ; vitesse droite
  vg.b     ; vitesse gauche
  a.f     ; accélération
  t.f     ; temps
  g.f     ; Gravite
EndStructure

Global MonSprite.CB\X 
Global MonSprite.CB\Y

Global DIR
Global ySp = 160 - 69 ; Frontière sol (bas)
Global xSP = 800 - 64 ; Frontière ecran (droite)


; Gestion du saut
; Global c = 100    ; Hauteur du saut max
; Global b = MonSprite.CB\X + 200 ; Distance x du saut
; Global a = MonSprite.CB\X 
; positionFinale.x = MonSprite.CB\V * tempsApresLancer * Cos(angleDeLancer) + positionInitiale.x;


Macro CoW(champ,valeur)
  Global MonSprite.CB\champ = valeur
EndMacro


; INITIALISATION /////////

Cow(Y,ySp)
Cow(X,64)
Cow(Xini,64)
Cow(vd,3)
Cow(vg,-3)
Cow(g,9.6)
Cow(Dir,#Droite)

;////////////////////////


If OpenWindow(#win, 0, 0, 800, 160, "sprite jump", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  DIR = #NOMOVE
  If OpenWindowedScreen(WindowID(0), 0, 0, 800, 160)
    KeyboardMode(#PB_Keyboard_International)
    
    CreaSprite()

    
  Else
    MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
    End
  EndIf
EndIf


Repeat
  ; Double repeat / event et 2D
  ;
  Repeat
    Event = WindowEvent()
    
    Select Event 
             
      Case #PB_Event_Gadget
        If EventGadget() = 0
          End
        EndIf
        
      Case #PB_Event_CloseWindow
        End 
    EndSelect
  Until Event = 0
  
  
  ; ***************** PARTIE 2D
  FlipBuffers() 
  ClearScreen(RGB(0, 0, 0))
  
  ExamineKeyboard()
  
  ; GAUCHE
  If KeyboardPushed(#PB_Key_Q)
    DIR = #GAUCHE
    LastDIR = #GAUCHE
    MonSprite.CB\X + MonSprite.CB\vg
    
    ; DROITE
  ElseIf KeyboardPushed(#PB_Key_D)  
    DIR = #DROITE
    LastDIR = #DROITE
    MonSprite.CB\X + MonSprite.CB\vd
  EndIf  
  
    
    ; SAUT
  If KeyboardPushed(#PB_Key_Space)
    Debug "hop"
    Saut = #True

  Else
    DIR = #NOMOVE
  EndIf
  

  
; AFFICHAGE
  
  If Saut = #True
;      t = ElapsedMilliseconds()
;     While ElapsedMilliseconds() < t + 2000 
;    MonSprite.CB\X = 0.5*MonSprite.CB\a * t * t + MonSprite.CB\v * t + MonSprite.CB\Xini
;    MonSprite.CB\y + 3
;     Wend
    Saut = #False
  
  EndIf  
    
    
  
  
;   TransparentSpriteColor(#CB1,$FF00FF)
  DisplayTransparentSprite(#CB1, MonSprite.CB\X, MonSprite.CB\Y)
  CheckFrontiere()
  
 
  
  Delay(1)
ForEver




Procedure CheckFrontiere()
  Shared MonSprite.CB\X, MonSprite.CB\Y, ySp, xSp
  Debug Str(Xsp) + " / " + Str(MonSprite.CB\X)
  With MonSprite.CB
    If \X >= xSP : \X  = xSP : EndIf
    If \X <= 0   : \X  = 0   : EndIf
    If \Y >= ySp : \Y  = ySp : EndIf
    If \Y <= 43  : \Y  = 43  : EndIf  
  EndWith
EndProcedure


Procedure CreaSprite()
  CreateSprite(#CB1, 64,69)
  StartDrawing(SpriteOutput(#CB1))
  Box(0,0,64,69,$0000FF)
  StopDrawing()
  
EndProcedure


Re: Aide pour algorithme saut de sprite...

Publié : lun. 15/août/2016 17:41
par falsam
Presse la touche fléche haute pour appliquer une impulsion.
Change la gravité pour voir se que ça donne.

Code : Tout sélectionner

EnableExplicit

;Quelques variables 
Global Event  
Global Image  
Global Ground
Global Ennemy
Global Ball, BallX = 100, BallY = 200
Global BallVelocityX.f = 1,  BallVelocityY.f = 0, BallGravityY.f = 2

;Initialisation diverses
If InitSprite()
  InitKeyboard()
  InitMouse()
EndIf
UsePNGImageDecoder()
UsePNGImageEncoder()

;Creation du screen
OpenWindow(0, 0, 0, 800, 600, "Jeux 1 - Saut", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600)

;Création et sauvegarde de l'image de référence pour la création des autres sprites
;Cette image est sauvegardée au format PNG afin de gérér la transparence. 
Image = CreateImage(#PB_Any, 8, 8, 24, RGB(255, 255, 255))
SaveImage(Image, "WhiteSquare.png", #PB_ImagePlugin_PNG)

;Creation du sol 
Ground = LoadSprite(#PB_Any, "WhiteSquare.png")
ZoomSprite(Ground,  800, 32)

;Création d'un obstacle
Ennemy = LoadSprite(#PB_Any, "WhiteSquare.png")
ZoomSprite(Ennemy,  32, 32)

;Creation de la ball
Ball = LoadSprite(#PB_Any, "WhiteSquare.png")
ZoomSprite(Ball, 32, 32)

;Boucle evenementielle
Repeat  
  Repeat
    Event = WindowEvent()
     
    Select Event    
      Case #PB_Event_CloseWindow
        End
    EndSelect  
  Until Event = 0 ;Plus d'évenement fenêtre
    
  FlipBuffers()
  ClearScreen(RGB(135, 206, 235))
  
  ;Adfichage des sprites
  DisplaySprite(Ground, 0, 570)  
  DisplaySprite(Ennemy, 384, 537)
  DisplaySprite(Ball, BallX, BallY)
  
  ;Evenement clavier : Touche Up => Impulsion vers le haut
  ExamineKeyboard()
  
  ;Pour pouvoir effectuer un saut la balle ne doit plus bouger
  If KeyboardReleased(#PB_Key_Up) And BallVelocityY = 0
    BallVelocityY = -30 ;La balle va monter
  EndIf
  
   ;Affichage de la balle  
  If BallVelocityY <> 0
    BallX + BallVelocityX ;Déplacement à droite
    RotateSprite(Ball, 2, #PB_Relative) ;Une petite rotation 
  EndIf

  ;La balle est en mouvement
  ;Elle va monter puis redescendre 
  BallVelocityY + BallGravityY 
  BallY + BallVelocityY
  
  ; C'est le moment de tester la collision de La balle avec un obstacle
  ; ici se sera le sol.
  If SpriteCollision(Ball, BallX, BallY+10, Ground, 0, 570)
    BallY = 537 ; Ajustement de la position Y de la balle
    BallVelocityY = 0 ;Interdiction de bouger 
    RotateSprite(Ball, 0, #PB_Absolute) ;Plus de rotation
  EndIf
  
  ;Collision avec l'ennemi
  If SpriteCollision(Ball, BallX, BallY+10, Ennemy, 384, 537)
    BallY = 505 ; Ajustement de la position Y de la balle
    BallVelocityY = 0 ;Interdiction de bouger 
    RotateSprite(Ball, 0, #PB_Absolute) ;Plus de rotation
  EndIf
  
Until KeyboardPushed(#PB_Key_Escape)

Re: Aide pour algorithme saut de sprite...

Publié : lun. 15/août/2016 17:50
par falsam
Modification du code précédent. j'ai diminué la velocité x de la balle pour tester la collision avec un ennemi.

Re: Aide pour algorithme saut de sprite...

Publié : lun. 15/août/2016 17:51
par Zorro
c'est le principe de l'elastic

tu as un Sprite qui va vers la droite (pour exemple )

son deplacement est donc positif son pas sera de (+2 )
elastic est egale a 0.66 par exemple

et a chaque fois que le sprite se déplace de 2 , toi tu retires l'elastic (pos_du_sprite=pos_du_sprite - Elastic )
elastic=elastic+0.66

et elastic lui deviens de plus en plus grand (il resiste de plus en plus), donc forcement a un moment ton sprite va repartir en arriere
car son déplacement (son pas ) n'est de de 2 , mais Elastic lui continu de grandir :)

la gravité, c'est un elastic Vertical :)
sauf que tu bloques la progression de Elastic pour ne pas avoir une descente plus grande que la montée :lol:
(genre Tex Avery )

Re: Aide pour algorithme saut de sprite...

Publié : lun. 15/août/2016 18:21
par majikeyric
cf. source PunchAnabalt : http://www.purebasic.fr/french/viewtopi ... =8&t=14792

En gros ça correspond à ce que Dobro a expliqué,

Quand tu sautes tu appliques une force : une vitesse Y négative à la coordonnée Y de ton objet.
à chaque balayage écran tu fais donc :

Code : Tout sélectionner

Y=Y+VitesseY
mais tu appliques aussi une autre force : une "gravité" positive qui va faire diminuer VitesseY.

Code : Tout sélectionner

VitesseY=VitesseY+Gravite
Petit à petit VitesseY va passer de négative à positive (->chute de l'objet).

Re: Aide pour algorithme saut de sprite...

Publié : lun. 15/août/2016 18:32
par Zorro
avec ton code :

Code : Tout sélectionner

; principe de l'elastic
; 
; on a un sprite en mouvement
; avec un pas de deplacement de 2 
; on a une gravité fixe 
; cette gravité on va l'additioner sans arret sur une variable, de sorte
; qu'elle devienne de plus en plus forte
; 
; et cette gravité augmenté on va influencer notre deplacement avec 
; le pas de deplacement de 2 va donc diminuer petit a petit, jusqu'a devenir inversé
; c'est le mouvement inverse
; 

If InitSprite() = 0 Or InitKeyboard() = 0
		MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire aux sprites !", 0)
		End
EndIf
Declare   CheckFrontiere()
Declare   CreaSprite()
Enumeration
		#win
		#CB1
EndEnumeration
#DROITE = 1
#GAUCHE = 2
#NOMOVE = 0
Structure CB
		X.i     ; Position X
		Xini.i  ; Position initial en X (repère pour pour saut)
		Y.i     ; Position Vertical
		dir.b   ; direction
		vd.b    ; vitesse droite
		vg.b     ; vitesse gauche
		a.f     ; accélération
		t.f     ; temps
		g.f     ; Gravite
		pg.f ; pas gravité
		pas.f;pas d'avancement
EndStructure
Global MonSprite.CB\X
Global MonSprite.CB\Y
Global MonSprite.CB\pas.f=2
Global MonSprite.CB\pg.f=0.095
Global DIR
Global ySp = 160 - 69 ; Frontière sol (bas)
Global xSP = 800 - 64 ; Frontière ecran (droite)
; Gestion du saut
; Global c = 100    ; Hauteur du saut max
; Global b = MonSprite.CB\X + 200 ; Distance x du saut
; Global a = MonSprite.CB\X
; positionFinale.x = MonSprite.CB\V * tempsApresLancer * Cos(angleDeLancer) + positionInitiale.x;
Macro CoW(champ,valeur)
		Global MonSprite.CB\champ = valeur
EndMacro
; INITIALISATION /////////
Cow(Y,ySp)
Cow(X,64)
Cow(Xini,64)
Cow(vd,3)
Cow(vg,-3)
Cow(g,9.6)
Cow(Dir,#Droite)
;////////////////////////
If OpenWindow(#win, 0, 0, 800, 160, "sprite jump", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		DIR = #NOMOVE
		If OpenWindowedScreen(WindowID(0), 0, 0, 800, 160)
				KeyboardMode(#PB_Keyboard_International)
				CreaSprite()
		Else
				MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
				End
		EndIf
EndIf
Repeat
		; Double repeat / event et 2D
		;
		Repeat
				Event = WindowEvent()
				Select Event
				Case #PB_Event_Gadget
						If EventGadget() = 0
								End
						EndIf
				Case #PB_Event_CloseWindow
						End
				EndSelect
		Until Event = 0
		; ***************** PARTIE 2D
		FlipBuffers()
		ClearScreen(RGB(0, 0, 0))
		ExamineKeyboard()
		; GAUCHE
		If KeyboardPushed(#PB_Key_Q)
				DIR = #GAUCHE
				LastDIR = #GAUCHE
				MonSprite.CB\X + MonSprite.CB\vg
				; DROITE
		ElseIf KeyboardPushed(#PB_Key_D) 
				DIR = #DROITE
				LastDIR = #DROITE
				MonSprite.CB\X + MonSprite.CB\vd
		EndIf 
		; SAUT
		If KeyboardPushed(#PB_Key_Space)
				Debug "hop"
				Saut = #True
		Else
				DIR = #NOMOVE
		EndIf
		; AFFICHAGE
		If Saut = #True
				MonSprite.CB\pas.f=MonSprite.CB\pas.f-MonSprite.CB\pg.f ; ici on on diminue le pas de deplacement avec notre gravité
				MonSprite.CB\y=MonSprite.CB\y-MonSprite.CB\pas.f ;ici c'est le deplacement standard , mais du coup avec un pas qui change
				if MonSprite.CB\y=YSP ; ça c'est le test du retour au sol
						MonSprite.CB\pas.f=2 ; on remet le pas a 2 (vitesse de deplacement )
						Saut = #False
				Endif
		EndIf 
		;   TransparentSpriteColor(#CB1,$FF00FF)
		DisplayTransparentSprite(#CB1, MonSprite.CB\X, MonSprite.CB\Y)
		CheckFrontiere()
		Delay(1)
ForEver

Procedure CheckFrontiere()
		Shared MonSprite.CB\X, MonSprite.CB\Y, ySp, xSp
		Debug Str(Xsp) + " / " + Str(MonSprite.CB\X)
		With MonSprite.CB
				If \X >= xSP : \X  = xSP : EndIf
				If \X <= 0   : \X  = 0   : EndIf
				If \Y >= ySp : \Y  = ySp : EndIf
				If \Y <= 43  : \Y  = 43  : EndIf 				
		EndWith
EndProcedure

Procedure CreaSprite()
		CreateSprite(#CB1, 64,69)
		StartDrawing(SpriteOutput(#CB1))
				Box(0,0,64,69,$0000FF)
		StopDrawing()
EndProcedure
;Epb

Re: Aide pour algorithme saut de sprite...

Publié : lun. 15/août/2016 18:45
par Ar-S
Merci les gars c'est nickel.

Re: [OK]Aide pour algorithme saut de sprite...

Publié : mar. 16/août/2016 10:01
par JohnJohnsonSHERMAN
Si tu veux vraiement être trés précis dans le saut de ton sprite, tu peux aussi utiliser la formule physique qui va bien :
Image
(le z(t) correspond à la coordonnée y)

Où :
  • g est la gravité (sur Terre : 9.82 environ)
  • Vo est la vitesse initiale de l'objet
  • a est l'angle de tir par rapport au sol
  • x et y les coordonnées de l'objet
En PB ca donne :

Code : Tout sélectionner

y = -(g/2*Vo*Vo*Cos(a)*Cos(a))*x*x + (Tan(a))*x
Le résultat est une courbe parabolique que l'objet décrit pendant son mouvement en chute libre (il n'y a plus d'impulsion aprés le départ).
Note : Le poid de l'objet n'entre pas en compte dans le cas d'un saut (chute libre).
Voila 8)

Re: [OK]Aide pour algorithme saut de sprite...

Publié : mar. 16/août/2016 12:29
par Zorro
cool :)

Re: [OK]Aide pour algorithme saut de sprite...

Publié : mar. 16/août/2016 15:48
par Ar-S
Merci pour la formule, j'avais vu cette explication mais la mise en pratique reste obscure.
Oui je suis un peu teubé dès que j'entre dans des mathématiques. (pourtant 16 au bacs ^^ à l'époque)

Re: [OK]Aide pour algorithme saut de sprite...

Publié : mar. 16/août/2016 18:21
par JohnJohnsonSHERMAN
La mise en pratique : Comme la formule calcule juste la position en Y du sprite en fonction de sa position en X, il suffit de remplacer X par la variable appropriée (ici MonSprite\X).
A propos, quand on cesse de presser une touche directionnelle, le sprite cesse son mouvement même s'il est en vol, alors qu'il devrait continuer jusqu'au point d'impact. Faudrait le faire continuer son déplacement quand Saut = #True.
intégrer ma formule dans ton code demande quelques calculs annexes, comme par exemple la vitesse initiale (a définir au début) ou l'angle (varie selon qu'on bouge ou qu'on est immobile), ce qui risque d'alourdir juste un peu le code, mais ca donne des déplacements plus réalistes (enfin si tout marche) 8)
Je vais faire quelques essais et je posterai peut etre un exemple si je suis content :P

Re: [OK]Aide pour algorithme saut de sprite...

Publié : mar. 16/août/2016 19:13
par falsam
JohnJohnsonSHERMAN a écrit :Je vais faire quelques essais et je posterai peut etre un exemple si je suis content
Tu as interet à le faire ton exemple de code avec ta formule ^^

Re: [OK]Aide pour algorithme saut de sprite...

Publié : mar. 16/août/2016 21:55
par Ar-S
@Falsam,
tu t'es trompé de "Quoteur" mon gars :twisted:

Re: [OK]Aide pour algorithme saut de sprite...

Publié : mar. 16/août/2016 22:07
par falsam
Non c'est un bug du script du forum quand on se trompe de bouton Citer. Et je n'ai pas fait attention au nom qui c'est affiché. C'est corrigé :oops: