Page 1 sur 2

Synchro ? Bug ? Probleme de clignotement

Publié : jeu. 25/mai/2006 16:12
par Thyphoon
j'ai un problème de clignotement de mon image dans le jeu que je suis en train de programmé. Et je comprends pas bien d'ou ça vient.
J'ai simplifié au maximum le programme pour vous faire la demonstration.
Je me demande si ce n'est pas un pb de FlipBuffer() ou de clearscreen()...
Mais c'est tres currieux.
A votre avis ?

Code : Tout sélectionner

If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0
  MessageRequester("Error","DirectX 7+ is needed.",0)
EndIf
OpenScreen(800, 600, 32, "Aliens")
CreateSprite(0,288,217)
StartDrawing(SpriteOutput(0))
Global Address=DrawingBuffer() 
Global Pitch=DrawingBufferPitch()
Global PixelFormat=DrawingBufferPixelFormat()
StopDrawing()

Procedure DrawLine(x1,y1,x2,y2,col) 
x=x1:y=y1:D=0 
hx=x2-x1 
hy=y2-y1 
xinc=1:yinc=1 



If hx<0 
xinc=-1:hx=-hx 
EndIf 

If hy<0 
yinc=-1:hy=-hy 
EndIf 

If hy<=hx 
c=2*hx:m=2*hy 
L1: 
;col=col(Int(x*255/320))
If x>0 And x<288 And y>0 And y<217
PokeL(Address+x*4+Pitch*y,col)
EndIf
If x=x2:Goto BR1:EndIf 
x=x+xinc 
d=d+m 
If d>hx : y=y+yinc : d=d-c : EndIf 
Goto L1 
BR1: 
Else 

c=2*hy:m=2*hx 

L2: 
;col=col(Int(x*255/320))
If x>0 And x<288 And y>0 And y<217
PokeL(Address+x*4+Pitch*y,col)
EndIf

If y=y2 : Goto BR2 : EndIf 

y=y+yinc 
d=d+m 

If d>hy : x=x+xinc : d=d-c : EndIf 
Goto L2 
BR2: 
EndIf 
EndProcedure 

Procedure ArcCircle(x,y,angle1,angle2,Rayon,col)
      Xo=0:
      Yo=0:
     
      For a=angle1 To angle2 Step 10
        Xp = x + Rayon * Cos(a*2*3.1415/360) 
        Yp = y + Rayon * Sin(a*2*3.1415/360)
        If (Xo>0 Or Yo>0) 
          DrawLine(Xo,Yo,Xp,Yp,col)
        EndIf  
          Xo=Xp
          Yo=Yp 
      Next
EndProcedure

Macro DMLine(a,rd,rf)
   If a >360:a=a-360:EndIf
   If a<0:a=a+360:EndIf
   Xa = 144 + rd * Cos(a*2*3.1415/360) 
   Ya = 217+ rd * Sin(a*2*3.1415/360)
   Xb = 144 + rf * Cos(a*2*3.1415/360) 
   Yb = 217 + rf * Sin(a*2*3.1415/360)
  DrawLine(Xa,Ya,Xb,Yb,RGB(0,255,0))
EndMacro

