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

Auteur Sujet: Quel conteneur pour une map?  (Lu 8497 fois)

0 Membres et 1 Invité sur ce sujet

Crone123

  • Full Member
  • ***
  • Messages: 141
    • Voir le profil
Quel conteneur pour une map?
« le: Avril 15, 2012, 01:17:48 pm »
Bonjour,
Je développe actuellement un RPG, et j'ai besoin d'un conteneur pour stocker beaucoup d'objets pour la map. (Tout est positionné proprement sur des cases)
J'ai d'abord pris un std::vector mais le problème c'est qu'il fallait dans la boucle a chaque fois chercher dans tout le vector pour afficher les objets, et ça prends trop de temps, ça fait ramer le jeu.
Je suis donc passé sur un std::map<std::string, type_de_mon_obj> qui est plus pratique, mais pareil, ça a tendance a ramer...j'ai des chutes de FPS provenant de là, c'est injouable.
Je cherche donc un conteneur un peu comme les std::map, c'est a dire que je peux y accéder de la même façon, associatif en fait, mais plus rapide a l’exécution, ou bien, trouver une meilleure façon de l'utiliser.
J'ai pensé a la limite utiliser un std::map<sf::Vector2f, type_de_mon_obj> mais est-ce que je gagnerais des performances? Pas sur.

Existe-t-il, en dehors des bêtes tableaux standard, des objets dynamiques ou pour accéder a une case de ma map je demande:
obj[X][Y] ou X et Y sont des int, mais que le tableau soit géré dynamiquement par l'objet et supporte les nombres négatifs?
Ce ne serait pas associatif, mais ça serait sûrement encore mieux :)

Voilà, si quelqu'un pouvait m'aider pour ça, ça serait sympa parce que dans tous mes projets j'ai des gros problèmes avec les conteneurs et ça fait ramer le jeu...
Merci :)

Ceylo

  • Hero Member
  • *****
  • Messages: 2325
    • Voir le profil
    • http://sfemovie.yalir.org/
    • E-mail
Re : Quel conteneur pour une map?
« Réponse #1 le: Avril 15, 2012, 01:28:58 pm »
Je m'y connais pas trop dans le domaine mais il me semble que les quadtree répondraient à ton problème (si le problème est vraiment là) : http://fr.wikipedia.org/wiki/Quadtree
Want to play movies in your SFML application? Check out sfeMovie!

Crone123

  • Full Member
  • ***
  • Messages: 141
    • Voir le profil
Re : Quel conteneur pour une map?
« Réponse #2 le: Avril 15, 2012, 02:58:28 pm »
Merci pour ta réponse, mais je ne pense pas que ce soit ça dont j'ai besoin...
J'ai repensé plus précisément a l'objet dont j'ai besoin, et donc, ce qu'il me faudrait exactement, ce serait un tableau dynamique a 2 dimensions.
Sur lequel je peux avoir sa taille (comme un std::vector avec size()), et qui soit dynamique.
Exemple, je dis:
Tableau[82](104] = Pointeur_vers_un_obj;
Si cette case n'existe pas, il agrandi automatiquement le tableau :)

Sinon, au pire je prends un tableau standard que je fais assez grand :) (mais du coup, j'ai pas de taille illimitée, ni de fonctions pratiques sur l'objet, et ça bouffe beaucoup plus de ram...)

Ceylo

  • Hero Member
  • *****
  • Messages: 2325
    • Voir le profil
    • http://sfemovie.yalir.org/
    • E-mail
Re : Quel conteneur pour une map?
« Réponse #3 le: Avril 15, 2012, 03:08:00 pm »
Dans ce cas le plus pratique serait probablement de faire ta propre classe à base de vector de vector de pointeur. Ainsi tu aurais ce que tu veux, une taille illimitée, une consommation mémoire en fonction de ton utilisation, et pour les fonctions pratique, à toi de les écrire.

Peut-être que tu peux aussi déjà trouver des classes de matrice en C++ sur le net.
Want to play movies in your SFML application? Check out sfeMovie!

Crone123

  • Full Member
  • ***
  • Messages: 141
    • Voir le profil
Re : Quel conteneur pour une map?
« Réponse #4 le: Avril 15, 2012, 03:27:22 pm »
OK, Merci :)
Je vais essayer un truc a base de tableaux standard pour l'instant, si entièrement remplis ça me prends 1.2Go de ram, mais si ce n'est pas entièrement remplis, ça ne consomme rien :)
La map fera 1000*1000 en 32*32 je pense que c'est déjà bien (surtout a gérer en réseau) et ne prendra 1.2Go de ram que si la map empile toutes les textures possibles du jeu les une sur les autres sur les 1000000 de cases disponibles, donc voilà, merci pour votre aide :D

PS: Donc au final le jeu ne prendra pas plus de ram qu'avant :)

lezebulon

  • Full Member
  • ***
  • Messages: 235
    • Voir le profil
