Saccades du sprite

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
killer7
Messages : 18
Inscription : ven. 06/févr./2004 16:24
Contact :

Saccades du sprite

Message par killer7 »

bonjour,

J'aimerais comprendre pourquoi lors d'un déplacement mon sprite saccade.

Exemple : le joueur sur un Space Invaders Like (ou même les aliens).

Existe-t-il une solution pour que tout celà devienne fluide ?
Merci d'avance ! :wink:
Patrick88
Messages : 1564
Inscription : mer. 21/janv./2004 18:24

Message par Patrick88 »

tu nous montres le bout de code qui chiotte, afin que l'on puisse t'aider...

t'as mis le flipbuffer() ?

patrick
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Essaye ça

Code : Tout sélectionner

;Danilo - Forum Anglais 

;- procedures 
Procedure InitGameTimer() 
  Shared _GT_DevCaps.TIMECAPS 
  timeGetDevCaps_(_GT_DevCaps,SizeOf(TIMECAPS)) 
  timeBeginPeriod_(_GT_DevCaps\wPeriodMin) 
EndProcedure 

Procedure StopGameTimer() 
  Shared _GT_DevCaps.TIMECAPS 
  timeEndPeriod_(_GT_DevCaps\wPeriodMin) 
EndProcedure 


;- variables 
Global player1_move.f, player1_x.f, player1_y.f 

