Performance d'un jeu en 2D

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Anonyme

Message par Anonyme »

Dobro , ton code est simple et expose clairement le problème ( que je ne vois pas sous linux au passage :D )
j'ai essayer de mélanger mon code avec ( 1° page de ce post ) , toujours le même problème... pas fluide , des saccades tout les 250ms environs...

Pas top la syncro , a voir en FullScreen ce que ca donne...
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

beaucoup plus stable en full screen !! :D
(surtout debugger ON !! 8O )
normal, ya pas les event a gerer !! :D

c'est quand meme pas de l'Atari niveau stabilité !! :?

(touche ESCAPE pour quitter)



Structure sprite
    x.l
    y.l
    vitesse.l
EndStructure
nbr_sprite=1000
Dim sprite.sprite(nbr_sprite)

; Test
EcranX = GetSystemMetrics_ ( #SM_CXSCREEN )
EcranY = GetSystemMetrics_ ( #SM_CYSCREEN )
InitSprite (): InitKeyboard ()

;hwnd=OpenWindow(1,0,0,EcranX,EcranY,"test", #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget )
OpenScreen (EcranX,EcranY,32, "Test" )

; *********** prepare les parametres de chaque sprite *****************
For t=0 To nbr_sprite
    sprite(t)\x = Random (EcranX)+1
    sprite(t)\y= Random (EcranY)+1
    sprite(t)\vitesse= Random (4)+1
   CreateSprite (t, sprite(t)\vitesse, sprite(t)\vitesse)
     ; dessine le sprite
StartDrawing ( SpriteOutput (t))
     Box (0,0, sprite(t)\vitesse, sprite(t)\vitesse, RGB ( Random (100)+100, Random (100)+100, Random (100)+100))
StopDrawing ()

Next t
; ***************************************************************
Repeat
     
     For t= 0 To nbr_sprite
         DisplaySprite (t,sprite(t)\x,sprite(t)\y)
        
        sprite(t)\x=sprite(t)\x+sprite(t)\vitesse
         If sprite(t)\x>EcranX
            sprite(t)\x=0
         EndIf
        
     Next t
    
     FlipBuffers ( #PB_Screen_SmartSynchronization )
     ClearScreen (0)
     Delay (1) ;*
     ExamineKeyboard ()
     If KeyboardPushed ( #PB_Key_Escape )
         End
     EndIf
    
ForEver
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

Cpl.Bator a écrit :Dobro , ton code est simple et expose clairement le problème ( que je ne vois pas sous linux au passage :D )
j'ai essayer de mélanger mon code avec ( 1° page de ce post ) , toujours le même problème... pas fluide , des saccades tout les 250ms environs...

Pas top la syncro , a voir en FullScreen ce que ca donne...
Comme nous le rappelle si brillamment Dobro, FlipBuffers est d'une importance capitale. Alors conditionner l'affichage avec un ElapsedMilliseconds, c'est rajouter une couche de, heu, je sais pas quoi, mais bon tu vois.
Il me semble que Fred a amélioré la gestion de FlipBuffers, ce qui est joyeusement enthousiasment, mais nos certitudes acquise avant la 4.30 sont, heu, plus si certaine, hum.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

de memoire on avait quand meme pas autant d'instabilitée en V 3.94 !! :?
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

Dobro a écrit :beaucoup plus stable en full screen !! :D
(surtout debugger ON !! 8O )
en mode plein écran, quel outil utilise-tu pour voir si c'est stable ou pas ?
config de mon ordi: seven, directx11, Pentium(R) DualCore E5700, RadeonHD 4550 512MB, PureBasic 4.61 x86
Buckethead
Messages : 122
Inscription : jeu. 27/sept./2007 20:25

Message par Buckethead »

Dobro a écrit :normal que ça saccade !!

un delay() doit se mettre APRES un flipbuffer ! pas avant ! :)

si vous aviez fait du Stos basic, vous sauriez cela !!

parcequ'en Stos on manipulais directement le buffer de fond des sprites,
buffer video vu, et buffer video calculé ...

le flipbufer c'est un swap entre la memoire video calculé (celle ou se dessine le sprite) , et la memoire video affiché (celle qu'on vois..)

si tu met un delay() avant le swap, c'est normal qu'il y est une petite saccade
puisque tu empeche l'ecran d'apparaitre !! :)

met ton delay apres, tu verra :)
comme ça :

Code : Tout sélectionner


; Test
InitSprite()
hwnd=OpenWindow(1,0,0,800,600,"test", #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget  )
OpenWindowedScreen (hwnd,0,0,800,600,0,0,0)

Dim x(120) : Dim v(120)
For y = 0 To 120
    x(y) = Random(800) : v(y) = 1 + Random(4)
Next y

Repeat
    
    
    StartDrawing(ScreenOutput())
        For y = 0 To 120
            x(y) = x(y) + v(y)
            If x(y) > 800 : x(y) = 0 : EndIf
            c = 100 +v(y) * 25
            Box(x(y), 5*y, v(y), v(y) ,RGB(c,c,c))
        Next y
    StopDrawing()
    
    If WindowEvent() = #PB_Event_CloseWindow : End : EndIf
    
   
    
    FlipBuffers(1)
    ClearScreen(0)
     Delay(10) ;*
ForEver 

de plus logiquement on met le clearscreen après l'affichage
puisque après l'affichage on met un coup de balais sur l'écran pour préparer le prochain travail

beaucoup on tendance a commencer par nettoyer avant de dessiner
personnellement je trouve plus logique de balayer ma surface de travail a la fin du travail

parce que c'est pas très malin d'arriver au boulot et de commencer a passer le balais :lol:


autre chose !!

les sprites sont pas la pour faire jolis !!

là tu dessine des box directement a l'écran !!

tu a choisi la technique la plus lente qui soit !!

si tu avait fait des sprites , tu aurai pu voir la difference !! ;)
Ok, maintenant le Delay() est plus efficace, MERCI. Tout de fois mon exemple avec les BOX était pensé pour être un peu lourd, autrement j'aurais été même jusqu'à tout précalculer voir utiliser un autre API, revoir l'algo, et certain auraient utilisé de l'assembleur.
Allons.. Mon systeme est tout à fait capable d'afficher 120 BOX() fluide à 60 FPS, ce n'est rien comparé à ce que nous codons la pluspart du temps.
On peut optimiser ton exemple mais le but du truc c'est de voir si on peut obtenir une animation fluide en mode fenêtre avec un delay(), même juste un point qui scroll horizontalement. (et AUCUN exemples ici ne sont fluide! Le sprite() n'y change rien!!)

