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

Auteur Sujet: Optimiser l'affichage de tiles  (Lu 4985 fois)

0 Membres et 1 Invité sur ce sujet

MyPix

  • Full Member
  • ***
  • Messages: 117
    • Voir le profil
    • E-mail
Optimiser l'affichage de tiles
« le: Mai 13, 2015, 02:00:55 pm »
Bonjour,

J'aimerais créer un jeu qui s'inspire de Wakfu, en gros le décor bouge selon le personnage (la caméra reste centrée sur le personnage) mais si le monde est très grand (bien que je peux faire des "district" dans le monde pour éviter d'avoir trop de map à la suite) j'ai peur que l'appel de l'affichage des tiles (draw) de chaque map (sur plusieurs calques parfois selon le type de map) soit trop  gourmand en ressources sachant que c'est des textures de +- 150*150 et que mes maps sont composé de 16x16 tiles.
Donc un petit calcul, imaginons un grand monde de 20*20 cartes, donc 400 cartes, chacune ayant 256 tiles ça fait 100 000+ d'appels par CALQUE à afficher chaque FRAME.. beaucoup beaucoup n'est ce pas.

Donc j'aimerais optimiser cela.
Pour cela j'ai plusieurs idées :
N'afficher que les maps qui sont autour du joueur. ça peut être facile (je ne sais pas vraiment enfait) à réaliser comme difficile vu que chaque tick je devrait prendre la position du joueur et vérifier si il se trouve sur une tile d'une map (donc 100 000 vérification chaque seconde ou moins selon le point de départ de la vérification), sauf si vous avez une idée c'est pas ergonomique.

N'afficher que les TILES visible par la caméra, en prenant leur position et en vérifiant si elle est à l'intérieur du rectangle de la caméra, je pense que c'est le mieux à faire mais j'aimerais des avis de pro ^^

Au niveau de ma map, c'est une classe qui est hérité de Drawable et Transformable et qui dessine chacune les tiles qui lui sont propres (comme ça la SFML gère tout si je dois déplacer/tourner ma map :) ) (Matrice des tiles étant récupérées d'un fichier JSON mais je vais pas détailler, car cela est chargé en mémoire lors du chargement initial du jeu)

Merci :)
« Modifié: Mai 13, 2015, 02:02:58 pm par MyPix »

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Optimiser l'affichage de tiles
« Réponse #1 le: Mai 13, 2015, 04:03:54 pm »
C'est assez simple a faire le calcul des tuiles visible.

il faut d'abord que tu calculs le nombre de tuiles visibles à l'écran :

nombre_visible = (Taille de ta vue en pixel / taille de ta tuile en pixel) + 1

Ensuite, il faut que tu determine sur quel tuile ton personnage se trouve :

hero_tile_pos = position en pixel de ton perso / taille tuile

Avec ces deux éléments, tu peu déterminer ou ta boucle d'affichage va commencer et terminer

Start_x = (hero_tile_pos.x - (nombre_visible.x /2)) - 1
End_x  = Start_x + nombre_visible.x + 1


MyPix

  • Full Member
  • ***
  • Messages: 117
    • Voir le profil
    • E-mail
Re : Optimiser l'affichage de tiles
« Réponse #2 le: Mai 13, 2015, 04:20:01 pm »
Déterminer le nombre de tiles à l'écran me sert à rien ^^
Je veux dire, pour chaque tile, la map vérifie si elle est dans le rectangle de la vue, si oui elle dessine si non elle passe autre chose

Et la pos du Hero, y'a pas une fonction pour vérifier si un point (pos du hero) se trouve sur un sprite (si oui lequel) ou pas ? (ou j'ai rêvé ? x) )

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Optimiser l'affichage de tiles
« Réponse #3 le: Mai 13, 2015, 04:24:43 pm »
Citer
N'afficher que les TILES visible par la caméra, en prenant leur position et en vérifiant si elle est à l'intérieur du rectangle de la caméra, je pense que c'est le mieux à faire mais j'aimerais des avis de pro ^^

Citer
Déterminer le nombre de tiles à l'écran me sert à rien ^^

...

je ne sais pas quoi te répondre. ayant déjà fait des jeux de plateforme, c'est comme cela que je procède...
 

Citer
Et la pos du Hero, y'a pas une fonction pour vérifier si un point (pos du hero) se trouve sur un sprite (si oui lequel) ou pas ? (ou j'ai rêvé ? x) )

Relis mon topic et essaye de le comprendre.

