Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: affichage/gestion du temps  (Lu 1320 fois)

0 Membres et 1 Invité sur ce sujet

mazertys17

  • Full Member
  • ***
  • Messages: 123
    • Voir le profil
    • E-mail
affichage/gestion du temps
« le: Décembre 31, 2014, 03:00:32 pm »
Bonjour.

J'ai besoin de quelques conseils/aides s.v.p. :-[
Mon programme fonctionne très correctement, cependant, dès que j'ajoute de nombreux éléments sur ma scène, le jeu n'est plus fluide...ralentissements, accélérations etc...J'ai besoin de savoir si:

    -pour le nombre d'éléments demandés, le fait que le jeu rame est normal, en raison des composantes de la SFML/pc ou autre...
    -ma gestion d'affichage n'est pas conforme/optimisé pour ce faire.
    -cela pourrait surtout venir de la façon dont je gère le temps.
    -probablement le codage de mes objets.
    -ou autre suggestion...

voila en gros mes questionnements. Dans mon exemple, j'affiche environ 400 éléments de décors, + environs 500 éléments intéractifs qui font un certains nombre d'actions (collisions, animations, sourisSur etc..) + quelques dizaines d'autres éléments qui fonctionnent pareil, dont un qui génère plusieurs sf::Drawable par secondes (mais ne semble pas influencer sur la fluidité du jeu)...le tout updatés tous les 31250 microseconds, dans le but d'avoir des animations fluides à 16 images/secondes.

Dans cet exemple, ce qui se passe, souvent, c'est qu'il rame beaucoup les quelques premières secondes, puis se remet a fonctionner tout a fait normalement. Le jeu est alors parfaitement jouable.
Cependant, si je rajoute, par exemple, 500 éléments interactifs supplémentaire, cela commence a ramer de façon durable.
J'ai un pc de gamer assez récent. Quand je vois les possibilités de certains moteurs 3D actuels, je me dit que 1000 éléments affichés n'est pas vraiment énorme.

Pour l'instant, le temps est géré ainsi:


//...ici le main, boucle principale...//

            while(tempsEcoule.asMicroseconds() < 31250)
            {
            tempsEcoule = clock.getElapsedTime();
            }
           if(tempsEcoule.asMicroseconds() >= 31250)
                {
                clock.restart();
                }

        //...tout ce qui doit se passer...//
 

et mon affichage est géré ainsi : un pointeur de sf::Texture est envoyé a chaque sf::Drawable au chargement, et a chaque appel (soit toutes les 31250 microsecondes) il se passe ceci pour tous les objets/images:

(m_entiteImage est une sf::Drawable)


void ObjetExemple::rafraichi()
{

    //...diverses choses pour gérer les animations, déplacements etc...//

     sf::VertexArray vertexArrayRelais;

     vertexArrayRelais.setPrimitiveType(sf::Quads);
     vertexArrayRelais.resize(4);
     vertexArrayRelais[0] = sf::Vector2f (m_x                        ,m_y);
     vertexArrayRelais[1] = sf::Vector2f (m_x + m_tailleImageL       ,m_y);
     vertexArrayRelais[2] = sf::Vector2f (m_x + m_tailleImageL       ,m_y + m_tailleImageH);
     vertexArrayRelais[3] = sf::Vector2f (m_x                        ,m_y + m_tailleImageH);

     vertexArrayRelais[0].texCoords = sf::Vector2f (m_tailleImageL * m_compteurX                         ,m_tailleImageH * m_compteurY);
     vertexArrayRelais[1].texCoords = sf::Vector2f (m_tailleImageL * m_compteurX + m_tailleImageL        ,m_tailleImageH * m_compteurY);
     vertexArrayRelais[2].texCoords = sf::Vector2f (m_tailleImageL * m_compteurX + m_tailleImageL        ,m_tailleImageH * m_compteurY + m_tailleImageH);
     vertexArrayRelais[3].texCoords = sf::Vector2f (m_tailleImageL * m_compteurX                         ,m_tailleImageH * m_compteurY + m_tailleImageH);

     m_entiteImage.recoitVertexArray(vertexArrayRelais);

}

