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

Auteur Sujet: Tri croissant par rapport à une valeur d'un Tableau d'une class_créée  (Lu 7118 fois)

0 Membres et 2 Invités sur ce sujet

Arnibou

  • Newbie
  • *
  • Messages: 30
    • Voir le profil
Bonsoir,

Pour commencer une partie de mon code:

Entite_static.cpp

Entite_static::Entite_static()
{
    for(int i = 0; i < NB_DECOR; i++)
    {
        rect_decor[i].left = 0;
        rect_decor[i].top = 0;
        rect_decor[i].width = 0;
        rect_decor[i].height = 0;
    }

}

Entite_static::~Entite_static()
{

}

void Entite_static::ajout_entite(unsigned char id, int x, int y)
{
    if(id == 0)
    {
        tree_texture.loadFromFile("sprites/environnements/tree_barrens/tree_450_500.png");
        sprite_tree.setTexture(tree_texture);
    }
    if(id == 1)
    {
        tree2_texture.loadFromFile("sprites/environnements/tree_barrens/tree2_450_500.png");
        sprite_tree2.setTexture(tree2_texture);
    }

    //Positions des Entite_static
    sprite_tree.setPosition(x, y);
    sprite_tree2.setPosition(x, y);

    //Recuperation box tree
    rect_decor[0] = sprite_tree.getGlobalBounds();
    //Ajustement box tree
    rect_decor[0].left = rect_decor[0].left + 113;
    rect_decor[0].top = rect_decor[0].top + 380;
    rect_decor[0].width = 226;
    rect_decor[0].height = 72;
    //Recuperation box tree2
    rect_decor[1] = sprite_tree2.getGlobalBounds();
    //Ajustement box tree2
    rect_decor[1].left = rect_decor[1].left + 250;
    rect_decor[1].top = rect_decor[1].top + 400;
    rect_decor[1].width = 150;
    rect_decor[1].height = 72;
}


void Entite_static::afficher_decor(sf::RenderTarget &target)
{
    target.draw(sprite_tree);
    target.draw(sprite_tree2);
}
 

ensuite dans :
map.h

Entite_static decor_monde1[NB_TOTAL_DECOR];
 

map.cpp
void Map::monde1()
{
    //Chargement monde1
    map_monde1.loadFromFile("maps/map1.png");
    sprite_map_monde1.setTexture(map_monde1);
    sprite_map_monde1.setPosition(-1400, -700);

    /*
    Chargement du decor
    ajout_entite(id_du_decor, position_en_x, position_en_y)
    */

    //TREE
    decor_monde1[0].ajout_entite(0, 200, 200);
    decor_monde1[1].ajout_entite(0, 200, 0);
    //TREE2
    decor_monde1[2].ajout_entite(1, 400, 0);
    decor_monde1[3].ajout_entite(1, 1000, -110);
}

void Map::afficher_map(sf::RenderTarget &target, unsigned char monde)
{
    target.draw(sprite_map_monde1);
}

void Map::afficher_decor(sf::RenderTarget &target, unsigned char monde)
{
    for(int i = 0; i < NB_TOTAL_DECOR; i++)
    decor_monde1[i].afficher_decor(target);
}
 

Voila une partie de mon code pour afficher un decor par rapport à son id et sa position x, y

Est il possible de classer le tableau decor_monde1 en focntion de la position en y de l'entité car pour l'affichage je voudrais que ceux qui sont le plus en haut soit affiché en 1er?
« Modifié: Mai 01, 2012, 10:25:45 pm par Arnibou »

Lo-X

  • Hero Member
  • *****
  • Messages: 618
    • Voir le profil
    • My personal website, with CV, portfolio and projects
Pourquoi tu n'utilises pas un std::vector ? Suffit de définir comment le trier en surchargeant l'opérateur < (si je dis pas de bêtises).

Vas voir : http://bakura.developpez.com/tutoriel/cpp/tri/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Surcharger l'opérateur < de la classe juste pour définir un ordre de tri particulier, c'est la mauvaise solution. LA bonne est d'utiliser la version de std::sort qui prend un foncteur perso.

Il y a plein de choses à ce sujet sur le net, un peu de recherche devrait te montrer tout ce qu'il te faut savoir.
Laurent Gomila - SFML developer

Lo-X

  • Hero Member
  • *****
  • Messages: 618
    • Voir le profil
    • My personal website, with CV, portfolio and projects
Surcharger l'opérateur < de la classe juste pour définir un ordre de tri particulier, c'est la mauvaise solution. LA bonne est d'utiliser la version de std::sort qui prend un foncteur perso.

Il y a plein de choses à ce sujet sur le net, un peu de recherche devrait te montrer tout ce qu'il te faut savoir.