MyPix

  • Full Member
  • ***
  • Messages: 117
    • Voir le profil
    • E-mail
Re : Optimiser l'affichage de tiles
« Réponse #4 le: Mai 13, 2015, 04:41:20 pm »
Pour les tiles à l'écran = http://www.sfml-dev.org/documentation/2.0-fr/classsf_1_1Rect.php#aa8a5364c84de6dd5299f833b54e31ef1 (contains) je pense bien

Pour la pos du héro, je peux pas appliquer cela aussi (voir si chaque tile contient le point du héro?)

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Optimiser l'affichage de tiles
« Réponse #5 le: Mai 13, 2015, 04:53:23 pm »
Tes tuilles sont dans quoi ? un vector ? tu vas utilisé contains sur toutes tes tuilles pour savoir laquelle est à l'écran ? autant ne rien faire.

Citer
Pour la pos du héro, je peux pas appliquer cela aussi (voir si chaque tile contient le point du héro?)

Elle est ou l'optimisation ?

tx = hero_pos.x / tilesize.x;
ty = hero_pos.y / tilesize.y;
tile_id = tx + mapsize.x * ty;

tile_id te renvois la position dans un tableau 2D ( ta map )

Pareil pour l'affichage :
toute la map :
for ( y = 0, y<mapsize.y; ++y){
  for ( x = 0, x<mapsize.x; ++x){
   affichage...
 }
}

Avec mon explication plus haut :
for ( y = begin.y, y<end.y; ++y){
  for ( x = begin.x, x<end.x; ++x){
   affichage...
 }
}


je ne vais pas pondre un code complet, relis mon post plus haut.

MyPix

  • Full Member
  • ***
  • Messages: 117
    • Voir le profil
    • E-mail
Re : Optimiser l'affichage de tiles
« Réponse #6 le: Mai 13, 2015, 05:15:29 pm »
Je suis vraiment perdu la.
Mes Tiles sont dans un vector oui.. mais le vector faut pas oublier qu'il est tourné à 45 degrés car c'est de la vue Isométrique.
ta formule si mon perso est à genre 500x 300y et que la map c'est du 1920x1080
500/150
300/150
3.33 + 1920*2 ça fait 3800 et des poussieres, elle est ou la coordonée la ?

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Optimiser l'affichage de tiles
« Réponse #7 le: Mai 13, 2015, 05:21:22 pm »
Citer
c'est de la vue Isométrique.
Heureusement que tu le précises... la formule n'est pas la même : regarde ici : http://www.gotoandplay.it/_articles/2004/02/tonypa_p24.php

Pour ton perso, tu ne récupère pas une coordonnée , mais un index , qui lui est l'index de ta tuile dans le std::vector , evidement , il faut que tu convertissent la position du perso en coordonnée iso aussi avant.

MyPix

  • Full Member
  • ***
  • Messages: 117
    • Voir le profil
    • E-mail
Re : Optimiser l'affichage de tiles
« Réponse #8 le: Mai 13, 2015, 11:56:15 pm »
Re,
Donc pour mon problème. J'ai essayé de faire ça
void Map::draw(sf::RenderTarget& target, sf::RenderStates states) const
{                      
        // They are sorted.. simply draw them :)
        for (int layers(0); layers < m_tiles.size(); layers++)
        {
                for (int x(0); x < m_tiles[layers].size(); x++)
                {
                //      cout << endl << m_tiles[layers][x].k << "[" << m_tiles[layers][x].sprite.getPosition().x << ";" << m_tiles[layers][x].sprite.getPosition().y << "]";
                //      if (m_tiles[layers][x].k < 4)
                        if (target.getView().getViewport().contains(m_tiles[layers][x].sprite.getPosition()))
                                target.draw(m_tiles[layers][x].sprite, states);
                        else
                                cout << "Tile number " << x << " wont be rendered" << endl;
                }
        }
}
 
Cependant ma fonction me renvoie toujours NON donc ducoup Rien n'est affiché, si je fais ! devant la condition tout est affiché, quel est le problème ? Ce que je veux faire c'est vérifier que le sprite que je veut afficher est bien visible par le joueur ^^

