Comment éviter de perturber un timer?

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Torp
Messages : 360
Inscription : lun. 22/nov./2004 13:05

Comment éviter de perturber un timer?

Message par Torp »

Salut,

Je m'explique. J'ai intégrer dans mon prog un timer qui gère le temps imparti aux joueurs. A chaque déclenchement du timer le temps restant s'affiche. Le problème est que les déplacements de la souris (ou tout autre action) semble ralentir le timer, ou plutot on dirait qu'il fait des sauts pour rattraper le temps perdu..

Il y a t'il une solution pour rendre un timer imperturbable... :? ?

Merci
Torp
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

tu doit surement utiliser un "WaitWindowEvent() "

utilise un "WindowEvent()" suivi d'un delay(2) et tu aura un meilleurs
rendu , je pense ! :)
Torp
Messages : 360
Inscription : lun. 22/nov./2004 13:05

Message par Torp »

Ben c'est ce que j'ai. Ca parait un peu mieux mais c'est pas encore ca. C'est pas vraiment linéaire comme pourrait l'etre... euh... un chrono. Si je bouge la souris rapidement (voir frénétiquement :lol:) j'arrive casiement a le stoppper que ce soit avec un WaitWindowEvent() ou un WindowEvent() avec delay(20). Il doit y avoir une solution car si tu prends en exemple la "pendule" de Windows, tu as beau bouger la souris comme un bourrin elle est IMPERTURBABLE, comme...euh...un chrono...:lol:..
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

T'aurais pas un petit code pour mettre en évidence?
Torp
Messages : 360
Inscription : lun. 22/nov./2004 13:05

Message par Torp »

ouep bouge pas je prépare ca...
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

Un timer renvoie un évènement donc il est inutile de passer par un windowevent()

après, tout dépend comment tui gère ton chrono. moi, j'ai jamais eu de problème.

si tu passes par une procedure

SetTimer(Windowid(), 0, 1000, @procedure())

la procedure est exécuté dans un thread différent donc pas de souci

sinon, avec ceci
SetTimer(WindowID(), 0, 1000, 0)

il faut récupérer l'évènement WM_Timer

Tu fais comment ?


petite précision, dans un jeux openscreen, on a le flipbuffer qui attend la synchronisation avec l'écran pour basculer

cela signifie que si ton fps est de 85 HZ (fps max sur un écran 85hz), tu ne peux pas être plus précis que 1/85 de secondes

et si ton FPS est plus bas, la précision est encore moindre
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Torp
Messages : 360
Inscription : lun. 22/nov./2004 13:05

Message par Torp »

Je colle un lien car il y a 2 images avec...
Le code est un peu long pour un exemple mais c'est parceque c'est un extrait de mon prog original (j'ai juste gardé ce qu'il fallait pour illustrer)
Il faut changer le C:\Temp\ dans le code, par le chemin où l'archive sera décompressée....
ouais je sais c'est pas simple :oops:

Pour illuster l'exemple, lorsque tu verras les chiffres défiler, gardes le bouton de la souris enfoncé et bouge un peu la souris.... le défilement se bloque...

Il y a les 2 codes. WaitWindowEvent et WindowEvent.

http://www.penguinbyte.com/apps/pbwebst ... /Timer.zip
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

Dans le fichier avec WindowEvent, essaie de mettre:

Code : Tout sélectionner

  Select WindowEvent()
    Case 0
      Delay(20)
  EndSelect
juste avant le "Forever"
Torp
Messages : 360
Inscription : lun. 22/nov./2004 13:05

Message par Torp »

En fait mon prog original c'est l'autre (le WaitWindowEvent). Il marche d'ailleurs mieux que celui avec WindowEvent, mais le compteur ne défile pas de facon linéaire, meme si c'est moins perceptible...
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

En fait, il y a déjà un problème au niveau de la gestion de la touche Escape.

Normalement, comme tu utilises un WindowedScreen(), tu ne devrais même pas avoir besoin d'utiliser la boucle des évènements.

D'ailleurs, elle ne te sers que pour capter la touche Escape qui ferme le programme.

Essaye ça à la place:

Code : Tout sélectionner

  ;+++++++++++++++++++++++++++++++++++++++
  FlipBuffers(0)
  
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Escape)
    End
  EndIf
  
  While WindowEvent():Wend
  Delay(1)
ForEver
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

bon, ben voilà, ça marche

Code : Tout sélectionner