Ah voilà c'est ça que je cherchais.

Arnibou

  • Newbie
  • *
  • Messages: 30
    • Voir le profil
bon si c'est la seule solution ok ^^

Je me suis deja pencher sur cette solution avec un std::sort avec le foncteur en 3eme argument et j'ai bien galéré jusqu'à abandonné lol donc me reste plus qu'à m'y remettre dessus ;)

merci à vous 2
« Modifié: Mai 01, 2012, 11:39:35 pm par Arnibou »

Arnibou

  • Newbie
  • *
  • Messages: 30
    • Voir le profil
Bonsoir,

Avec les exemples que j'ai trouvé sur le tri avec std::sort, j'ai un petit problème!

Voila ce que ça donne:

alors dans Entite_static.cpp:

en constructeur j'ai modifié et mit

Entite_static::Entite_static(int y) : value(y)
{
    for(int i = 0; i < NB_DECOR; i++)
    {
        rect_decor[i].left = 0;
        rect_decor[i].top = 0;
        rect_decor[i].width = 0;
        rect_decor[i].height = 0;
    }
}
 

dans Entite_static.h
j'ai rajouté une variable en public et crée un struct triAscendant:

class Entite_static
{
...
public :

    Entite_static(int y);//Constructeur
    int value;
...
};

struct TriAscendant
{
   inline bool operator() (const Entite_static & a, const Entite_static & b) const
   {
      return a.value <= b.value;
   }
};
 

Dans le map.h

J'ai crée un std::vector<Entite_static> decor_monde1;
au lieu d'un Entite_static decor_monde1[NB_DECOR];

Et pour finir dans le map.cpp
Voila comment j'ai procédé

void Map::monde1()
{
    //Chargement monde1
    map_monde1.loadFromFile("maps/map1.png");
    sprite_map_monde1.setTexture(map_monde1);
    sprite_map_monde1.setPosition(-1400, -700);

    /*
    Chargement du decor
    */


    //La valeur correspond à la position en Y de l'entite ajoutée
    decor_monde1.push_back(Entite_static(200));
    decor_monde1.push_back(Entite_static(0));
    decor_monde1.push_back(Entite_static(0));
    decor_monde1.push_back(Entite_static(-110));
    decor_monde1.push_back(Entite_static(300));

    //ajout_entite(id_du_decor, position_en_x, position_en_y)
    //TREE
    decor_monde1[0].ajout_entite(0, 200, 200);
    decor_monde1[1].ajout_entite(0, 200, 0);
    //TREE2
    decor_monde1[2].ajout_entite(1, 400, 0);
    decor_monde1[3].ajout_entite(1, 1000, -110);
    //TREE3
    decor_monde1[4].ajout_entite(2, 800, 300);
   
    std::sort(decor_monde1.begin(), decor_monde1.end(), TriAscendant());
}

void Map::afficher_map(sf::RenderTarget &target, unsigned char monde)
{
    target.draw(sprite_map_monde1);
}

void Map::afficher_decor(sf::RenderTarget &target, unsigned char monde)
{
    for(int i = 0; i < NB_TOTAL_DECOR; i++)
    decor_monde1[i].afficher_decor(target);
}

 

Le tri a l'air de fonctionner mais seul le dernier sprite est affiché et les 4 autres ca fait un carré blanc de la taille du sprite à la place, comme si l'image n'etait plus chargée ... alors pourquoi les 4 premières et pas la derniére ça le fait?
Ai je oublié quelque chose?
« Modifié: Mai 02, 2012, 11:47:20 pm par Arnibou »

lezebulon

  • Full Member
  • ***
  • Messages: 235
    • Voir le profil
Il nous manque surtout les .h pour pouvoir comprendre ce qui ce passe parce que là on a aucune idée de comment tu peux desssiner des sprites vu que y'a pas de sf::sprite dans ce que tu postes... à mon avis c'est juste que tu gères mal la copie des Entite_static et que tu détruis la texture en route.
Mais sinon ton design est à revoir de tte façon, pourquoi tu as
    decor_monde1.push_back(Entite_static(200));
   et après
    decor_monde1[0].ajout_entite(0, 200, 200);

??


Arnibou

  • Newbie
  • *
  • Messages: 30
    • Voir le profil
Regarde mon 1er post pour les sf::Sprite, la dans le dernier j'ai juste mis ce que j'ai modifié.

Ensuite j'ai mis decor_monde.push_back(Entite_Static(200));

