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

Auteur Sujet: [ Résolu ] SIGSEGV (inventaire)  (Lu 11782 fois)

0 Membres et 2 Invités sur ce sujet

Glân de Brylan

  • Invité
Re : SIGSEGV plantage du prog
« Réponse #15 le: Avril 11, 2015, 07:13:34 pm »
J'ai décortiqué ta fonction RInter() :
if (p.inter(e) == e.getType())
Mettons que e soit de type 0, donc une simple entité. p.inter(e) renvoie 0, et e.getType() aussi, donc la condition vaut vrai. Les tests suivants seront donc exécutés, ce qui est idiot puisqu'un RObject de type 0 n'a aucune interaction. La première ligne de cette fonction devrait être
if (e.getType() == 0)
    return false;
Ensuite, appel à p.inter(e). Oh, cette fonction est inutilement compliquée, puisqu'un test de collision, sur ce type de configuration, se résume à ça :
bool inter(Entity e)
{
    return ( e.getX() == x && e.getY() == y )
}

Et ta fonction RInter devient :
bool RInter(Perso& p, RObject& e, const std::string& texture, Inventory& inv)
{
   if (e.getType() == 0)
        return false;

    // Comme tes QDebug() affichaient (je suppose) les numéro de ligne, je les ai enlevés, puisque ça ne va plus correspondre à rien.
    // À propos c'est une mauvaise façon de procéder, si tu veux savoir où en est ton programme, tu utilises le debugger en mode pas-à-pas.

    if (p.inter(e) && e.inter()) // Si le perso est bien au même endroit que e et que e est disponible...
        {
            e.changeU(false);   // Eh ben e n'est plus dispo, puisque p vient de le ramasser.

            if (!e.load(texture))   // Tu devrias plutôt ne charger qu'une seule fois la texture, le la donner à ton entité quand elle en a besoin
                 return false;      // Parce que là tu as une texture par entité alors qu'elles utilisent toutes la même, ce genre de truc bouffe vite de la mémoire pour rien.

            string e_name = e.getName();

            if (e_name == "ble")
            {
                int nb = inv.recupInt(0);
                int nbr = nb+1;
                inv.modifier(0, nbr, e_name); // On le met dans l'inventaire.
            }
            if (e_name == "orge")
            {
                int nb = inv.recupInt(1);
                int nbr = nb+1;
                inv.modifier(1, nbr, e_name); // Idem.
            }
            // D'ailleurs, si ton inventaire est plein et que tu essaies d'ajouter un truc, je crois que ton programme va planter. Mais ce n'est pas le problème.

            return true; // Et on dit "oui, cette entité a été ramassée".
    }

    return false; // Ou pas.
}

Lis bien les commentaires, ils pourraient t'apprendre un truc ou deux.
Cette version de p.inter(e) et de RInter() devrait fonctionner, tu me confirmes ça ?

S66

  • Full Member
  • ***
  • Messages: 120
  • *-*
    • Voir le profil
    • Teal
Re : SIGSEGV plantage du prog
« Réponse #16 le: Avril 11, 2015, 07:36:19 pm »
« D'ailleurs, si ton inventaire est plein et que tu essaies d'ajouter un truc, je crois que ton programme va planter. Mais ce n'est pas le problème. »
Bin non, vu que mon inventaire est primitif, chaque objet a sa place. Blé aura la place 0, orge la place 1.

if (e_name == "ble")
                {
                    int nb = inv.recupInt(0);
                    int nbr = nb+1;
                    inv.modifier(0, nbr, e_name); // On le met dans l'inventaire.
                }
                if (e_name == "orge")
                {
                    int nb = inv.recupInt(1);
                    int nbr = nb+1;
                    inv.modifier(1, nbr, e_name); // Idem.
                }

Et, euh, maintenant c'est le type qui déraille.

pour le truc e.load, j'ai fait ça:
main.cpp:
//mes includes

using namespace std;

sf::Texture deadBle;

deadBle.loadFromFile("deadBle.png");

bool RInter(Perso& p, RObject& e, const std::string& texture, Inventory& inv) {...}
et il me met deadBle en rouge surligné, et lors de la compilation, la compilo me dit:
C:\Users\william\Projets\C++\newQt\Projects\dofus\Code\tilemap\main.cpp:23: erreur : 'deadBle' does not name a type
 deadBle.loadFromFile("deadBle.png");
 ^