EntiteImage* ObjetExemple::renvoiEntiteImage()
{
    return &m_entiteImage;
}


 

cette EntiteImage* est alors envoyé jusqu'au main qui fait:


        while(afficheur.contientImage())
        {
             entiteImage.insert(it,afficheur.renvoiEntiteImage());
        }

       fenetre.setView(*afficheur.renvoiVue());
       for (std::multiset<EntiteImage>::iterator it = entiteImage.begin(); it != entiteImage.end(); it++)
       {
               fenetre.draw(*it);
       }
 


Voilà. J'espère avoir été assez clair quant a ma problématique. Je n'ai pas l'intention de remettre en question tout le système qui marche bien (sauf ultimatum), mais bien sur je suis prêt à le modifier si nécessaire, ou encore accepter de voir au rabais certains éléments du gameplay. Mon but est de partir avec les meilleurs bases possible pour bien adaptateur mon GD par la suite aux possibilités qu'offre la SFML , en optimisant au maximum avec mes compétences en programmation.

Un simple avis ou des pistes me rendraient service, je n'en demande pas plus  ;)

Merci beaucoup si vous pouvez m'aider  :D
« Modifié: Décembre 31, 2014, 03:09:17 pm par mazertys17 »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : affichage/gestion du temps
« Réponse #1 le: Décembre 31, 2014, 03:13:40 pm »
Plein de choses ne vont pas dans ce que tu montres.

Citer
            while(tempsEcoule.asMicroseconds() < 31250)
            {
            tempsEcoule = clock.getElapsedTime();
            }

Tu bloques tout le thread pendant 31 ms à chaque tour de boucle, en occupant 100% du CPU. Pourquoi donc faire ça ? Au pire si tu veux ralentir toute ton application, utilise sf::sleep de sorte à ne pas monopoliser le CPU pour rien.

Citer
void ObjetExemple::rafraichi()
{
    sf::VertexArray vertexArrayRelais;

    // ...

    m_entiteImage.recoitVertexArray(vertexArrayRelais);
}

Ici tu crées et détruis un nouveau vertex array, (qui alloue sa mémoire dynamiquement), puis en fais une copie voire plus, à chaque tour de boucle pour chaque entité. Puisque la taille est connue (4), utilise un tableau à taille fixe dont la mémoire est allouée sur la pile (std::array<sf::Vertex, 4> ou sf::Vertex[4]). Pour ce qui est d'éviter la recopie, ça dépend de ton architecture de classes, là je ne peux pas me prononcer. Ensuite est-ce que ce vertex array a systématiquement besoin d'être reconstruit ? Est-ce qu'il ne peut pas l'être que lorsque l'une des variables impliquée est modifiée ?

Citer
        while(afficheur.contientImage())
        {
             entiteImage.insert(it,afficheur.renvoiEntiteImage());
        }
Je ne comprends pas le but de cette boucle.

Citer
std::multiset<EntiteImage>
Tu stockes tes entités par copie, tu es sûr que c'est ce que tu veux ? A chaque insertion, l'entité et tout ce qu'elle contient sera entièrement recopiée. Si tu fais ça pour chaque entité à chaque tour de boucle, là encore tu as plein de copies et d'allocations mémoire pour rien.

Et sinon : apprends aussi à utiliser un profiler, c'est fait pour ça ;)
Laurent Gomila - SFML developer

mazertys17

  • Full Member
  • ***
  • Messages: 123
    • Voir le profil
    • E-mail
Re : affichage/gestion du temps
« Réponse #2 le: Décembre 31, 2014, 04:01:52 pm »
Merci pour votre réponse  :)

(jai modifié ma réponse)

En fait, en réfléchissant bien, je vais finalement revoir une bonne partie de mon système...En effet, la recopie via le std::multiset et autre est tout a fait évitable...
Bref...Merci pour ces conseils/pistes, que je vais suivre !

Bonne année 2015  ;)
« Modifié: Janvier 01, 2015, 02:09:49 pm par mazertys17 »