car le tri se fait pas rapport au y (donc je reporte le 200 ici du 1er ajout_entite) et je ne vois pas comment remplir le vector sans cette façon (cela fait que 5 mois que j'ai commencé à aprendre le c++ donc je suis loin de connaitre la meileur façon de faire)

Je ne voyais pas comment faire autrement pour trier le vector avec std:sort, à moins qu'il y ai une methode plus simple.

sinon voici le code un peu plus complet :

Entite_statuc.h
class Entite_static
{

    private :

    sf::Texture tree_texture, tree2_texture, tree3_texture;
    sf::Sprite sprite_tree, sprite_tree2, sprite_tree3;

    //Tableau qui va retourner toutes les valeurs des box des Entite_Static
    sf::FloatRect rect_decor[NB_DECOR];
    float top;

    public :

    Entite_static(int y);//Constructeur
    int value;
    ~Entite_static();//Destructeur
    void ajout_entite(unsigned char id, int x, int y);//Ajout entite
    void afficher_decor(sf::RenderTarget &target);//Affichage de l'entité
    std::vector<sf::FloatRect> decor_box();//Retour des valeurs de la box de l'entite pour collision

};

struct TriAscendant
{
   inline bool operator() (const Entite_static & a, const Entite_static & b) const
   {
      return a.value <= b.value;
   }
};
 

Entite_static.cpp
Entite_static::Entite_static(int y) : value(y)
{
    for(int i = 0; i < NB_DECOR; i++)
    {
        rect_decor[i].left = 0;
        rect_decor[i].top = 0;
        rect_decor[i].width = 0;
        rect_decor[i].height = 0;
    }

}

Entite_static::~Entite_static()
{

}

void Entite_static::ajout_entite(unsigned char id, int x, int y)
{
    if(id == 0)
    {
        tree_texture.loadFromFile("sprites/environnements/tree_barrens/tree_450_500.png");
        sprite_tree.setTexture(tree_texture);
    }
    if(id == 1)
    {
        tree2_texture.loadFromFile("sprites/environnements/tree_barrens/tree2_450_500.png");
        sprite_tree2.setTexture(tree2_texture);
    }
    if(id == 2)
    {
        tree_texture.loadFromFile("sprites/environnements/tree_barrens/tree3_700_500.png");
        sprite_tree3.setTexture(tree_texture);
    }

    //Positions des Entite_static
    sprite_tree.setPosition(x, y);
    sprite_tree2.setPosition(x, y);
    sprite_tree3.setPosition(x, y);

    //Recuperation box tree
    rect_decor[0] = sprite_tree.getGlobalBounds();
    //Ajustement box tree
    rect_decor[0].left = rect_decor[0].left + 113;
    rect_decor[0].top = rect_decor[0].top + 380;
    rect_decor[0].width = 226;
    rect_decor[0].height = 72;
    //Recuperation box tree2
    rect_decor[1] = sprite_tree2.getGlobalBounds();
    //Ajustement box tree2
    rect_decor[1].left = rect_decor[1].left + 250;
    rect_decor[1].top = rect_decor[1].top + 400;
    rect_decor[1].width = 150;
    rect_decor[1].height = 72;
    //Recuperation box tree3
    rect_decor[2] = sprite_tree3.getGlobalBounds();
    //Ajustement box tree3
    rect_decor[2].left = rect_decor[2].left + 280;
    rect_decor[2].top = rect_decor[2].top + 460;
    rect_decor[2].width = 140;
    rect_decor[2].height = 72;
}


void Entite_static::afficher_decor(sf::RenderTarget &target)
{
    target.draw(sprite_tree);
    target.draw(sprite_tree2);
    target.draw(sprite_tree3);
}


std::vector<sf::FloatRect> Entite_static::decor_box()
{
    std::vector<sf::FloatRect> return_rect_decor;
    for(int i = 0; i < NB_DECOR; i++)
    return_rect_decor.push_back(rect_decor[i]);

    return return_rect_decor;
}
 

Map.h

#ifndef MAP_H_INCLUDED
#define MAP_H_INCLUDED

#include "Entites.h"
#include "Constantes.h"
#include <algorithm>


class Map
{

    private :

    sf::Texture map_monde1;
    sf::Sprite sprite_map_monde1;

    //Creation des entites
    std::vector<Entite_static> decor_monde1;
    std::vector<sf::FloatRect> copy_rect_decor;



    public :

    Map();
    ~Map();
    void monde1(); //Chargement map et entite monde1
    void afficher_map(sf::RenderTarget &target, unsigned char monde);//Affichage de la map
    void afficher_decor(sf::RenderTarget &target, unsigned char monde);//Affichage du decor
    std::vector<sf::FloatRect> tableau_decor_box();//Retour des valeurs des box entite

};


#endif // MAP_H_INCLUDED
 

et pour finir Map.cpp

#include "Map.h"



Map::Map() :  copy_rect_decor(0)
{

}

Map::~Map()
{

}
void Map::monde1()
{
    //Chargement monde1
    map_monde1.loadFromFile("maps/map1.png");
    sprite_map_monde1.setTexture(map_monde1);
    sprite_map_monde1.setPosition(-1400, -700);

    /*
    Chargement du decor
    */


    //La valeur correspond à la position en Y de l'entite ajoutée
    decor_monde1.push_back(Entite_static(200));
    decor_monde1.push_back(Entite_static(0));
    decor_monde1.push_back(Entite_static(0));
    decor_monde1.push_back(Entite_static(-110));
    decor_monde1.push_back(Entite_static(300));


    //ajout_entite(id_du_decor, position_en_x, position_en_y)
    //TREE
    decor_monde1[0].ajout_entite(0, 200, 200);
    decor_monde1[1].ajout_entite(0, 200, 0);
    //TREE2
    decor_monde1[2].ajout_entite(1, 500, 0);
    decor_monde1[3].ajout_entite(1, 1000, -110);
    //TREE3
    decor_monde1[4].ajout_entite(2, 800, 300);


    /*
    Dans le tableau decor_box()[i]
    i = id du décor ajouté
    */

    copy_rect_decor.push_back(decor_monde1[0].decor_box()[0]);
    copy_rect_decor.push_back(decor_monde1[1].decor_box()[0]);
    copy_rect_decor.push_back(decor_monde1[2].decor_box()[1]);
    copy_rect_decor.push_back(decor_monde1[3].decor_box()[1]);
    copy_rect_decor.push_back(decor_monde1[4].decor_box()[2]);

    //std::sort(decor_monde1.begin(), decor_monde1.end(), TriAscendant());


}

void Map::afficher_map(sf::RenderTarget &target, unsigned char monde)
{
    target.draw(sprite_map_monde1);
}

void Map::afficher_decor(sf::RenderTarget &target, unsigned char monde)
{

    for(int i = 0; i < NB_TOTAL_DECOR; i++)
    decor_monde1[i].afficher_decor(target);
}


std::vector<sf::FloatRect> Map::tableau_decor_box()
{
    return copy_rect_decor;
}

 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Relis la fin du tutoriel sur les sprites ;)