Mon compilateur est fou !

Glân de Brylan

  • Invité
Re : SIGSEGV plantage du prog
« Réponse #17 le: Avril 11, 2015, 07:57:51 pm »
Déj), c'est j'ai bien compris, deadBle est global. Tetete. On ne t'as jamais appris que les variables global c'était mal ?

Crée ta texture dans ta fonction main. Change le prototype de RInter pour que sont paramètre texture soit effectivement une sf::Texture et non un std::string et modifie des RObject pour que leur fonction load() prenne directement la texture plutôt que de prendre son adresse et de la charger. (pareil pour ble.png, orge.png et deadOrge.png, bien sûr)
Si une même texture est chargée plusieurs fois dans ton programme, c'est qu'il y a un problème de conception. Perso j'utilise une classe textureCore qui s'occupe de charger les texture et de distribuer leurs adresses aux classes qui les demandent.
(par exemple une class Champignon va faire :
 m_texture = textCore->giveMeTexture("champignon");
)
Où textCore est un pointeur global qui pointe sur l'unique instance de textureCore (bon, les variables globales son pratique dans ce genre de cas, mais d'après moi c'est le seul)

S66

  • Full Member
  • ***
  • Messages: 120
  • *-*
    • Voir le profil
    • Teal
Re : SIGSEGV plantage du prog
« Réponse #18 le: Avril 12, 2015, 11:40:42 am »
Okay. J'utilise 4 textures pour ble, orge, deadBle, deadOrge, et j'ai changé les std::string en sf::Texture.
Le blé veut toujours pas se faire ramasser.

Glân de Brylan

  • Invité
