Performance d'un jeu en 2D

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Norswap
Messages : 11
Inscription : sam. 14/mars/2009 13:35

Performance d'un jeu en 2D

Message par Norswap »

Youpie, c'est encore moi.
J'ai donc codé un super petit jeu avec une sprite qui bouge. Seulement quand le jeu est lancé mon usage CPU monte à 55% (contre 10-15% avant), ce que je trouve quand même conséquent.

De plus j'ai comparé avec un jeu équivalent en C# (aussi une sprite qui bouge, un tuto que j'avais commencé) et là, le jeu fait seulement monter l'usage CPU à 20% !

Limiter le framerate via SetFrameRate() ne change pas grand chose (quelque % de gagnés tout au plus, si c'est bien du à cela, ce qui n'est pas sûr).

Alors, est-ce normal ou est-ce que je m'y suis très mal pris ? J'ai utilisé un loop infini comme on fait souvent en jeu vidéo. Voici la partie de mon code qui gère l'affichage :

Code : Tout sélectionner

Repeat
  FlipBuffers()
  ClearScreen(RGB(0, 0, 0))
  ExamineKeyboard()
  
  If WindowEvent() = #PB_Event_Menu And EventMenu() = 2 : Goto Menu : EndIf
  If WindowEvent() = #PB_Event_CloseWindow : End : EndIf 
  
  If KeyboardPushed(#PB_Key_Up)     : y - speed : EndIf
  If KeyboardPushed(#PB_Key_Down)   : y + speed : EndIf
  If KeyboardPushed(#PB_Key_Left)   : x - speed : EndIf
  If KeyboardPushed(#PB_Key_Right)  : x + speed : EndIf
  
  If x > WindowWidth(0) - size  : x = WindowWidth(0) - size   : EndIf
  If y > WindowHeight(0) - size : y = WindowHeight(0) - size  : EndIf
  If x < 0 : x = 0 : EndIf
  If y < 0 : y = 0 : EndIf
  
  Start3D() : ZoomSprite3D(0, size, size) : DisplaySprite3D(0, x, y) : Stop3D()
ForEver
De plus j'utilise une sprite3D pour gérer la transparence.

C'est grave docteur ?
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Message par Huitbit »

Bonjour,

Il est d'usage de rajouter un petit delay (delay(1) ou plus pour "rendre" la main au système) dans la boucle principale et comme par magie l'usage du CPU tombe à pic !

N'hésite pas à nous faire profiter de tes créations ! :wink:

Hasta la vista !
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ps : on dit UN sprite !

la regle en français, c'est de privilégier le masculin, lorsqu'on ne sait pas ..

:)
beauregard
Messages : 1307
Inscription : dim. 08/juil./2007 18:32
Localisation : Toulouse

Message par beauregard »

Dobro a écrit :ps : on dit UN sprite !

la regle en français, c'est de privilégier le masculin, lorsqu'on ne sait pas ..

:)
je n'ai plus accès au moniteur CPU, c'est moi ou spécifique à la version 4.30 ?
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ben le moniteur CPU fonctionne bien avec japbe et la v 4.30 :)
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

@Norswap

Ce code plus bas fonctionne bien et mange peu de ressources CPU. Comme dit HuitBit, il y a la fonction Delay() à rajouter, par contre, moi je mets 16ms, car des fois ça joue des tours de mettre moins (sous XP). Rien qu'insérer la commande Delay(16) dans ton code source le met au poil concernant les ressources CPU.

Il y a aussi le plein écran (c'est le cas de ce code). En effet, si tu veux maintenir des ressources CPU au maximum, il vaut mieux laisser le GPU jouer son rôle, notamment si tu as beaucoup de sprites.

Bonne continuation.

(touche Echap pour quitter)

Code : Tout sélectionner

;****************************************
; On prépare tout le fourbil nécessaire
;****************************************
Define WinWidth.I
Define WinHeight.I
Define WinDepth.I
InitSprite()
InitSprite3D()
InitKeyboard()
ExamineDesktops()
WinWidth = DesktopWidth(0)
WinHeight = DesktopHeight(0)
WinDepth = DesktopDepth(0)
OpenScreen(WinWidth, WinHeight, WinDepth, "")

Size = 50
CreateSprite(0, size, size, #PB_Sprite_Texture)
StartDrawing(SpriteOutput(0) )
Box(0, 0, size, size, #Red)
speed = 1
StopDrawing()
CreateSprite3D(0, 0)


Define Event.I
Define xMin.I = speed
Define yMin.I = speed
Define xMax.I = WinWidth - Size - speed
Define yMax.I = WinHeight - Size - speed
Define CoulFond.I = RGB(0, 0, 0)
Define Tempo.I
; Boucle principale


Repeat
   Delay(16)
   FlipBuffers()
   ClearScreen(CoulFond)
   Start3D()
      ZoomSprite3D(0, size, size)
      DisplaySprite3D(0, x, y)
   Stop3D()   
   ExamineKeyboard()   
   If KeyboardPushed(#PB_Key_Up)
      If y > yMin
         y - speed
      EndIf
   ElseIf KeyboardPushed(#PB_Key_Down)
      If y < yMax
         y + speed
      EndIf
   EndIf
   If KeyboardPushed(#PB_Key_Left)
      If x > xMin
         x - speed
      EndIf
   ElseIf KeyboardPushed(#PB_Key_Right)
      If x < xMax
         x + speed
      EndIf
   EndIf
 
   If KeyboardPushed(#PB_Key_Escape) : End: EndIf 
ForEver
Norswap
Messages : 11
Inscription : sam. 14/mars/2009 13:35

Message par Norswap »

Le Delay(16) aide effectivement a diminuer l'usage cpu, mais l'image est moins fluide, tandis qu'à 1 l'impact est minimal sur l'usage cpu. En fait 8 est un assez bon compromis je trouve.

Sinon je préfère rester en fenêtré pour le moment, le jeu étant censé être quelque chose d'assez réduit. En plus, c'est plus facile pour tester :)
beauregard a écrit :je n'ai plus accès au moniteur CPU, c'est moi ou spécifique à la version 4.30 ?
Tu peux aussi utiliser le moniteur de performances de Windows (avec ctrl+alt+delete) qui a l'avantage de moins oscillier.
Dobro a écrit :ps : on dit UN sprite !

la regle en français, c'est de privilégier le masculin, lorsqu'on ne sait pas ..

:)
Ca sonne moins bien pourtant, je pense que je vais persévérer dans mon vice ^^
Anonyme

Message par Anonyme »

Oulalala , les solutions proposé pour les jeux ne sont pas super :D
d'un pc à un autre , la vitesse change ( proc différent , +/- de ram , CG plus ou moins performante , etc...)

le mieux c'est de basé sa boucle d'affichage sur un timer défini ( une sorte de bloquage du FPS ) , 40 Frames par secondes , voir 35 suffit largement à avoir une application fluide , cela ne sert à rien d'encombrer le pc d'instructions imperceptible pour nous.

De plus , si l'on met 35 itérations par secondes pour l'affichage , le reste du temps DOIT être alloué au algo divers de d'applications ( IA , PATHFINDING,etc...)


voila un snippet décrivant mes dires :

Code : Tout sélectionner

OpenConsole()

FPS_LIMIT = 40


Repeat
		
		If (ElapsedMilliseconds() > CheckTime + 1000 / FPS_LIMIT)
				CheckTime = ElapsedMilliseconds()


				/*AFFICHAGE ICI*/
							
				
				Else
				Delay(1)
		EndIf
		
		
				/* ALGORITHME , ROUTINES DIVERSES , ICI */
		
		
ForEver 
Norswap
Messages : 11
Inscription : sam. 14/mars/2009 13:35

Message par Norswap »

Intéressant, je me demandais juste comment cela se comparait avec la méthode SetFrameRate(). Intuitivement je pense qu'elle limite juste l'affichage, mais les instructions sont tout de même exécutées, c'est juste ?
Anonyme

Message par Anonyme »

oui , l'instruction ne rend pas la main à l'os ou à tes routines d'algo.
tu perds des frames pour rien avec cette instruction.

Ton Delay( 8 ) n'est valable que sur ton pc , ou un autre avec une config similaire.
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Message par Huitbit »

Merci Caporal :D !
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Cpl a écrit :Oulalala , les solutions proposé pour les jeux ne sont pas super
Ah ben bien sûr! Et comme par hasard le seul abruti à avoir posté un code d'exemple qui marche complètement, ben c'est moi!!

Ah ben tu m'en taille une veste!!!

Je répondais seulement au message "Eh! C# vous nique!!! Hihihi! Z'avez pas mieux?"
J'interprète bien évidemment. Mais il fallait bien pondre un minimum de code pour répondre à ça!

Pour infos, si je dois faire un jeu, je ne mets pas tout de suite le chrono indispensable (ce que tu précises) à une bonne compatibilité. Je fais D'ABORD mon petit jeu, et ensuite je lui fourre une tempo.

Pourquoi? Parce que si ça plante, j'aurai un paramètre en moins à vérifier. Et ça ne plante pas qu'une fois... D'une part. Et d'autre part, un timer peut s'implanter de diverses manières.

Et la manière la plus dingue est souvent la meilleure!!!! C'est-à-dire que, parfois ça n'est pas plus méchant de laisser certaines séquences s'exécuter un peu "follement" tant que le déroulement général du jeu se produit d'une manière assez analogue sur toutes les bécanes. Aussi, un Delay(16) sur XP est assez stable sur x bécanes quelque soit la config..

La réponse au pourquoi se trahit ici dans le différentiel minimum entre deux valeurs retournées par ElapsedMilliseconds(). Pour Linux, je n'en sais rien. Logiquement, ça ne devrait pas être loin non plus.

Code : Tout sélectionner

   Define Ref.I
   Define Ctrl.I
   Define Gaspillage.I
   Ref = ElapsedMilliseconds()
   Gaspillage = 0
   Repeat
      Delay(1)
      Ctrl = ElapsedMilliseconds()
      Gaspillage + 1
   Until Ctrl > Ref
   Debug "Qté de boucles effectuées : " + Str(Gaspillage)
   Debug "Différentiel (en ms) = " + Str(Ctrl - Ref)
Je crois bien que tu as un différentiel de 16ms (+ ou - 1 ms) qui s'affiche? Pourtant, je ne lui ai aucunement précisé cette valeur!

Si je devais faire un jeu, je ne réfléchirais pas en FPS mais en cycles logiciels pour permettre à l'OS de gérer le reste. Un jeu doit prendre maximum 2 cycles par boucles (FPS = env. 30), sinon il est à chier au niveau ergonomie.

On démarre avec un Delay(16) (2 cycles) dans la boucle principale. Si, par chance, le jeu peut se finaliser ainsi, ça n'est que du bonheur (FPS optimum). Le Delay est réduit à 1. Et poum, on a soit un jeu très rapide, et donc fluide (1 cycles), soit un jeu hyper relax en ressources CPU (Delay laissé à 16 = 2 cycles). Sinon, 2 "Delay(1)"s sont à répartir dans la boucle principale. S'il est impossible à gérer, alors il faut tabler les infos recueillies (externaliser les calculs lourds) où éviter de compliquer le jeu plus que ça. Car si on insiste, et c'est valable pour tout type de compilateur, il y a tôt ou tard un plantage. User du 3ème cycle (FPS = env. 20ms), c'est voir le jeu ingérable dans certaines circonstances que l'OS peut être amené à imposer temporairement.

Et c'est idem pour les applications.

Ollivier
Dernière modification par Ollivier le dim. 15/mars/2009 18:03, modifié 1 fois.
cha0s
Messages : 681
Inscription : sam. 05/mars/2005 16:09

Message par cha0s »

est ce réellement utile d'économiser le CPU pour un jeu ? a pars peut être pour le debugage !
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

@ChaOs

Ce que j'ai écrit est donc une connerie?

Ollivier
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Message par Huitbit »

@cha0s
est ce réellement utile d'économiser le CPU pour un jeu ?
C'est toujours désagréable d'entendre le ventilateur tourner pour un pong :? !

Hasta la vista !
Répondre