Re : Quel conteneur pour une map?
« Réponse #5 le: Avril 15, 2012, 08:52:44 pm »
Tu veux stocker quoi dans ta map exactement?
Vu que apparement c'est des objets sur chaque case, je vois pas pourquoi un std::vector en 2D va pas marcher, pourquoi tu as besoin de boucler pour chercher un objet??
Moi pour mon RPG 2D j'utilisait un tableau 2D de pointeurs par map, donc même avec un million de cases tu t'en sors avec 8 Mo de RAM si il est vide (donc rien du tout), et puis je remplis ou vide les cases de ce tableau dynamiquement (genre si on ne ne voit pas la case, je détruis les objets graphiques associés)

Koryushin

  • Jr. Member
  • **
  • Messages: 93
    • Voir le profil
Re : Quel conteneur pour une map?
« Réponse #6 le: Avril 15, 2012, 11:02:47 pm »
Y a des petites optimisations qui existent pour booster un peu le fps.
entre autre n'afficher que ce qui est visible à l'écran, optimiser les boucles for() en faisant des ++obj au lieu de obj++ etc..

Ceylo

  • Hero Member
  • *****
  • Messages: 2325
    • Voir le profil
    • http://sfemovie.yalir.org/
    • E-mail
Re : Re : Quel conteneur pour une map?
« Réponse #7 le: Avril 15, 2012, 11:10:18 pm »
Y a des petites optimisations qui existent pour booster un peu le fps.
entre autre n'afficher que ce qui est visible à l'écran, optimiser les boucles for() en faisant des ++obj au lieu de obj++ etc..
oO
Je suis assez surpris par ta réponse. N'afficher que ce qui est visible à l'écran est loin d'être une petite optimisation. À moins que le module graphique ne gère ça de façon automatique, ça fait une énorme différence. En tout cas avec SFML 1.6 ce n'était pas géré automatiquement, je ne sais pas ce qu'il en est exactement avec SFML 2.0.

Et peux-tu expliquer en quoi un ++obj serait avantageux par rapport à un obj++ ?
Want to play movies in your SFML application? Check out sfeMovie!

Crone123

  • Full Member
  • ***
  • Messages: 141
    • Voir le profil
Re : Quel conteneur pour une map?
« Réponse #8 le: Avril 15, 2012, 11:37:33 pm »
Oui, en fait je boucle pour chercher les objets avec des for parce que ce sont des tableaux de pointeurs.
Donc, j'utilise maintenant un tableau standard a 2 dimensions de 1000 * 1000 ça ne rame pas d'un poil :)
Citer
Je suis assez surpris par ta réponse. N'afficher que ce qui est visible à l'écran est loin d'être une petite optimisation. À moins que le module graphique ne gère ça de façon automatique, ça fait une énorme différence. En tout cas avec SFML 1.6 ce n'était pas géré automatiquement, je ne sais pas ce qu'il en est exactement avec SFML 2.0.
Bah, dans mon jeu actuel, j'ai pas essayé, je sais que de toutes façon ça diminue beaucoup les perfs, mais dans un autre de mes projets:
25 - 50 FPS a tout casser en affichant tout (et des bugs de fluidité, des rams, passage a travers les murs, et tout et tout), et 110  a 120 FPS en affichant uniquement ce qui est visible :)
Citer
entre autre n'afficher que ce qui est visible à l'écran, optimiser les boucles for() en faisant des ++obj au lieu de obj++ etc..
Actuellement, je fais ça, j'affiche par rapport au joueur, vu que maintenant le tableau standard a les objets bien rangés en fonction de leurs positions, je fais des for pour afficher tout ce qui sera visible a l'écran, c'est ultra rapide, c'est impeccable :D

Rien qu'au chargement de la map depuis un serveur de jeu, avant ça mettait 10s avec un std::map, maintenant ça met a tout casser une seconde avec le tableau standard :)

lezebulon

  • Full Member
  • ***
  • Messages: 235
    • Voir le profil
Re : Re : Re : Quel conteneur pour une map?
« Réponse #9 le: Avril 15, 2012, 11:41:01 pm »
Et peux-tu expliquer en quoi un ++obj serait avantageux par rapport à un obj++ ?
Tu peux être 100% sûr qu'en release ça change rien...
En fait quand tu fais "obj++" tu copies l'ancien obj en backup, tu incrémente obj avec ++obj et tu retournes le backup de obj (pas incrémenté), donc en théorie tu fais une copie de plus.
Bon je pense que meme en config debug, pour les int et les itérateurs la différence de temps est meme pas mesurable

Oui, en fait je boucle pour chercher les objets avec des for parce que ce sont des tableaux de pointeurs.
J'ai rien compris à ce message, tu boucles sur quoi pour chercher quoi? Peu importe ce que tu cherches, tu devrais pas avoir un temps en O(n) mais en ln(n) dans tous les cas...
« Modifié: Avril 15, 2012, 11:45:18 pm par lezebulon »