Re : SIGSEGV plantage du prog
« Réponse #19 le: Avril 12, 2015, 02:47:54 pm »
C'est bien dans ton main et pas en variables globales ? Parce que si oui...ben, ton compilo est fou et j'y peux rien :(

S66

  • Full Member
  • ***
  • Messages: 120
  • *-*
    • Voir le profil
    • Teal
Re : SIGSEGV plantage du prog
« Réponse #20 le: Avril 12, 2015, 03:09:00 pm »
Oui, c'est bien dans mon main  :( :o

S66

  • Full Member
  • ***
  • Messages: 120
  • *-*
    • Voir le profil
    • Teal
Re : SIGSEGV plantage du prog
« Réponse #21 le: Avril 15, 2015, 04:50:01 pm »
C'est vrai, mon compilateur était fou.
Mais j'ai résolu le problème par diverses manipulations.
2e problème: L'inventaire qui affiche rien.
else {
                //Draw Invetory
                myInt = 0;
                myFloat = 0;
                while (Inventaire.recupInt(myInt) > 0) {
                    string strr = Inventaire.recupStr(myInt);
                    string str_texture = strr;
                    str_texture += ".png";
                    if (myTexture.loadFromFile(str_texture)) {
                        mySprite.setTexture(myTexture);
                        int nbrr = Inventaire.recupInt(myInt);
                        string nbrrr = to_string(nbrr);
                        sf::Text myText(strr, font, 10);
                        sf::Text myText2(nbrrr, font, 10);
                        myText2.move(20.f, 0.f);

                        myText.move(myFloat, 0.f);
                        myText2.move(myFloat, 0.f);
                        mySprite.move(myFloat, 0.f);

                        window.draw(mySprite);
                        window.draw(myText);
                        window.draw(myText2);
                    }
                    window.draw(InvMode); // texte dont le string est "Inventaire"
                    myFloat += 32;              // Pour annoncer qu'on est en mode inventaire
                    myInt += 1;
                }
            }

Le problème... rien ne s'affiche. même pas le sf::Text InvMode.
(Je vois juste du vert, car j'ai window.clear(sf::Color::Green); avant.)

Glân de Brylan

  • Invité
Re : SIGSEGV plantage du prog
« Réponse #22 le: Avril 15, 2015, 05:20:23 pm »
Premièrement, tu charges une texture à chaque itération de la boucle, ce qui est extrêmement mauvais pour les performances, encore plus que d'avoir une texture par entité.
Normalement, tu avais déjà chargé les texture, mettons que tu les as nommées textureBle et textureOrge, remplace :
str_texture += ".png";
if (myTexture.loadFromFile(str_texture)) {
    mySprite.setTexture(myTexture);
Par :
if(str_texture == "Ble")
    mySprite.setTexture(textureBle);
else
    mySprite.setTexture(textureOrge);
Cela ne résoudra pas ton problème mais c'est important. Enfin en fait, le résoudra peut-être? Tu sais, un texture, c'est fait pour être chargé une fois, par pour changer à tout bout de champ. Tu es sensé la créer, charger son image, puis ne t'en servir que pour la plaquer sur des entités comme les sprites. Peut-être que ce sont ces changements intempestifs d'images qui empêchent le dessin de se dérouler correctement.

Sinon, peut-être est-ce parce que myText, myText2 et mySprite sont des variables temporaires, supprimées à chaque fin d'itération de la boucle ? Essaie de mettre des sprites dans ton inventaire, puis de dessiner le tout avec par exemple une fonction Inventaire.makeDraws(window) qui ferait tous les window.draw() nécessaires.

S66

  • Full Member
  • ***
  • Messages: 120
  • *-*
    • Voir le profil
    • Teal
Re : SIGSEGV plantage du prog
« Réponse #23 le: Avril 15, 2015, 06:12:15 pm »
EDIT: non c'est bon, j'ai plus l'erreur to_string

Par contre il veut toujours pas draw.

if (perso.getStatus() == 0) {
                window.draw(map);
                if (RObjects) {
                    if (Ble) {
                        if (ble.getAvb())
                            window.draw(ble);
                        if (ble2.getAvb())
                           window.draw(ble2);
                        if (ble3.getAvb())
                           window.draw(ble3);
                        if (ble4.getAvb())
                          window.draw(ble4);
                        if (ble5.getAvb())
                          window.draw(ble5);
                        if (ble6.getAvb())
                            window.draw(ble6);
                    }
                    if (Orge) {
                        if (orge.getAvb())
                            window.draw(orge);
                        if (orge2.getAvb())
                            window.draw(orge2);
                        if (orge3.getAvb())
                            window.draw(orge3);
                        if (orge4.getAvb())
                            window.draw(orge4);
                    }
                }
                window.draw(perso);
            }
            //if (perso.getStatus() == 1)
            else {
                //Draw Inventory
                Inventaire.drawInventory(window, font);
            }
Fonction drawInventory:
void drawInventory(sf::RenderWindow& w, sf::Font& font) {
        int myInt = 0;
        float myFloat = 0;
        while(recupInt(myInt) != 0) {
            std::string iStr = recupStr(myInt);
            int iNb = recupInt(myInt);
            std::string iNbr = std::to_string(iNb);
            sf::Sprite iImg = recupSprite(myInt);
            sf::Text oName(iStr, font, 10);
            sf::Text oNbr(iNbr, font, 10);
            oNbr.move(20.f, 0.f);

            iImg.move(myFloat, 0.f);
            oName.move(myFloat, 0.f);
            oNbr.move(myFloat, 0.f);

            w.draw(iImg);
            w.draw(oName);
            w.draw(oNbr);

            myInt += 1;
            myFloat += 32;
        }
    }
« Modifié: Avril 15, 2015, 06:19:22 pm par S66 »

Glân de Brylan

  • Invité
Re : SIGSEGV plantage du prog
« Réponse #24 le: Avril 15, 2015, 06:18:45 pm »
std::to_string

S66

  • Full Member
  • ***
  • Messages: 120
  • *-*
    • Voir le profil
    • Teal
Re : SIGSEGV plantage du prog
« Réponse #25 le: Avril 16, 2015, 06:11:27 pm »
Hem, et maintenant ? :x

Glân de Brylan

  • Invité
Re : SIGSEGV plantage du prog
« Réponse #26 le: Avril 16, 2015, 06:18:20 pm »
Il y a toujours le problème de tes sprites et textes qui cessent d'exister à chaque fin d'itération de la boucle. Fais-toi un vector de sprite (ajoutant une nouveau sprite avec la bonne texture et la bonne position à chaque ble ou orge récupéré) et fais :
for( std::size_t i(0) ; i < mesObjets.size() ; i++)
    window.draw(mesObjets[i]);[/cpp]

S66

  • Full Member
  • ***
  • Messages: 120
  • *-*
    • Voir le profil
    • Teal
Re : SIGSEGV (inventaire)
« Réponse #27 le: Avril 18, 2015, 03:46:33 pm »
Toujours rien.
Et voici mon nouveau code:
RInter:
bool RInter(Perso& p, RObject& e, sf::Texture& texture, Inventory& inv, sf::Sprite& img) {
    if (e.getType() == 0)
            return false;
    if (p.inter(e) && e.inter()) // Si le perso est bien au même endroit que e et que e est disponible...
            {
        //Ln 48
                e.changeU(false);   // Eh ben e n'est plus dispo, puisque p vient de le ramasser.

                if (!e.load(texture))   // Tu devrais plutôt ne charger qu'une seule fois la texture, le la donner à ton entité quand elle en a besoin
                     return false;      // Parce que là tu as une texture par entité alors qu'elles utilisent toutes la même, ce genre de truc bouffe vite de la mémoire pour rien.
                //Ln 53
                std::string eName = e.getName();
                inv.add(1, eName, img);
                // D'ailleurs, si ton inventaire est plein et que tu essaies d'ajouter un truc, je crois que ton programme va planter. Mais ce n'est pas le problème.

                return true; // Et on dit "oui, cette entité a été ramassée".
        }
        // return false ln 72
        return false; // Ou pas.
}

Et Inventory.h:
class Inventory {
public:
    Inventory () :  maxTailleX(16), dfault(), invInt(0, 0), invName(0, ""), invImg(0), invTextName() {
        //unsigned int invInt[maxTailleX];
        //std::string invName[maxTailleX];
        sf::IntRect inRec(0, 0, 32, 32);
        dfault.setTextureRect(inRec);
        dfault.setColor(sf::Color::Black);
    }
    ~Inventory () {}
    bool add (int nbr, std::string str, sf::Sprite img) {
        if (invInt.size() < maxTailleX) {
            bool trouver = false;
            for (std::size_t i(0) ; i < invName.size() ; i++) {
                if (invName[i] == str) {
                    invInt[i] += nbr;
                    trouver = true;
                }
            }
            if (!trouver) {
                if (invInt.size() < maxTailleX) {
                    invInt.push_back(nbr);
                    invName.push_back(str);
                    invImg.push_back(img);
                }
            }
        return true;
        } else
            return false;
    }
    bool del(/*std::string delName*/) {
        //je sais pas comment delete une case précise dans un vector.
        //et evidemment, je peux pas utiliser pop_back...
        return true;
    }
    unsigned int recupInt (const unsigned int pos) const {
        if(pos < invInt.size())
            return invInt[pos];
        else
            return 0;
    }
    std::string recupStr (const unsigned int pos) const {
        if(pos < invName.size())
            return invName[pos];
        else
            return "";
    }
    sf::Sprite recupSprite (const unsigned int pos) const {
        if(pos < invImg.size()) {
            if (recupInt(pos) != 0)
                return invImg[pos];
            else
                return dfault;
        } else
            return dfault;
    }
    void drawInventory(sf::RenderWindow& w/*, sf::Font& font*/) {
        //int myInt = 0;
        //float myFloat = 0;
        for( std::size_t i(0) ; i < invImg.size() ; i++) {
            invImg[i].move(32.f, 0.f);
            w.draw(invImg[i]);
        }
    }
private:
   const unsigned int maxTailleX;
   sf::Sprite dfault; //carré noir de 32x32 pixels
   std::vector<int> invInt; // Nombre d'objets dans la place de l'inventaire X
   std::vector<std::string> invName; // Nom de l'objet dans la place de l'inventaire X
   std::vector<sf::Sprite> invImg;
   sf::Text invTextName;
};

Glân de Brylan

  • Invité
Re : SIGSEGV (inventaire)
« Réponse #28 le: Avril 18, 2015, 04:48:11 pm »
bool del(/*std::string delName*/) {
        //je sais pas comment delete une case précise dans un vector.
        //et evidemment, je peux pas utiliser pop_back...
        return true;
    }
Alors si tu veux pouvoir supprimer des cases au milieu de ton tableau tu devrais utiliser des list. Avec un vector, c'est impossible. Par contre, tu ne pourras plus utiliser les crochets [] pou accéder à un élément. Tu sais te servir des itérateurs ?

En fait, idéalement, tu te servirais des priority_queue pour trier tes éléments en mettant celui le plus à gauche (avec le x le plus petit) en premier, pour facilement ajouter 32 au x d'un élément que tu ajouterais.

Ensuite, plutôt que d'avoir un vector<int>, un vector<std::string> et un vector<sf::Sprite>, tu devrais avoir un seul vector d'objets de ce genre :
class InvSpace
{
    InvSpace() : number(0), name(""), image() {}
    InvSpace(int qty, const std::string& nm, const sf::Texture& texture) : number(qty), name(nm), image(texture) {}

    int number;
    std::string name;
    sf::Sprite image;
}
Ce serait plus simple. Et surtout, le C++ te permet de mettre ensemble les données qui sont liées, alors ne te gêne pas.
Comme ton inventaire a une taille limite, je te conseillerais d'avoir un simple tableau d'InvSpace de taille 16, ou à la rigueur un std::array<InvSpace, 16>. Et pour indiquer qu'une case est vide, il suffirait de faire :
myObjects[index].number = 0;
Pour indiquer que cette case est vide.
La position du sprite devrait être indiquée dans ta fonction add, ce n'est pas le rôle d'une fonction de dessin, qui devrait seulement faire :
void drawInventory(sf::RenderWindow& w)
{
    w.draw(invTextName);

    for( std::size_t i(0) ; i < invImg.size() ; i++)
        if(myObjects[i].number > 0)
            w.draw(myObjects[i].image);
}

Ensuite, ta fonction add :
bool add (int nbr, std::string str, const sf::Texture& img) // note comme je demande une texture plutôt qu'un sprite
{
    bool found = false;

    for (std::size_t i(0) ; i < 16 ; i++)
    {
        if (myObjects[i].name == str) // on a trouvé une case qui contient déjà de ces objets !
        {
            myObjects[i].number += nbr; // donc on en ajoute le nombre qu'il faut.
            return true; // objets ajoutés à l'inventaire avec succès.
        }
    }

    for(std::size_t i(0) ; i < 16 ; i++) // aucune case contenant déjà de ces objets n'a été trouvée, on va donc en chercher une vide.
    {
        if(myObjects[i].number == 0) // si cette case est vide...
        {
            myObjects[i].number = nbr; // ...on la remplit avec notre nouvel objet.
            myObjects[i].name = str;
            myObjects[i].image.setTexture(texture);

            if(i == 0) // si c'est la première case de l'inventaire...
                myObjects[i].image.setPosition(/* x et y du premier objet*/); // ...on lui donne la position du premier objet à afficher.
            else
            {
                myObjects[i].image.setPosition( myObjects[i-1].image.getPosition() ); // ...sinon on lui donne la position de l'objet d'avant...
                myObjects[i].image.move(32f, 0); // ...avec x+32 !
            }
            return true; // objets ajoutés à l'inventaire avec succès.
        }
    }

    return false; // échec, l'inventaire est plein, les objets n'ont pas pu y être ajoutés.
}

Si ça ne fonctionne pas...je ne sais plus quoi faire.


Enfin, met des retours à la ligne entre tes fonctions, aère ton code, ça le rend plus facile à lire. Si tu regardes le code source de la SFML tu verras qu'il met même des grandes lignes de / entre ses fonctions pour bien les séparer.

victorlevasseur

  • Full Member
  • ***
  • Messages: 206
    • Voir le profil
Re : SIGSEGV (inventaire)
« Réponse #29 le: Avril 18, 2015, 07:04:37 pm »
Citer
Alors si tu veux pouvoir supprimer des cases au milieu de ton tableau tu devrais utiliser des list. Avec un vector, c'est impossible. Par contre, tu ne pourras plus utiliser les crochets [] pou accéder à un élément. Tu sais te servir des itérateurs ?
http://www.cplusplus.com/reference/vector/vector/erase/
On peut tout à fait supprimer/insérer au milieu d'un std::vector (mais sera plus lent que sur une std::list)

 

anything