Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2124 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  consommation 80% du cpu - D'où ca vient ?

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

consommation 80% du cpu - D'où ca vient ?

n°2131629
beuted
Posté le 15-03-2012 à 17:50:09  profilanswer
 

Bonjour à tous,
Je me lance dans le C++ et la bibliothèque sdl pour essayer de coder un truc très simple pour l'instant : un personnage qui se balade sur un terrain vue de 3/4.  :ange:  
J'en suis à l’étape où mon personnage "glisse" (pas d'animation de marche pour l'instant) sur le terrain.
Et j'ai un problème que j'aimerais régler avant d'aller plus loin un consommation de 80% du cpu lors de l’exécution... Je trouve ca un peu excessif, dites moi si je me tompe. (d'un autre coté je viens de remarquer que firefox en utilise 64%)
Voici le code (je suis ouverts à tout conseil/remarque/insulte) :
 

Code :
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <iostream>
  4. #include <SDL/SDL.h>        //bibli de base de SDL
  5. #include <SDL/SDL_image.h>  //pour inclure des images non bmp.
  6. #include "personnage.h"
  7. #include "map.h"
  8. #include "affichage.h"
  9. using namespace std;
  10. void pauseIci(); // pause() était deja pris ...
  11. int main()
  12. {
  13.   cout << "begining of the story baby" << endl;
  14.   //creation du personnage
  15.   Personnage monPersonnage;
  16.   monPersonnage.afficherEtat();
  17.   //creation de la carte
  18.   Map maCarte;
  19.   maCarte.insererObjet(4,4,2);
  20.   maCarte.afficherTerrainTerm();
  21.  
  22.   //testSDL
  23.  
  24.   Affichage monEcran;
  25.   monEcran.initialisationFenetre();
  26.   monEcran.definirTerrain();
  27.   monEcran.afficherTerrain();
  28.   monEcran.definirPersonnage();
  29.   monEcran.afficherPersonnage();
  30.   monEcran.flip();
  31.   SDL_Event event;
  32.   int continuer = 1;
  33.   int tempsPrecedent = 0, tempsActuel = 0;
  34.   while (continuer)
  35.     {
  36.       SDL_PollEvent(&event);
  37.       switch(event.type)
  38.         {
  39. case SDL_QUIT:
  40.   continuer = 0;
  41.   break;
  42. case SDL_KEYDOWN:
  43.   tempsActuel = SDL_GetTicks();
  44.   if (tempsActuel - tempsPrecedent > 30)
  45.     // Si 30 ms se sont écoulées depuis le dernier tour de boucle
  46.     {
  47.       monEcran.deplacement(event);
  48.       tempsPrecedent = tempsActuel;
  49.     }
  50.   else //on endort le programme le temps qu'il faut
  51.     {
  52.       SDL_Delay(30 - (tempsActuel - tempsPrecedent));
  53.     }
  54.   break;
  55.         }
  56.       monEcran.clearScreen();
  57.       monEcran.afficherTerrain();
  58.       monEcran.afficherPersonnage();
  59.       monEcran.flip();
  60.     }
  61.   cout << "sortie de boucle, on désaloue la memoire" << endl;
  62.   monEcran.libererMemoire();
  63.   //monEcran.pauseIci();
  64.   return 0;
  65. }


 
Et le code de Affichage.cpp dans la foulé :