; +-------------------------------------------------------------------
; PURE ARNAQUE
; par Torp
; Pure Basic 3.92
; +-------------------------------------------------------------------
; OpenConsole()
; +-------------------------------------------------------------------
;- Declaration des constantes
; +-------------------------------------------------------------------
#Plateau = 1
#Cpt1 = 32 : #CptX = 7 : #CptY = 384
#Sprite = 2 : #TxtCpt = 0
; +-------------------------------------------------------------------
;- Declarations des Variables et affectations des valeurs
; +-------------------------------------------------------------------
Declare Timer()
Declare Sablier(hwnd.l, uMsg.l, idEvent.l, dwTime.l)
Global AffCpt.b, Ro.w, Ve.w, Bl.w, ValCpt.b
AffCpt = #False
PosJoueur2 = 0 : Ro = 255 : Ve = 255 : Bl = 0
Installation$ = "C:\Temp\"
LoadFont(#TxtCpt, "arial", 16) : UseFont(#TxtCpt)

; +-------------------------------------------------------------------
;- Initialisation de ecran du jeu
; +-------------------------------------------------------------------
If InitSprite() = 0 Or InitSound() = 0
  MessageRequester("Erreur", "Impossible d'initialiser DirectX", 0)
  End
EndIf

If OpenWindow(0, 0, 0, 800, 600, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_TitleBar, "Le jarnac") = 0
  MessageRequester("Erreur", "Impossible d'afficher l'écran principal", 0)
  End
EndIf

If OpenWindowedScreen(WindowID(), 0, 0, 800, 600, 0, 0, 0) = 0
  MessageRequester("Erreur", "Impossible d'afficher l'écran principal", 0)
  End
EndIf

; +-------------------------------------------------------------------
;- Structures et listes chainees et tableaux
; +-------------------------------------------------------------------

; +-------------------------------------------------------------------
;- Chargement des Sprites
; +-------------------------------------------------------------------
UsePNGImageDecoder()
LoadSprite(#Cpt1, "Cpt1.png")
LoadSprite(#Plateau, "Plateau.png")

; +-------------------------------------------------------------------
;- Premier Tirage de Lettres
; +-------------------------------------------------------------------
Timer()
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

; +-------------------------------------------------------------------
;- Programme principal
; +-------------------------------------------------------------------

CreateSprite(#Sprite, 40, 19)

Repeat
  
  ; +++++++++++++++++++++++++++++++++++++++
  
  Select WaitWindowEvent()
      
    Case #WM_KEYDOWN
      
      key.b = EventwParam()
      
      If key = 27 : End : EndIf
      
    Case #WM_TIMER
      Select EventwParam() ; Recupere le N° du Timer
        Case 1 ; Timer N°1
          ValCpt + 1
        
          DisplaySprite(#Cpt1, #CptX, #CptY)
          StartDrawing(ScreenOutput())
            DrawingFont(UseFont(#TxtCpt))
            DrawingMode(1)
            FrontColor(Ro, Ve, Bl)
            Locate(#CptX + 20, #CptY + 12)
            DrawText(Str(ValCpt))
          StopDrawing()
          
          FlipBuffers(0)
          
        Case 2 ; Timer N°2
          KillTimer_(WindowID(0), 1) ; Destruction du Timer N°1
          KillTimer_(WindowID(0), 2) ; Destruction du Timer N°2
          AffCpt = #False : ValCpt = 0
          Timer()
      EndSelect
      
  EndSelect
  
ForEver

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


; +-------------------------------------------------------------------
;- Mise en route des Timers
; +-------------------------------------------------------------------
Procedure Timer()
  Timer1 = SetTimer_(WindowID(0), 1, 1000, 0)
  Timer2 = SetTimer_(WindowID(0), 2, 21000, 0)
EndProcedure
exactement le problème cité ci dessus, le flibuffers qui ralentit le programme, et comme il est dans la boucle de lecture des évènement, on les lit au ralentit
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

essaie ça.
mieux vaut ne pas attacher un timer à une fenêtre : ça crée des décalages selon l'"occupation" de celle-ci.
Et crée deux procédures distinctes pour les deux timers.
De plus, pour changement immédiat et pas d'interruption d'affichage, il faut mettre les displaysprites dans la boucle de la fenêtre et dans la procédure

Code : Tout sélectionner

;+-------------------------------------------------------------------
;PURE ARNAQUE
;par Torp
;Pure Basic 3.92
;+-------------------------------------------------------------------
;OpenConsole()
;+-------------------------------------------------------------------
;-Declaration des constantes
;+-------------------------------------------------------------------
#Plateau=1
#Cpt1=32:#CptX=7:#CptY=384
#Sprite=2:#TxtCpt=0
;+-------------------------------------------------------------------
;-Declarations des Variables et affectations des valeurs
;+-------------------------------------------------------------------
Declare Timer()
Declare Sablier()      
Global AffCpt.b,Ro.w,Ve.w,Bl.w,ValCpt.b
AffCpt=#False
PosJoueur2=0:Ro=255:Ve=255:Bl=0
Installation$="d:\téléchargements\timer\"
LoadFont(#TxtCpt,"arial",16):UseFont(#TxtCpt)

;+-------------------------------------------------------------------
;-Initialisation de ecran du jeu
;+-------------------------------------------------------------------
If InitMouse()=0 Or InitSprite()=0 Or InitKeyboard()=0 Or InitSound()=0
  MessageRequester("Erreur","Impossible d'initialiser DirectX",0)
  End
EndIf

If OpenWindow(0,0,0,800,600,#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered|#PB_Window_TitleBar,"Le jarnac")=0
  MessageRequester("Erreur","Impossible d'afficher l'écran principal",0)
  End
EndIf

If OpenWindowedScreen(WindowID(),0,0,800,600,0,0,0)=0
  MessageRequester("Erreur","Impossible d'afficher l'écran principal",0)
  End
EndIf

;+-------------------------------------------------------------------
;-Structures et listes chainees et tableaux
;+-------------------------------------------------------------------

;+-------------------------------------------------------------------
;-Chargement des Sprites
;+-------------------------------------------------------------------
UsePNGImageDecoder() 
LoadSprite(#Cpt1,Installation$+"Cpt1.png")
LoadSprite(#Plateau,Installation$+"Plateau.png")

;+-------------------------------------------------------------------
;-Premier Tirage de Lettres
;+-------------------------------------------------------------------
  Timer()
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;+-------------------------------------------------------------------
;-Programme principal
;+-------------------------------------------------------------------
          Repeat

            DisplaySprite(#Plateau,0,0)
            DisplaySprite(#Cpt1,#CptX,#CptY)
            CreateSprite(#Sprite, 40, 19)
            StartDrawing(SpriteOutput(#Sprite))
            DrawingFont(UseFont(#TxtCpt))
            DrawingMode(1)
            FrontColor(Ro,Ve,Bl)
            DrawText(Str(ValCpt))
            StopDrawing()
            DisplayTransparentSprite(#Sprite,#CptX+25+PosJoueur2,#CptY+12)
                      
            ;++++++Affichage des compteurs
            
            
            
            ;+++++++++++++++++++++++++++++++++++++++
            
            Select WaitWindowEvent()

              Case #WM_KEYDOWN 
                          
                key.b = EventwParam()
      
                If key = 27:End:EndIf

            EndSelect
            
            FlipBuffers(0)
            
          ForEver

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


;+-------------------------------------------------------------------
;-Mise en route des Timers
;+-------------------------------------------------------------------
Procedure Timer()
Timer1=SetTimer_(0,0, 1000, @Sablier())
;Timer2=SetTimer_(WindowID(0), 2, 21000, @Sablier())
EndProcedure

;+-------------------------------------------------------------------
;-Tache a effectuer par le declenchement des Timers
;+-------------------------------------------------------------------
Procedure Sablier()
  ValCpt+1
  DisplaySprite(#Cpt1,#CptX,#CptY)
  CreateSprite(#Sprite, 40, 19)
  StartDrawing(SpriteOutput(#Sprite))
  DrawingFont(UseFont(#TxtCpt))
  DrawingMode(1)
  FrontColor(Ro,Ve,Bl)
  DrawText(Str(ValCpt))
  StopDrawing()
  DisplayTransparentSprite(#Sprite,#CptX+25+PosJoueur2,#CptY+12)
EndProcedure
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

une autre solution qui marche également

Code : Tout sélectionner

; +-------------------------------------------------------------------
; PURE ARNAQUE
; par Torp
; Pure Basic 3.92
; +-------------------------------------------------------------------
; OpenConsole()
; +-------------------------------------------------------------------
;- Declaration des constantes
; +-------------------------------------------------------------------
#Plateau = 1
#Cpt1 = 32 : #CptX = 7 : #CptY = 384
#Sprite = 2 : #TxtCpt = 0
; +-------------------------------------------------------------------
;- Declarations des Variables et affectations des valeurs
; +-------------------------------------------------------------------
Declare Timer()
Declare Sablier(hwnd.l, uMsg.l, idEvent.l, dwTime.l)
Global AffCpt.b, Ro.w, Ve.w, Bl.w, ValCpt.b
AffCpt = #False
PosJoueur2 = 0 : Ro = 255 : Ve = 255 : Bl = 0
Installation$ = "C:\Temp\"
LoadFont(#TxtCpt, "arial", 16) : UseFont(#TxtCpt)

; +-------------------------------------------------------------------
;- Initialisation de ecran du jeu
; +-------------------------------------------------------------------
If InitMouse() = 0 Or InitSprite() = 0 Or InitKeyboard() = 0 Or InitSound() = 0
  MessageRequester("Erreur", "Impossible d'initialiser DirectX", 0)
  End
EndIf

If OpenWindow(0, 0, 0, 800, 600, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_TitleBar, "Le jarnac") = 0
  MessageRequester("Erreur", "Impossible d'afficher l'écran principal", 0)
  End
EndIf

If OpenWindowedScreen(WindowID(), 0, 0, 800, 600, 0, 0, 0) = 0
  MessageRequester("Erreur", "Impossible d'afficher l'écran principal", 0)
  End
EndIf

; +-------------------------------------------------------------------
;- Structures et listes chainees et tableaux
; +-------------------------------------------------------------------

; +-------------------------------------------------------------------
;- Chargement des Sprites
; +-------------------------------------------------------------------
UsePNGImageDecoder()
LoadSprite(#Cpt1, Installation$ + "Cpt1.png")
LoadSprite(#Plateau, Installation$ + "Plateau.png")

; +-------------------------------------------------------------------
;- Premier Tirage de Lettres
; +-------------------------------------------------------------------
Timer()
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

; +-------------------------------------------------------------------
;- Programme principal
; +-------------------------------------------------------------------
Repeat
  
  DisplaySprite(#Plateau, 0, 0)
  
  
  ; ++++++Affichage des compteurs
  
  If AffCpt = #True
    
    DisplaySprite(#Cpt1, #CptX, #CptY)
    CreateSprite(#Sprite, 40, 19)
    StartDrawing(SpriteOutput(#Sprite))
      DrawingFont(UseFont(#TxtCpt))
      DrawingMode(1)
      FrontColor(Ro, Ve, Bl)
      DrawText(Str(ValCpt))
    StopDrawing()
    DisplayTransparentSprite(#Sprite, #CptX + 25 + PosJoueur2, #CptY + 12)
    
  EndIf
  
  ; +++++++++++++++++++++++++++++++++++++++
  
  Repeat
    Event = WindowEvent()
    Select Event
      Case #WM_KEYDOWN
        
        key.b = EventwParam()
        
        If key = 27 : End : EndIf
        
    EndSelect
  Until Event = 0
  
  FlipBuffers(0)
  
ForEver

; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


; +-------------------------------------------------------------------
;- Mise en route des Timers
; +-------------------------------------------------------------------
Procedure Timer()
  Timer1 = SetTimer_(WindowID(0), 1, 1000, @Sablier())
  Timer2 = SetTimer_(WindowID(0), 2, 21000, @Sablier())
EndProcedure

; +-------------------------------------------------------------------
;- Tache a effectuer par le declenchement des Timers
; +-------------------------------------------------------------------
Procedure Sablier(hWnd, uMsg, idEvent, dwTime)
  Select uMsg
    Case #WM_TIMER
      Select idEvent ; Recupere le N° du Timer
        Case 1 ; Timer N°1
          ValCpt + 1
          AffCpt = #True
        Case 2 ; Timer N°2
          KillTimer_(WindowID(0), 1) ; Destruction du Timer N°1
          KillTimer_(WindowID(0), 2) ; Destruction du Timer N°2
          AffCpt = #False : ValCpt = 0
          Timer()
      EndSelect
  EndSelect
EndProcedure

par contre, évite de metre un sprite qui est crée à chaque tour de la boucle principale, voir code du message précédent
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

C'est bien pour ça que les timers sont gérés par une procédure, il n'y a pas d'évenements fenêtre à récupérer puisque le WindowedScreen() couvre la totalité de la fenêtre, donc, il est inutile de faire une boucle d'évènement.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

oui, enfin, on peut gérer le bouton fermer de windows par la boucle d'évènement, c'est plus pratique que de faire echap
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Répondre