Crone123

  • Full Member
  • ***
  • Messages: 141
    • Voir le profil
Re : Quel conteneur pour une map?
« Réponse #10 le: Avril 15, 2012, 11:52:46 pm »
Moi perso j'ai jamais fait de obj++ j'ai toujours fait des ++obj.
Sinon, pour le fait de boucler:
Exemple avec un tableau de sf::Sprite:
sf::Sprite *Tableau[1000][1000];
//On suppose que le tableau est bien déclaré, que tous les pointeurs sont remis a 0 et qu'on a mis (ou pas) des objets dedans. (via pointeur)
for(unsigned int compteur(0); compteur < 1000; ++compteur)
{
for(unsigned int compteur2(0); compteur2 < 1000; ++compteur2)
{
if(Tableau[compteur][compteur2] != 0)
{
Draw(*Tableau[compteur][compteur2]);
}
}
}
Je met Draw tout seul, vous pouvez choisir un rendu si vous le souhaitez, pour ma part vu que mon jeu tourne dans une fenêtre Qt: Draw()  me suffit puisque mes objets sont dans la sf::RenderWindow :)

lezebulon

  • Full Member
  • ***
  • Messages: 235
    • Voir le profil
Re : Quel conteneur pour une map?
« Réponse #11 le: Avril 16, 2012, 12:13:55 am »
Aaaah ok, j'avais pas compris... dans ce cas-là c'est le plus rapide effectivement

Koryushin

  • Jr. Member
  • **
  • Messages: 93
    • Voir le profil
Re : Re : Re : Quel conteneur pour une map?
« Réponse #12 le: Avril 16, 2012, 07:36:07 am »
Y a des petites optimisations qui existent pour booster un peu le fps.
entre autre n'afficher que ce qui est visible à l'écran, optimiser les boucles for() en faisant des ++obj au lieu de obj++ etc..
oO
Je suis assez surpris par ta réponse. N'afficher que ce qui est visible à l'écran est loin d'être une petite optimisation. À moins que le module graphique ne gère ça de façon automatique, ça fait une énorme différence. En tout cas avec SFML 1.6 ce n'était pas géré automatiquement, je ne sais pas ce qu'il en est exactement avec SFML 2.0.

Et peux-tu expliquer en quoi un ++obj serait avantageux par rapport à un obj++ ?

Bah c'est pas si dur que ça si on prend le temps, comprendre comment sfml fonctionne.
-Extraire le rectangle englobant de la vue courante,
-Soit tester si les Sprites de notre map sont dans le rectangle de la vue. (Fonction sf::Rect::Intersects())
-Soit s'arranger pour que nos boucles for() bouclent en fonction du rectangle de la vue.

Bigz

  • Full Member
  • ***
  • Messages: 154
    • Voir le profil
    • Bigz.fr
Re : Quel conteneur pour une map?
« Réponse #13 le: Avril 16, 2012, 10:14:23 am »
A propos du post et pré incrémentation, comme l'a dit Lezebulon, la post incrémentation fait une copie en backup en plus de la post. De la sorte :

const Foo& Foo::operator++() // called for ++i
{
    this->data += 1;
    return *this;
}

const Foo Foo::operator++(int)  // called for i++
{
    Foo tmp(*this);
    this->data += 1;
    return tmp;
}

Autrement dit, sur un int, on s'en bat les reins. Même si ça reste une (très très très) légère optimisation, d'utiliser la pré incrémentation. D'ailleurs, je serais pas étonné que les compilo optimisent ça tout seul mais j'en suis vraiment pas sur.

Par contre, si l'objet est un peu plus compliqué qu'un int, il faut se rappeler qu'un appel au constructeur par copie peu être coûteux (c'est aussi pour ça qu'on évitera dans de nombreux cas des retours de fonctions par valeur, qui utilisent le constructeur par copie, au profit d'un retour par référence ou pointeur).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Quel conteneur pour une map?
« Réponse #14 le: Avril 16, 2012, 10:30:20 am »
Citer
Autrement dit, sur un int, on s'en bat les reins. Même si ça reste une (très très très) légère optimisation, d'utiliser la pré incrémentation. D'ailleurs, je serais pas étonné que les compilo optimisent ça tout seul mais j'en suis vraiment pas sur.
Pour les types natifs, post et pré-incrémentations donnent le même code, il n'y a aucune différence.

Citer
Par contre, si l'objet est un peu plus compliqué qu'un int, il faut se rappeler qu'un appel au constructeur par copie peu être coûteux
Pour les types incrémentables habituels qu'on utilise dans les boucles, autre que les types natifs (donc les itérateurs), c'est vraiment négligeable. Franchement, avant de commencer à optimiser ce genre de chose, il y a des questions bien plus importantes à se poser. Ne gaspillez pas trop votre temps sur ce genre de détail insignifiant.
Laurent Gomila - SFML developer