Code :
  1. #include "affichage.h"
  2. Affichage::Affichage()
  3. {
  4.   // Definition variables de l'ecran
  5.   HAUTEUR_ECRAN = 500;
  6.   LARGEUR_ECRAN = 500;
  7.  
  8.   //Personnage
  9.   positionPersonnage.x = LARGEUR_ECRAN/2;
  10.   positionPersonnage.y = HAUTEUR_ECRAN/2;
  11.  
  12.   //directions
  13.   direction = 0;
  14.   LEFT = 0;
  15.   RIGHT = 1;
  16.   UP = 2 ;
  17.   DOWN = 4 ;
  18.   //animation
  19.   frame = 0;
  20.  
  21.   //Decoupe du personnage
  22.   for(int i(0);i<4;i++) {
  23.         decoupePersonnageL[ i ].x = 26 * i -23;
  24.         decoupePersonnageL[ i ].y = 3*38 +2;
  25.         decoupePersonnageL[ i ].w = 26;
  26.         decoupePersonnageL[ i ].h = 35;
  27.   }
  28.   for(int i(0);i<4;i++) {
  29.         decoupePersonnageR[ i ].x = 205-26 * i -3;
  30.         decoupePersonnageR[ i ].y = 3*38 +2;
  31.         decoupePersonnageR[ i ].w = 26;
  32.         decoupePersonnageR[ i ].h = 35;
  33.   }
  34.   for(int i(0);i<4;i++) {
  35.         decoupePersonnageU[ i ].x = 26 * i -23;
  36.         decoupePersonnageU[ i ].y = 1*38 +2;
  37.         decoupePersonnageU[ i ].w = 26;
  38.         decoupePersonnageU[ i ].h = 35;
  39.   }
  40.     for(int i(0);i<4;i++) {
  41.         decoupePersonnageD[ i ].x = 26 * i -23;
  42.         decoupePersonnageD[ i ].y = 5*38 +3;
  43.         decoupePersonnageD[ i ].w = 26;
  44.         decoupePersonnageD[ i ].h = 35;
  45.   }
  46. }
  47. Affichage::~Affichage()
  48. {
  49. }
  50. void Affichage::initialisationFenetre()
  51. {
  52.   SDL_Init(SDL_INIT_VIDEO); // Initialisation de la SDL
  53.   ecran = SDL_SetVideoMode(LARGEUR_ECRAN, HAUTEUR_ECRAN, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
  54.   SDL_WM_SetCaption("Jeu cool", NULL); // Change titre de la fenetre
  55.   SDL_EnableKeyRepeat(10, 10); // interval de repetition des touches
  56.   coordX = 0;
  57.   coordY = 0;
  58. }
  59. void Affichage::afficherTerrain()
  60. {
  61.   SDL_Rect positionFond;
  62.   positionFond.x = coordX;
  63.   positionFond.y = coordY;
  64.   SDL_BlitSurface(Terrain, NULL, ecran, &positionFond);
  65. }
  66. void Affichage::afficherPersonnage()
  67. {
  68.   if (direction == LEFT)
  69.     {
  70.       SDL_BlitSurface(Personnage, &decoupePersonnageL[1], ecran, &positionPersonnage);
  71.     }
  72.   else if (direction == RIGHT)
  73.     {
  74.       SDL_BlitSurface(PersonnageInverse, &decoupePersonnageR[1], ecran, &positionPersonnage);
  75.     }
  76.   else if (direction == UP)
  77.     {
  78.       SDL_BlitSurface(Personnage, &decoupePersonnageU[1], ecran, &positionPersonnage);
  79.     }
  80.   else if (direction == DOWN)
  81.     {
  82.       SDL_BlitSurface(Personnage, &decoupePersonnageD[1], ecran, &positionPersonnage);
  83.     }
  84. }
  85. void Affichage::definirTerrain()
  86. {
  87.   Terrain = IMG_Load("ressources/herbe.jpg" );
  88. }
  89. void Affichage::definirPersonnage()
  90. {
  91.   Personnage = IMG_Load("ressources/iceboy.png" );
  92.   Personnage = SDL_DisplayFormat( Personnage );
  93.   SDL_SetColorKey(Personnage, SDL_RLEACCEL | SDL_SRCCOLORKEY, SDL_MapRGB(Personnage->format, 180, 255, 180)); // vire le fond
  94.   PersonnageInverse = copierEtRetourner(Personnage);
  95. }
  96. void Affichage::flip()
  97. {
  98.   SDL_Flip(ecran);
  99. }
  100. void Affichage::pauseIci()
  101. {
  102.   int continuer = 1;
  103.   SDL_Event event;
  104.   while (continuer)
  105.     {
  106.       SDL_WaitEvent(&event);
  107.       switch(event.type)
  108.         {
  109. case SDL_QUIT:
  110.   continuer = 0;
  111.         }
  112.     }
  113. }
  114. void Affichage::deplacement(SDL_Event event)
  115. {
  116.   switch(event.key.keysym.sym)
  117.     {
  118.     case SDLK_UP:   // Fleche haut
  119.       coordY++;direction = UP; break;
  120.     case SDLK_DOWN: // Fleche bas
  121.       coordY--;direction = DOWN; break;
  122.     case SDLK_RIGHT: // Fleche droite
  123.       coordX--; direction = RIGHT; break;
  124.     case SDLK_LEFT:  // Fleche gauche
  125.       coordX++; direction = LEFT; break;
  126.     }
  127. }
  128. void Affichage::clearScreen()
  129. {
  130.   SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
  131. }
  132. void Affichage::libererMemoire()
  133. {
  134.   SDL_FreeSurface(Personnage);
  135.   SDL_FreeSurface(Terrain);
  136. }


 
Merci d'avance.

mood
Publicité
Posté le 15-03-2012 à 17:50:09  profilanswer
 

n°2131647
tpierron
Posté le 15-03-2012 à 20:04:18  profilanswer
 

Hmm, tu utilises SDL_PollEvent() qui ne fait aucune attente. Du coup, d'après ton code, si tu n'appuies sur aucune touche => 100% d'utilisation du CPU.
 
Tu pourrais regarder les fonctions SDL_WaitEvent et SDL_AddTimer() pour faire un truc un peu plus sympa pour le CPU. Fait attention à la précision des timers, ça tourne autour de 10/15ms sous Windows.
 
Aussi, j'ai le souvenir que sous Linusque, les perfs ne sont vraiment pas terribles (edit: avec la lib SDL, hein, c'est pas vraiment linusque le problème :o )