Procedure UscmDraw()
  Static Time.l=0
  Static Rayon.l=0
  Static A.l
  UscmWidth=144
  UscmHeight=217
  UscmSpeed=40; pixel par second
  UscmRayMax=Sqr(Pow(Int(288/2),2)+Pow(217,2))
  ;A=A+1
  If A>360:A=0:EndIf
  ;UseBuffer(#DM)
  ;ClearScreen(0)
  ArcCircle(144,217,180,360,190,RGB(0,255,0))
  Angle1=A-20
  Angle2=A+20
  ;ArcCircle(144,217,Angle1,Angle2,180,RGB(0,255,0))
  Angle1=A-50
  Angle2=A-20
  ;ArcCircle(144,217,Angle1,Angle2,120,RGB(0,255,0))
  Angle1=A+20
  Angle2=A+50
  ;ArcCircle(144,217,Angle1,Angle2,120,RGB(0,255,0))
  ArcCircle(144,217,180,360,110,RGB(0,255,0))
 
  DMLine(A,90,200)
  DMLine(A+90,90,200)
  DMLine(A+180,90,200)
  DMLine(A+270,90,200)
  
  DMLine(A+45,110,200)
  DMLine(A+315,110,200)
  DMLine(A+135,110,200)
  DMLine(A+225,110,200)
  
  If Time=0:Time=ElapsedMilliseconds():EndIf 
  t.l=(ElapsedMilliseconds()-Time)
  Time=ElapsedMilliseconds()
  ;ArcCircle(144,217,180,360,Rayon,RGB(0,255,0))
  Rayon=Rayon+(UscmSpeed*t/100)
  If Rayon>UscmRayMax:Rayon=0:EndIf

EndProcedure


Repeat
 ExamineMouse() 
 ExamineKeyboard()
 UseBuffer(0)
 ClearScreen(RGB(100,100,100))
 
 UscmDraw()
 UseBuffer(-1)
 ClearScreen(0)
 DisplaySprite(0,0,0)
 FlipBuffers()

  Until KeyboardPushed(#PB_Key_Escape)
End 

Publié : jeu. 25/mai/2006 17:31
par Anonyme

Code : Tout sélectionner

Repeat 
 ExamineMouse() 
 ExamineKeyboard() 
 
 ;UseBuffer(0) 
 ClearScreen(RGB(100,100,100)) 
  
 UscmDraw() 
 ;UseBuffer(-1) 
 ;ClearScreen(0) 
 DisplaySprite(0,0,0) 
 
 
 
 
 FlipBuffers() 

  Until KeyboardPushed(#PB_Key_Escape) 
End 
Avec cette boucle, l'écran ne clignote plus.

@++

Publié : jeu. 25/mai/2006 17:45
par Thyphoon
Cpl.Bator a écrit :

Code : Tout sélectionner

Repeat 
 ExamineMouse() 
 ExamineKeyboard() 
 
 ;UseBuffer(0) 
 ClearScreen(RGB(100,100,100)) 
  
 UscmDraw() 
 ;UseBuffer(-1) 
 ;ClearScreen(0) 
 DisplaySprite(0,0,0) 
 
 
 
 
 FlipBuffers() 

  Until KeyboardPushed(#PB_Key_Escape) 
End 
Avec cette boucle, l'écran ne clignote plus.

@++
Merci Cpl.Bator, je suis arrivé a la même conclusion que toi. Le problème c'est que normalement tout cela est animé et si je ne fais pas un effacement du sprite avant de tracer ça laisse des traces...
Je me demande si dans certain cas la fonction ClearScreen ne serait pas buggé.
Y a t'il pas moyen d'effacer rapidement un sprite sans passer par la commande clearscreen ?

Publié : jeu. 25/mai/2006 18:48
par Thyphoon
apparement c'est un problème connu, j'ai trouvé ça sur le forum anglais :

Code : Tout sélectionner

http://www.purebasic.fr/english/viewtopic.php?t=9597&highlight=replace+clearscreen
ils sugèrent de remplacer le clearscreen par

Code : Tout sélectionner

StartDrawing(ScreenOutput()) 
Box (0,0,1204,768,0) 
StopDrawing()
Mais bon la commande StartDrawing est gourmande en temps CPU donc si quelqu'un a une autre proposition. :wink: [/quote]

Publié : jeu. 25/mai/2006 18:55
par djes
Perso j'affiche un bon gros sprite noir de la taille de l'écran.

Publié : jeu. 25/mai/2006 19:10
par Thyphoon
djes a écrit :Perso j'affiche un bon gros sprite noir de la taille de l'écran.
A oui c'est pas bête.

N'y a t' il pas moyen en connaissant l'adresse mémoire du sprite ainsi que la largeur et la hauteur de le remplir de zero tres tres rapidement ? (sans passé par les APIs si possible ?)

Publié : jeu. 25/mai/2006 19:47
par Thyphoon
J'ai remarqué quelques choses FlipBuffers() joue un role dans ce problème.
Avec un FlipBuffer(1) si je suis a plus de 50 im/sec par de problème de sintillement. Si parcontre le jeu est trop gourmant et qu'on tombe en dessous alors là ça sintille a fond.
Avec FlipBuffer(0) ou FlipBuffer(2) alors ça sintille tout le temps...

Comment faire pour ne pas avoir de sintillement si on est a 20 ou 30 im/sec (mon jeu demande pas mal de ressource)

Publié : jeu. 25/mai/2006 21:44
par djes
J'utilise flipbuffer(1).
As-tu fixé le frame rate avec setrefreshrate?

Publié : ven. 26/mai/2006 8:32
par Thyphoon
djes a écrit :J'utilise flipbuffer(1).
As-tu fixé le frame rate avec setrefreshrate?
J'ai essayé mais ça ne me donne rien de plus.
Je ne comprend pas le fonctionnement de FlipBuffer.
Je m'explique...POur moi FlipBuffer permutte 2 images (celle a l'écran et celle en buffer) Maintenant le programme n'utilisant pas de thread pour dessiner l'image en buffer même si le flip se fait pas synchro avec l'ecran l'image est toujours entierrement dessiné...or apparament ce n'est pas le cas...Je comprends pas.... :mad:
que le FPS tombe ne devrait pas faire clignoter l'image mais simplement donner une animation plus sacadé non ?
voici un nouveau code qui montre le problème sans avoir un pb de FPS...pourquoi ce clignotement ?

Code : Tout sélectionner

If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0
  MessageRequester("Error","DirectX 7+ is needed.",0)
EndIf
OpenScreen(800, 600, 32, "Aliens")
CreateSprite(0,288,217)
StartDrawing(SpriteOutput(0))
Global Address=DrawingBuffer() 
Global Pitch=DrawingBufferPitch()
Global PixelFormat=DrawingBufferPixelFormat()
StopDrawing()

Procedure DrawLine(x1,y1,x2,y2,col) 
x=x1:y=y1:D=0 
hx=x2-x1 
hy=y2-y1 
xinc=1:yinc=1 



If hx<0 
xinc=-1:hx=-hx 
EndIf 

If hy<0 
yinc=-1:hy=-hy 
EndIf 

If hy<=hx 
c=2*hx:m=2*hy 
L1: 
;col=col(Int(x*255/320))
If x>0 And x<288 And y>0 And y<217
PokeL(Address+x*4+Pitch*y,col)
EndIf
If x=x2:Goto BR1:EndIf 
x=x+xinc 
d=d+m 
If d>hx : y=y+yinc : d=d-c : EndIf 
Goto L1 
BR1: 
Else 

c=2*hy:m=2*hx 

L2: 
;col=col(Int(x*255/320))
If x>0 And x<288 And y>0 And y<217
PokeL(Address+x*4+Pitch*y,col)
EndIf

If y=y2 : Goto BR2 : EndIf 

y=y+yinc 
d=d+m 

If d>hy : x=x+xinc : d=d-c : EndIf 
Goto L2 
BR2: 
EndIf 
EndProcedure 

Procedure ArcCircle(x,y,angle1,angle2,Rayon,col)
      Xo=0:
      Yo=0:
     
      For a=angle1 To angle2 Step 10
        Xp = x + Rayon * Cos(a*2*3.1415/360) 
        Yp = y + Rayon * Sin(a*2*3.1415/360)
        If (Xo>0 Or Yo>0) 
          DrawLine(Xo,Yo,Xp,Yp,col)
        EndIf  
          Xo=Xp
          Yo=Yp 
      Next
EndProcedure

Macro DMLine(a,rd,rf)
   If a >360:a=a-360:EndIf
   If a<0:a=a+360:EndIf
   Xa = 144 + rd * Cos(a*2*3.1415/360) 
   Ya = 217+ rd * Sin(a*2*3.1415/360)
   Xb = 144 + rf * Cos(a*2*3.1415/360) 
   Yb = 217 + rf * Sin(a*2*3.1415/360)
  DrawLine(Xa,Ya,Xb,Yb,RGB(0,255,0))
EndMacro

Procedure UscmDraw()
  Static Time.l=0
  Static Timeb.l=0
  Static Rayon.l=0
  Static A.f
  UscmWidth=144
  UscmHeight=217
  UscmSpeed=40; pixel par second
  UscmRayMax=Sqr(Pow(Int(288/2),2)+Pow(217,2))
  ;A=A+1
  If ElapsedMilliseconds()>Timeb
    A=A+0.005
    Timeb=ElapsedMilliseconds()+10
  EndIf
  If A>360:A=0:EndIf
  ;UseBuffer(#DM)
  ;ClearScreen(0)
  ArcCircle(144,217,180,360,190,RGB(0,255,0))
  Angle1=A-20
  Angle2=A+20
  ;ArcCircle(144,217,Angle1,Angle2,180,RGB(0,255,0))
  Angle1=A-50
  Angle2=A-20
  ;ArcCircle(144,217,Angle1,Angle2,120,RGB(0,255,0))
  Angle1=A+20
  Angle2=A+50
  ;ArcCircle(144,217,Angle1,Angle2,120,RGB(0,255,0))
  ArcCircle(144,217,180,360,110,RGB(0,255,0))
 
  DMLine(A,90,200)
  DMLine(A+90,90,200)
  DMLine(A+180,90,200)
  DMLine(A+270,90,200)
  
  DMLine(A+45,110,200)
  DMLine(A+315,110,200)
  DMLine(A+135,110,200)
  DMLine(A+225,110,200)
  
  If Time=0:Time=ElapsedMilliseconds():EndIf 
  t.l=(ElapsedMilliseconds()-Time)
  Time=ElapsedMilliseconds()
  ;ArcCircle(144,217,180,360,Rayon,RGB(0,255,0))
  Rayon=Rayon+(UscmSpeed*t/100)
  
  If Rayon>UscmRayMax:Rayon=0:EndIf

EndProcedure


Repeat
 ExamineMouse() 
 ExamineKeyboard()
 UseBuffer(0)
 ClearScreen(RGB(100,100,100))
 
 UscmDraw()
 UseBuffer(-1)
 ClearScreen(0)
 DisplaySprite(0,0,0)
 FlipBuffers(0)

  Until KeyboardPushed(#PB_Key_Escape)
End 

Publié : ven. 26/mai/2006 11:01
par djes
Le problème vient du sprite. Il est en mémoire vidéo. Apparemment, les écritures dans cette mémoire sont dans un timing différé, ce qui pose des problèmes de rafraichissement. Essaye de mettre

Code : Tout sélectionner

CreateSprite(0,288,217,#PB_Sprite_Memory)
et là ça marche.

Publié : ven. 26/mai/2006 11:38
par Thyphoon
djes a écrit :Le problème vient du sprite. Il est en mémoire vidéo. Apparemment, les écritures dans cette mémoire sont dans un timing différé, ce qui pose des problèmes de rafraichissement. Essaye de mettre

Code : Tout sélectionner

CreateSprite(0,288,217,#PB_Sprite_Memory)
et là ça marche.
ça c'est une reponse interessante. J'ai testé avec le code "exemple" que j'ai donné et c'est vrai que ça marche.
Je viens de testé avec le code de mon jeu qui est beaucoup plus lourd...Et ça rrange un peu les choses mais ça clignote toujours un peu même si moins qu'avant et surtout je passe de 30 FPS a 3FPS....Gloups !!!!

C'est pas encore gagné... :(
Faut 'il mieux mettre toute les sprites de mon jeu en #PB_Sprite_Memory ou bien y a t'il un moyen de quand même utilisé les sprites en mémoire Video ?
Autres Question lorsqu'on fait un StartDrawing(Screenoutput())
C'est dans la mémoire video ou dans la mémoire classique ?

Publié : ven. 26/mai/2006 12:22
par djes
Non, seulement les sprites que tu traites directement avec le processeur. Dans tous les cas, il vaut mieux faire appel aux fonctions graphiques de l'api (directx ou opengl) qui utilisent l'accélération de la carte graphique. Même au niveau d'un simple plot je pense que ça vaut le coup. (faudrait faire des tests :) )

J'ai déjà demandé plusieurs fois à Fred comment il faisait son flip. Apparemment, il se base sur les fonctions de directx. Et on ne peut pas dire que directx soit un modèle de transparence! Au final on arrive à ce qu'on veut mais faut bidouiller un peu pour "découvrir" la bonne façon de procéder. C'est ça le closed source.

Publié : ven. 26/mai/2006 14:35
par Thyphoon
djes a écrit :Non, seulement les sprites que tu traites directement avec le processeur. Dans tous les cas, il vaut mieux faire appel aux fonctions graphiques de l'api (directx ou opengl) qui utilisent l'accélération de la carte graphique. Même au niveau d'un simple plot je pense que ça vaut le coup. (faudrait faire des tests :) )

J'ai déjà demandé plusieurs fois à Fred comment il faisait son flip. Apparemment, il se base sur les fonctions de directx. Et on ne peut pas dire que directx soit un modèle de transparence! Au final on arrive à ce qu'on veut mais faut bidouiller un peu pour "découvrir" la bonne façon de procéder. C'est ça le closed source.
Je ne suis pas fan de DirectX non plus. Je suis pour la portabilité. Mais Fred a du utiliser autre chose que DirectX pour la version Linux et MacOsX...ça voudrait donc peut être dire que le problème que j'ai n'existerais pas sur ces 2 autres platformes...????

En tout cas un PokeL est sur ma machine 30 fois plus rapide qu'un plot.
et un PokeL est legerement plus rapide que l'utilisation des pointeurs.
Et cela que ça soit en mémoire Normal ou Video... Enfin d'apres les tests que j'avais fait. Je vais peut ête envoyé un email a Fred(il y a un email pour le support) Je sais pas si il me repondra...mais je pense que c'est un problème important, si des qu'on a des projets un peu important en 2D on est confronté a un problème de clignotement. non ?
Qu'en pensez vous ?

Publié : ven. 26/mai/2006 14:58
par djes
Pour le plot, je ne pensais pas à la fonction intégrée dans pure, qui est très lente, mais à des listes. Faudrait que je retrouve ça.

Publié : ven. 26/mai/2006 15:10
par Thyphoon
djes a écrit :Pour le plot, je ne pensais pas à la fonction intégrée dans pure, qui est très lente, mais à des listes. Faudrait que je retrouve ça.
si tu retrouves ça m'interresse :P