(et tient en passant, quand on resize ma fenetre, comment éviter que mon rendu soit étirer mais que plutot la vue devienne plus grande ou plus petite (en gros si  j'ai du Full hd et que l'utilisateur resize la fenetre en 480p il vois une portion plus petite de l'écran) ou alors garder les proportions lors du resize)

Code complet de tout le machin https://github.com/MyPix/Blue/blob/master/Map.cpp
(Map.cpp essentiellement, code très brouillon avec pas mal de commentaire, je me sert plus de github comme une sauvegarde pour mon code si jamais j'ai un problème dans mon ordi ,c'est pas trop fait pour être publique :) )

(Petite explication, la valeur K d'une tile est une somme, ce qui me permet d'avoir un ordre clair et précis (k = la somme des position x et y dans le tableau (genre 1+1 pour [1;1], 2+3 pour [2,3])) je m'en sert pour l'ordre de rendu et le positionnement (ça m'as facilité la tache pour élaborer le bidule car je savais que tout ce qui avait le même 'k' était sur la même ligne (donc k a une incidence sur la position Y)mais je m'égare la, oublie, je ne veut pas t'embrouiller)
« Modifié: Mai 14, 2015, 12:02:53 am par MyPix »

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Optimiser l'affichage de tiles
« Réponse #9 le: Mai 14, 2015, 12:16:06 am »
mmm... ta méthode n'est absolument pas bonne. comme je te l'ai dis , tu parcours l'ensemble de ta map et tu essayes de faire un test d'intersection sur chaque tuile , ce qui est ridicule , puisque tu connais déjà leurs positions ( c'est une grille 2D à espace régulier , donc mathématiquement calculable avec une simple boucle imbriquée )

Relis mon post plus haut , et essaye d'optimiser dans un premier temps sans l'isométrie et sans tes intersections, tu fera de l’isométrie plus tard.

Pour ma part , je créer mes tuiles a la volée ( un vertex array ) , avant le rendu donc , avec uniquement les tuiles visibles comme expliqué plus haut , et je le donne a manger à draw() , un seul appel par layer donc.

MyPix

  • Full Member
  • ***
  • Messages: 117
    • Voir le profil
    • E-mail
Re : Optimiser l'affichage de tiles
« Réponse #10 le: Mai 14, 2015, 04:34:11 pm »
Ta méthode est applicable que si toutes les tuiles sont dans le même fichier image, moi j'ai plein de fichiers ;)
Peut tu réexpliquer ta méthode ? Et ce qui ne va pas dans la méthode.

Niveau isométrie je suis déja dedans, tout est codé pour, j'y ai passé des heures je veux pas faire régresser mon projet désolé.

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Optimiser l'affichage de tiles
« Réponse #11 le: Mai 14, 2015, 05:13:35 pm »
Je ne parle pas de ton projet, mais rien ne t’empêches de codé a coté.
Pour ton problème de "plein de texture" , rien ne t’empêche de créer une atlas texture , soit en dessinant, soit a la volée, c'est un autre problème.

Comme je te l'ai déjà expliquer , tu cherches a afficher les tuiles visibles via la méthode contain() sur l’ensemble de tes tuiles , et de faire un draw si nécessaire, cette approche n'est pas bonne , sur une map de 256x256 , tu testes 65536 tuiles. en calculant un min / max , en fonction du nombre de tuiles visible à l'écran , tu réduis considérablement le nombre d'appel à draw(). je vais voir si j'ai un code qui traine quelque part.

MyPix

  • Full Member
  • ***
  • Messages: 117
    • Voir le profil
    • E-mail
Re : Optimiser l'affichage de tiles
« Réponse #12 le: Mai 14, 2015, 05:34:26 pm »
Oui, essaye d'expliquer un petit peu :)
Sinon niveau textures/moteur j'ai pas de problèmes, voici un exemple de fichier JSON
http://pastebin.com/bRBgQubD
Et ce que mon code produit
http://prntscr.com/7557g2

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Optimiser l'affichage de tiles
« Réponse #13 le: Mai 14, 2015, 05:53:59 pm »
Expliqué... a part faire ton code , je ne vois pas comment je peu t'aider plus. :)
voila 2 liens qui vont t'aider à voir plus clair :
http://stackoverflow.com/questions/2060690/culling-offscreen-tiles-in-an-isometric-engine
http://gamedev.stackexchange.com/questions/19525/how-can-i-cull-non-visible-isometric-tiles

MyPix

  • Full Member
  • ***
  • Messages: 117
    • Voir le profil
    • E-mail
Re : Optimiser l'affichage de tiles
« Réponse #14 le: Mai 14, 2015, 06:17:36 pm »
Si j'ai bien compris, je prend le centre de l'écran (avec le viewport?), je prend sa position puis je calcule un "seuil" x et y et je vérifie si la tile est dans ce seuil?