Message édité par tpierron le 15-03-2012 à 20:05:49
n°2131649
Ehon
Posté le 15-03-2012 à 20:09:31  profilanswer
 

Bonjour
 
Pour répondre à ta question:
Sur le Site du zéro il parle de:
«si vous utilisez SDL_WaitEvent votre programme utilisera très peu de processeur car il attendra qu'un évènement se produise»
http://www.siteduzero.com/tutoriel [...] e-1-2.html
et de
«SDL_Delay peut donc être utile pour réduire l'utilisation du processeur»
http://www.siteduzero.com/tutoriel [...] temps.html
 
Sinon, si tu veux faire du C++
N'utilise pas les entête C
#include <stdlib.h>
#include <stdio.h>
Remplace la SDL par la SFML
http://www.sfml-dev.org/index-fr.php

n°2131657
Terminapor
I'll see you rise.
Posté le 15-03-2012 à 21:01:10  profilanswer
 

Mouais, WaitEvent est pas ce qu'il faut pour du temps réel, vu qu'il freeze le programme jusqu'à ce qu'une touche soit pressée (à moins de le foutre dans un thread)
 
Par contre, t'as foutu le contrôleur de framerate dans le cas d'une touche pressé, faut pas. En gros ta boucle principale se fait comme ça :
 
- On gère les évements (PollEvent)
- On exécute chaque code de chaque objet (gestion des déplacements et compagnie)
- On dessine chaque objet
- On flip l'écran
- On calcule le temps à attendre (SDL_Delay())


---------------
Perhaps you don't deserve to breathe
n°2131665
beuted
Posté le 15-03-2012 à 22:57:00  profilanswer
 

Merci à tous, pour ces bons conseils.
Je vais quand même rester sur de la SDL, même s'il y a plus performant.
J'ai complètement repensé la manière dont je gérais la pression des touches pour qu'on puisse en presser deux d'un coup et maintenant j'ai une utilisation du cpu qui varie de 16 à 20% ça me semble plus raisonnable. Je remets mon code (qui gere maintenant les déplacements en diagonale et les animations)
Voilà la boucle de mon main, j'utilise maintenant in qui est le tableau des touches enfoncées
 

Code :
  1. while(!(monEcran.in).key[SDLK_ESCAPE]) // On quiete en faisant echap.
  2.     {
  3.       tempsActuel = SDL_GetTicks();
  4.       // Si 30 ms se sont écoulées depuis le dernier tour de boucle  
  5.       if (tempsActuel - tempsPrecedent > 45)
  6.         {
  7.   monEcran.UpdateEvents(&(monEcran.in));
  8.   monEcran.deplacement();
  9.  
  10.   monEcran.clearScreen();              //applique du blanc sur tout l'ecran
  11.   monEcran.afficherTerrain();           //affiche le terrain
  12.   monEcran.afficherPersonnage();   //affiche le personnage
  13.   monEcran.flip();
  14.   tempsPrecedent = tempsActuel;
  15. }
  16.       else
  17. {
  18.   SDL_Delay(45 - (tempsActuel - tempsPrecedent));
  19. }
  20.     }


 
 