;- _program start 
;- _Init 
If InitSprite()=0 Or InitKeyboard()=0 
  MessageRequester("ERROR","Cant init DirectX !",#MB_ICONERROR):End 
EndIf 

If OpenScreen(800,600,32,"Timing")=0 
  If OpenScreen(800,600,24,"Timing")=0 
    If OpenScreen(800,600,16,"Timing")=0 
      MessageRequester("ERROR","Cant open screen !",#MB_ICONERROR):End 
EndIf:EndIf:EndIf 

If CreateSprite(1,32,32)=0 
  CloseScreen() 
  MessageRequester("ERROR","Cant create sprite !",#MB_ICONERROR):End 
Else 
  StartDrawing(SpriteOutput(1)) 
    Box (0,0,32,32,$00FFFF) 
    Line(0,0,32,32,$000000) 
    Line(32,0,0,32,$000000) 
  StopDrawing() 
EndIf 

player1_speed.f = 0.50 

; timer initialisieren 
InitGameTimer() 
StartTime = TimeGetTime_()
;StartTime = GetTickCount_()
time      = StartTime 

SetFrameRate(75) 

;- _game loop 
Repeat 
  ; calculate multiplicator 
  multiplicator.f = StartTime 
  StartTime = TimeGetTime_() 
  ;StartTime = GetTickCount_()   
  multiplicator   = StartTime - multiplicator 

  ; calc framerate 
  If TimeGetTime_()-time >= 1000 
  ;If GetTickCount_()-time >= 1000   
    time   = TimeGetTime_() 
    ;time   = GetTickCount_() 
    FPS    = Frames-1 
    Frames = 1 
  Else 
    Frames+1 
  EndIf 

  ClearScreen(0,0,0) 

  ; show framerate 
  StartDrawing(ScreenOutput()) 
    DrawingMode(1):FrontColor($80,$FF,$00) 
    Locate(50,50):DrawText("FrameRate: "+Str(FPS)) 
  StopDrawing() 

  ExamineKeyboard() 
  
  ; calc move-step for player1 
  player1_move = player1_speed * multiplicator 
  
  If KeyboardPushed(#PB_Key_Left) 
    player1_x - player1_move : EndIf 
  If KeyboardPushed(#PB_Key_Right) 
    player1_x + player1_move : EndIf 
  If KeyboardPushed(#PB_Key_Up) 
    player1_y - player1_move : EndIf 
  If KeyboardPushed(#PB_Key_Down) 
    player1_y + player1_move : EndIf 

  If player1_x < -32 : player1_x = 800 : EndIf 
  If player1_x > 800 : player1_x = -32 : EndIf 
  If player1_y < -32 : player1_y = 600 : EndIf 
  If player1_y > 600 : player1_y = -32 : EndIf 

  DisplaySprite(1,player1_x,player1_y) 

  FlipBuffers() 
Until KeyboardPushed(#PB_Key_Escape) 

;- _program end 
StopGameTimer()
killer7
Messages : 18
Inscription : ven. 06/févr./2004 16:24
Contact :

Message par killer7 »

Patrick88>>
Oui, j'ai bien mis Flipbuffer() à la fin de la boucle principale.
Je précise que c'est un mode fenêtré 640x480.

Comtois >>
Merci vais essayer de mettre un Timer de ce genre, c'est vrai que j'aurais du y penser.

M'en vais tester tout ça !!!
killer7
Messages : 18
Inscription : ven. 06/févr./2004 16:24
Contact :

Message par killer7 »

J'ai essayé, rien à faire ça saccade (encore plus lol).
Compiles et testes ton exemple, celà saccade aussi.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

chez moi , ça ne saccade pas .
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

Je viens d'essayer le code : Aucune saccade chez moi !!

Chris :)
Invité

Message par Invité »

Bah j'ai bien des tâches qui tournent en arrière plan, mais de là à monopoliser l'AMD 2200+, je sais pas.
P'tet ça alors. :?: :?: :?:
Vais tout couper et retester tout ça.

Merci de vos réponses rapides en tout cas. :wink:
killer7
Messages : 18
Inscription : ven. 06/févr./2004 16:24
Contact :

Message par killer7 »

Rien à faire j'ai toujours des petits acoups !
... vais tout reprendre depuis le début.

Petite question :
Comment les spécialistes de ce Forum feraient pour structurer le joueur, les aliens, etc ... par rapport à ce code source ?
Une structure pour le joueur, aliens, etc ...

http://darkprograms.hmt-forum.com/viewtopic.php?t=126

Question vachement important pour les débutants comme moi et d'autres !

Merci d'avance !
killer7
Messages : 18
Inscription : ven. 06/févr./2004 16:24
Contact :

Message par killer7 »

Bon, j'ai réussi à structurer tout ça.
Par contre je bloque un peu sur comment afficher les lignes de vaisseaux aliens, par la boucle For en se servant de la structure (vaisseaux aliens)

Comment préparer les lignes puis les afficher à l'écran ???
killer7
Messages : 18
Inscription : ven. 06/févr./2004 16:24
Contact :

Message par killer7 »

Finalement j'ai procédé ainsi :

Voici les 1ères parties importantes de la conversion du lien en code source utilisant des structures et des procédures, je trouve que c'est plus propre. Ce tutorial http://purebasic.hypervox.co.uk/ m'a bien aidé puisque j'ai utilisé des parties du code proposé, j'ai ensuite ajouté la partie des aliens.

Code : Tout sélectionner

; etc ...

#NUM_INVADERS = 50
Global player_1.Player
Global invaders_1.Invaders
Global spacex, spacey

; etc ...

Structure Player
  x.w       ;position du joueur - x
  y.w       ;position du joueur - y
  width.w   ;largeur du sprite
  height.w  ;hauteur du sprite
  speed.f   ;vitesse du joueur
  fps.w     ;frames par secondes du joueur
  frameno.w ;numéro courant du frame
  frames.Frame[3] ;array of frames to animate
EndStructure

Structure Invaders
  x.w       ;position des aliens - x
  y.w       ;position des aliens - y
  width.w   ;largeur du sprite
  height.w  ;hauteur du sprite
  speed.f   ;vitesse des aliens
  fps.w     ;frames par secondes des aliens
  frameno.w ;numéro courant du frame
  frames.Frame[3] ;array of frames to animate
EndStructure

; etc ...

Dim aliens.Invaders(#NUM_INVADERS)

;etc ...

; ////////////////////////////////////////////////////////////////////////////////////////
Procedure InitPlayer()
  ;
  ; Load player variable
  ;
  ; load sprite and set player's initial x,y and speed
  result = LoadSprite(#player1,"fighter2.bmp",0)
    
  If result = 0
    MessageRequester("b","Problème de chargement des sprites !!!",0)
  EndIf

  player_1\speed = 2 ; 1 / 0.50 / 0.30
  player_1\width = 60
  player_1\height = 60
  player_1\x = (#SCREEN_WIDTH - player_1\width) /2
  player_1\y = 520

  ; now load the frame data (note: not the bitmap, just the cordinates
  startpointx = 0
  startpointy = 0
  
  For x = 0 To 2
    player_1\frames[x]\x1 = startpointx
    player_1\frames[x]\y1 = startpointy
    player_1\frames[x]\x2 = startpointx + 60
    player_1\frames[x]\y2 = startpointy
    startpointx = startpointx + 60

    
  Next
  player_1\frameno = 0
EndProcedure
; ////////////////////////////////////////////////////////////////////////////////////////


; ////////////////////////////////////////////////////////////////////////////////////////
Procedure AnimatePlayer()
  ;
  ; Animate the player
  ; Clip the sprite
  ;  
  CurrFrame = player_1\frameno
  ClipSprite(#player1, player_1\frames[CurrFrame]\x1, player_1\frames[CurrFrame]\y1, player_1\width ,player_1\height)
  DisplayTransparentSprite(#player1,player_1\x,player_1\y)
  CurrFrame = CurrFrame + 1
  If CurrFrame > 2
    CurrFrame = 0
  EndIf
  player_1\frameno = CurrFrame
EndProcedure
; ////////////////////////////////////////////////////////////////////////////////////////


; ////////////////////////////////////////////////////////////////////////////////////////
Procedure InitInvaders()
  ;
  ; Load invaders variable
  ;
  ; load sprite and set invader's initial x,y and speed
  result = LoadSprite(#invaders1,"invaders1.bmp",0)
    
  If result = 0
    MessageRequester("b","Problème de chargement des sprites !!!",0)
  EndIf 

  invaders_1\speed  = 1 
  invaders_1\width  = 37
  invaders_1\height = 25

  For x = 0 To #NUM_INVADERS - 1
     spacex = spacex + 60
     aliens(x)\x = aliens(x)\x + spacex
     aliens(x)\y = aliens(x)\y + spacey
     If spacex > 550
        spacex = 0
        spacey = spacey + 40
     EndIf
  Next x
EndProcedure
; ////////////////////////////////////////////////////////////////////////////////////////


; ////////////////////////////////////////////////////////////////////////////////////////
Procedure AnimateInvaders()
  ;
  ; Animate invaders
  ; Clip the sprite
  ;  
  For i = 0 To #NUM_INVADERS - 1
  DisplayTransparentSprite(#invaders1,aliens(i)\x,aliens(i)\y)
  Next i
  
  ; mouvement des vaisseaux à définir ...
  
EndProcedure
; ////////////////////////////////////////////////////////////////////////////////////////
voilou, si vous avez des sugestions d'amélioration pour tout ça, merci d'avance.

sinon, encore une petite question : comment centrer mes colonnes de vaisseaux à l'écran par rapport à x ???

Ps: p'tain je me suis fait un monologue. :P
Enfin voilà si celà peux aider quelqu'un tant mieux.

Le code source : http://darkprograms.hmt-forum.com/viewtopic.php?t=126 me semblait très intéressant à structurer de façon procédurale.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

killer7 a écrit : sinon, encore une petite question : comment centrer mes colonnes de vaisseaux à l'écran par rapport à x ???
Ben pour ça tu as besoin de connaitre le nombre de colonnes , et la largeur de ton écran

Code : Tout sélectionner

;Définition des constantes
#LargeurEcran = 800
#NbColonnesVaisseaux = 3
#NbLignesVaisseaux = 4 
#NUM_INVADERS = #NbColonnesVaisseaux * #NbLignesVaisseaux

;et plus loin dans ton InitInvader()
Procedure InitInvaders() 
;pour calculer la position de chaque colonne 
;tu as juste à faire 
EspaceEntreColonne = #LArgeurEcran  / (NbColonnesVaisseaux + 1)
EspaceEntreLigne = 40
for a = 1 to #NbColonnesVaisseaux
   for b = 1 to #NbLignesVaisseaux
      aliens(x)\x = a * EspaceEntreColonne 
      aliens(x)\y = b * EspaceEntreLigne
      x + 1
   next b
next a
bon ,c'est une autre façon de faire, à chacun son goût :)

par contre avec ce système colonne , ligne , ça peut te permettre de faire des figures avec tes aliens avec des datas par exemples , ou un fichier texte

ça donnerait un truc du genre

data.l 1,1,1,1,1,1,1
data.l 0,1,1,1,1,1,0
data.l 0,0,1,1,1,0,0
data.l 0,0,0,1,0,0,0

tu as juste à lire les datas , si c'est un 1 tu places un alien , sinon rien
killer7
Messages : 18
Inscription : ven. 06/févr./2004 16:24
Contact :

Message par killer7 »

Merci bien Comtois ! :wink:
C'est vrai que la méthode est très intéressante, et ouvre pas mal de possibilités au niveaux de l'affichage des vaisseaux.
Je me pencherais en détails sur la Data.

Autre question :
Par rapport à mon dernier source affiché, comment faire pour que mes vaisseaux lorsqu'ils touchent le bord de l'écran (exemple à droite), descendent d'une ligne et repartent en sens inverse ?

Détecter la collision et enchainer sur la suite en gros : 1 ligne plus bas + sens inverse.

Merci d'avance !

Je tenais quand même à spécifier que je suis ici depuis peu et je suis très étonné de la rapidité de réponse et de la convivialité.
Bravo à tous !
On progresse à grands pas sur ce type de Forum.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

dans ta Structure Invaders , tu ajoutes un paramètre

Code : Tout sélectionner

Sens.b ; déplacement vers la droite = 1 , déplacement vers la gauche = -1
ensuite dans ta Procedure InitInvaders()
tu initialises ainsi

Code : Tout sélectionner

aliens(X)\Sens = 1 ; pour un déplacement vers la droite
puis dans ta procédure AnimateInvaders()
tu ajoutes le test de collision avec les bords de l'écran

Code : Tout sélectionner

  For i = 0 To #NUM_INVADERS - 1 
    ; Test de la collision ( le test sera différent selon que tu centres ton sprite ou non par rapport à aliens(i)\x ) 
    ; à toi d'adapter , dans ce cas , je considère que le sprite n'est pas centré 
    If aliens(i)\X + aliens(i)\width > #LargeurEcran Or aliens(i)\X < 0
      aliens(i)\Sens * -1 ; on inverse le sens de déplacement de l'alien
      aliens(i)\Y + 1 ; et on ajoute une ligne 
    EndIf
    DisplayTransparentSprite(#invaders1,aliens(i)\X+aliens(i)\Sens,aliens(i)\Y) 
  Next i  

Bon ça c'est juste pour te donner une idée , mais en fait , je crois que dans ce type de jeu , c'est toute la Ligne qui change de Sens ?
ça signifie qu'il faudrait le traiter non pas pour chaque alien , mais par ligne
en gros , tu as besoin de connaitre par Ligne le premier alien à gauche et le premier à droite ?
faudrait que je rejoue à ce jeu pour me souvenir du principe :) ou alors va falloir que tu précises un peu mieux le comportement que tu souhaites
Avatar de l’utilisateur
cederavic
Messages : 1338
Inscription : lun. 09/févr./2004 23:38
Localisation : Bordeaux

Message par cederavic »

j'ai commencer a lire, mais j'ai pas fini lol
si tu fait une version windows, je te conseil vivement de prendre la libray spriteex et de metre un waitvbl (voir forum suggestions...) ça evite entre autre les "demi saccade" (une moitier de la fenetre decaler par rapport a l'autre)
Répondre