Un meilleur exemple serait de mélanger les sprites avec du GrabSprite() et autre pour être proche de la réalité des programmes.

Pour le moment, je ne suis pas convaincu par delay() pour les animations
fluide en mode fenêtré , et pour le fullscreen je l'ai moi même répété plusieurs fois, un petit delay(1) ne fait pas de mal.


Le problème de mon exemple n'est pas un problème d'optimisation mais de synchronisation.

On voit très bien que c'est ce type d'animation qui ne fait pas de cadeau, je me tue à le dire...

Je ne suis pas d'accord avec le Clearscreen(), car c'est la même chose.

Repeat
ClearScreen(0)
...
FlipBuffers(1)
ForEver


ou



Repeat
...
FlipBuffers(1)
ClearScreen(0)
ForEver
Dernière modification par Buckethead le dim. 22/mars/2009 12:31, modifié 6 fois.
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

Buckethead a écrit : Je ne suis pas d'accord avec le Clearscreen(), car c'est la même chose.

Repeat
ClearScreen(0)
...
FlipBuffers(1)
ForEver


ou



Repeat
...
FlipBuffers(1)
ClearScreen(0)
ForEver
oui, certes, c'est une question d'organisation, la recommandation de Dobro n'est toutefois pas inutile.
config de mon ordi: seven, directx11, Pentium(R) DualCore E5700, RadeonHD 4550 512MB, PureBasic 4.61 x86
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

C'est à vous de gérer le temps dans un jeu, voir cet article, notamment le chapitre 'Gestion du temps'

Utiliser un delay() sans gérer un cycle n'a pas de sens.

http://www.gnurou.org/writing/linuxmag/sdl/partie3

Enfin bon , tout ça vous le saviez déjà :)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Buckethead
Messages : 122
Inscription : jeu. 27/sept./2007 20:25

Message par Buckethead »

Perso, je préfère effacer l'écran juste àprès le repeat, je ne vois pas le problème d'organisation.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Buckethead a écrit :Perso, je préfère effacer l'écran juste àprès le repeat, je ne vois pas le problème d'organisation.
tu fais bien comme tu veux !!

faudrait pas confondre de débat !

d'ailleurs beaucoup font comme toi :)

c'est pas le problème !

simplement de mon point de vue, je trouve mieux organisé de mettre
le nettoyage d'écran a la fin du travail , plutôt qu'au début

ma logique est ainsi faite, je code comme je vis , et si je me rase, c'est parce que j'ai des poils !! :)

et non pas parce que je me rase que j'ai des poils !! :D

je nettoie mon écran parce qu'il y a quelque chose dessus
et non pas , je met quelque chose dessus parce que mon écran est propre


évidement si tu ne saisi pas la nuance de ceci, tu ne peut me comprendre ..

mais cela peut révéler aussi de futur problèmes de mise au point de tes codes , si tu pense a l'envers ...

car un code s'exécute de haut en bas !!

mais cela n'est que mon avis hein , n'y vois rien d'agressif :)

comtois a écrit :C'est à vous de gérer le temps dans un jeu, voir cet article, notamment le chapitre 'Gestion du temps'
ton article est intéressant, cependant c'est pas le problème que nous démontrons !!

en effet le problème ici c'est que quoique tu fasse mode fenêtré ou pas
il n'y a pas de stabilité a partir du moment ou l'on code des sprites qui se déplacent , on aperçois le hachage due aux interruptions intempestif de windows !!

a croire que depuis la version 4.30

nos programme ne sont pas capable de réserver du temps machine de façon régulière !!

il me semble qu'en V3.94 on avait pas ce problème

essaye le dernier code coloré et regarde bien le déplacement des étoiles
il n'es pas toujours très régulier !!

c'est encore plus évident sur mon petit NC10 !! :)
Dernière modification par Backup le dim. 22/mars/2009 12:47, modifié 3 fois.
Buckethead
Messages : 122
Inscription : jeu. 27/sept./2007 20:25

Message par Buckethead »

C'est comme dire à un gaucher qu'il code à l'envers, dans la routine la permutation entre les 2 instructions sont identiques:

ClearScreen(0)
code
FlipBuffers(1)
ClearScreen(0)
code
FlipBuffers(1)
ClearScreen(0)
code
FlipBuffers(1)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Buckethead a écrit :C'est comme dire à un gaucher qu'il code à l'envers, dans la routine la permutation entre les 2 instructions sont identiques:

ClearScreen(0)
code
FlipBuffers(1)
ClearScreen(0)
code
FlipBuffers(1)
ClearScreen(0)
code
FlipBuffers(1)
bon laisse tomber ...
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Donc, en résumé, le code de Comtois:
-----------------------------------------------

- Prend 2% de CPU chez Beauregard;
- En mode fenêtré (non optimisé)
- A 60 Hz (sous XP) ou plus (sous Linux)
- N'étouffe pas XP (Delay(1) )

>> Fiabilité et fluidité sont réunis. Sujet clos pour pour moi ! ! !

Au passage, je vois que Beauregard ne comprend pas pourquoi Cpl.Bator utilise le chrono., etc...
... PARCE QUE LINUX VA TROP VITE !!!!

Bande de travail Linux : 1000 Hz
Bande de travail XP : 60 Hz

Avec une telle liberté sous Linux, il vaut mieux en effet mettre un chrono...
Anonyme

Message par Anonyme »

Dobro a écrit :
Buckethead a écrit :C'est comme dire à un gaucher qu'il code à l'envers, dans la routine la permutation entre les 2 instructions sont identiques:

ClearScreen(0)
code
FlipBuffers(1)
ClearScreen(0)
code

FlipBuffers(1)
ClearScreen(0)
code
FlipBuffers(1)
bon laisse tomber ...
@Buckethead , les instructions sont effectué dans le même ordre , ca n'a pas d'importance , juste une manière de faire.
Buckethead
Messages : 122
Inscription : jeu. 27/sept./2007 20:25

Message par Buckethead »

Je comprend bien, mais il y a aussi un interet a effacer juste après le repeat: si on a predessiné des trucs avant le repeat, on épargne 1 instruction clearscreen
Répondre