Je vous mets les fonctions principales de Affichage.cpp :
 
- un gros case tout moche pour l'affichage du personnage suivant la direction et la frame ou on est :

Code :
  1. void Affichage::afficherPersonnage()
  2. {
  3.   switch (direction) {
  4.   case LEFT:
  5.     SDL_BlitSurface(Personnage, &decoupePersonnageL[frame], ecran, &positionPersonnage); break;
  6.   case RIGHT:
  7.     SDL_BlitSurface(PersonnageInverse, &decoupePersonnageR[frame], ecran, &positionPersonnage); break;
  8.   case UP:
  9.     SDL_BlitSurface(Personnage, &decoupePersonnageU[frame], ecran, &positionPersonnage); break;
  10.   case DOWN:
  11.     SDL_BlitSurface(Personnage, &decoupePersonnageD[frame], ecran, &positionPersonnage); break;   
  12.   case UP_LEFT:
  13.     SDL_BlitSurface(Personnage, &decoupePersonnageUL[frame], ecran, &positionPersonnage); break;
  14.   case UP_RIGHT:
  15.     SDL_BlitSurface(PersonnageInverse, &decoupePersonnageUR[frame], ecran, &positionPersonnage); break;
  16.   case DOWN_LEFT:
  17.     SDL_BlitSurface(Personnage, &decoupePersonnageDL[frame], ecran, &positionPersonnage); break;
  18.   case DOWN_RIGHT:
  19.     SDL_BlitSurface(PersonnageInverse, &decoupePersonnageDR[frame], ecran, &positionPersonnage); break;
  20.   default:
  21.     break;
  22.   }
  23. }


 
- La fonction qui remplit le tableau de touche enfoncé

Code :
  1. void Affichage::deplacement() // On modifie direct la var global = MOCHE
  2. {
  3.    // UP
  4.   if (in.key[SDLK_UP] && !(in.key[SDLK_LEFT]) && !(in.key[SDLK_RIGHT]) && !(in.key[SDLK_DOWN])) {
  5.     coordY+=VITESSE; direction = UP; frame++;
  6.   }// DOWN
  7.   if (in.key[SDLK_DOWN] && !(in.key[SDLK_LEFT]) && !(in.key[SDLK_RIGHT]) && !(in.key[SDLK_UP])) {
  8.     coordY-=VITESSE; direction = DOWN; frame++;
  9.   }// RIGHT
  10.   if (in.key[SDLK_RIGHT] && !(in.key[SDLK_LEFT]) && !(in.key[SDLK_DOWN]) && !(in.key[SDLK_UP])) {
  11.     coordX-=VITESSE; direction = RIGHT; frame++;
  12.   }// LEFT
  13.   if (in.key[SDLK_LEFT] && !(in.key[SDLK_DOWN]) && !(in.key[SDLK_RIGHT]) && !(in.key[SDLK_UP])) {
  14.     coordX+=VITESSE; direction = LEFT; frame++;
  15.   }// UP + LEFT
  16.   if (in.key[SDLK_UP] && in.key[SDLK_LEFT]  && !(in.key[SDLK_RIGHT]) && !(in.key[SDLK_DOWN])) {
  17.     coordY+=VITESSED; coordX+=VITESSED; direction = UP_LEFT; frame++;
  18.   }//DOWN + LEFT
  19.   if (in.key[SDLK_DOWN] && in.key[SDLK_LEFT] && !(in.key[SDLK_RIGHT]) && !(in.key[SDLK_UP])) {
  20.     coordY-=VITESSED; coordX+=VITESSED; direction = DOWN_LEFT; frame++;
  21.   }// UP + RIGHT
  22.   if (in.key[SDLK_UP] && in.key[SDLK_RIGHT] && !(in.key[SDLK_LEFT]) && !(in.key[SDLK_DOWN])) {
  23.     coordY+=VITESSED; coordX-=VITESSED; direction = UP_RIGHT; frame++;
  24.   }// DOWN + RIGHT
  25.     if (in.key[SDLK_DOWN] && in.key[SDLK_RIGHT] && !(in.key[SDLK_LEFT]) && !(in.key[SDLK_UP])) {
  26.     coordY-=VITESSED; coordX-=VITESSED; direction = DOWN_RIGHT; frame++;
  27.   }
  28.   if (frame > 4) {
  29.       frame = 1;
  30.   }
  31. }


 