Laurent Gomila - SFML developer

Arnibou

  • Newbie
  • *
  • Messages: 30
    • Voir le profil
J'utilise la SFML2, l'exemple du tuto ne va pas fonctionner mais si j'ai bien compris :

donc quand je trie le vector cela fait des copie et la texture du sprite n'est plus en mémoire (d'où le carré blanc)

donc faut faire en sorte que le tableau utilise une copie de la texture en mémoire plutot que la texture en mémoire?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
En fait ce n'est pas que la texture n'est plus en mémoire, c'est plutôt qu'elle a été copiée ailleurs, alors que le pointeur que le sprite conserve, n'a pas changé. Il faut donc mettre à jour le lien entre sprite et texture lorsque la texture bouge en mémoire, en définissant par exemple correctement le constructeur de copie comme montré dans le tutoriel.
Laurent Gomila - SFML developer

lezebulon

  • Full Member
  • ***
  • Messages: 235
    • Voir le profil
Ah oui pour le coup c'est exactement le cas du tuto...
Moralité : mieux vaut pas stocker les sf::texture directement dans des containers, vu les problèmes de copies (perfs et pointeurs qui se perdent)
Sinon y'a moyen de déterminer "programatiquement" si la texture a été détruite à partir uniquement de l'objet sprite?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Citer
Sinon y'a moyen de déterminer "programatiquement" si la texture a été détruite à partir uniquement de l'objet sprite?
Non. Mais demander à un autre objet ce qu'il s'est passé sur la texture, plutôt que de le savoir parce que ton code le gère correctement, ce serait pas terrible de toute façon ;)
Laurent Gomila - SFML developer

lezebulon

  • Full Member
  • ***
  • Messages: 235
    • Voir le profil
Ok
je me demandais parce qu'il me semble qu'on a "systématiquement" (enfin à a connaissance) un carré blanc quand la texture a été libérée, alors que si le pointeur de texture a leaké on devrait avoir un comportement "random" non? Genre une texture qui dépendrait des valeurs pointées en mémoire

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
C'est le cas, le comportement est indéterminé. Mais c'est un peu plus compliqué que ça : la texture au final est un identificateur entier, pas un pointeur, donc OpenGL peut facilement savoir que ce n'est pas une texture valide, et mettre du blanc par défaut à la place.
Laurent Gomila - SFML developer