- la fonction qui remplit in le tableau des touches enfoncées

Code :
  1. void Affichage::UpdateEvents(Input *inp)
  2. {
  3.   SDL_Event event;
  4.   while(SDL_PollEvent(&event))
  5.     {
  6.       switch (event.type)
  7. {
  8. case SDL_KEYDOWN:
  9.   inp->key[event.key.keysym.sym]=1;
  10.   break;
  11. case SDL_KEYUP:
  12.   inp->key[event.key.keysym.sym]=0;
  13.   break;
  14. case SDL_QUIT:       //On quitte en fermant la fenetre
  15.   exit(EXIT_SUCCESS);
  16.   break;
  17. default:
  18.   break;
  19. }
  20.     }
  21. }


 
Le problème que j'ai, c'est que j'ai pas trouvé d'autre solution que de passer in en paramètre globale de la class affichage  :(  
En essayant de créer un fonction "renvoitIn" j'avais des problèmes de compilation de plus je ne sais pas ou définir la structure Input :

Code :
  1. typedef struct
  2. {
  3. char key[SDLK_LAST];
  4. } Input;


(pour l'instant definit dans Affichage.cpp)
 
Je présents que c'est un problème de passer une fonction en pointeur ou un truc du genre mais je suis dans le vague.


Message édité par beuted le 15-03-2012 à 22:57:32
n°2131667
Terminapor
I'll see you rise.
Posté le 15-03-2012 à 23:29:35  profilanswer
 

T'es pas obligé de mettre ton code update / déplacer et compagnie après le if pour la gestion du framerate, SDL_Delay() met le programme en pause, en gros aucune instruction n'est exécutée tant que le temps d'attente n'est pas fini.
aussi, typedef est inutile dans ton code, struct Input { }; suffit ;)
 
Pour la SDL, tu peux directement récupérer l'état des touches :
 

Code :
  1. Uint8 * keystate = SDL_GetKeyState(NULL); // ou SDL_GetKeyboardState(NULL), ça dépend de ta version
  2. if (keystate[SDLK_LEFT])
  3. // On a appuyé sur la flèche gauche
  4. if (keystate[SDLK_A])
  5. // On a appuyé sur la touche 'a'
  6. // etc


Message édité par Terminapor le 15-03-2012 à 23:30:10

---------------
Perhaps you don't deserve to breathe
n°2131848
beuted
Posté le 16-03-2012 à 21:54:24  profilanswer
 

Merci pour les conseils,
J'avais le code que tu propose avant mais il ne gère pas le fait que l'utilisateur appuie sur deux boutons en même temps.
Et pour le SDL_Delay(), il me semble que faire comme je fais permet d'avoir des intervalles de temps entre chaque image plus réguliers.

n°2131862
Terminapor
I'll see you rise.
Posté le 17-03-2012 à 02:07:43  profilanswer
 

Ben pour les deux touches à la fois, tu fais par exemple "if (keystate[SDLK_LEFT] && keystate[SDLK_A] )",ça marche pas ?
Et pour le SDL_Delay, je sais pas trop, ça m'étonne un peu..


---------------
Perhaps you don't deserve to breathe

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  consommation 80% du cpu - D'où ca vient ?

 

Sujets relatifs
Objet WMI inaccessible : de quoi vient cette erreur ?Problème à l'importation B.D.D MySQL
[CubeOlap] Traiter un cube / regénérer à partir D'Excel 2010webservice C# et consommation SOAP : problème de namespace
Démon utilisant D-BusPROGRAMME POUR LIVRE D'OR
PROBLEME d'if comportant un lienAMELIORATION D'un calendrier de recherche sur base sql
Plus de sujets relatifs à : consommation 80% du cpu - D'où ca vient ?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR