Problem mit SFML, sf::Image und std::vector
-
Hallo!
Ich möchte gerne eine Bilddatei laden, diese dann in mehrere Bilder aufspalten und die Teilbilder dann in einem std::vector ablegen.
Mein Ansatz dazu:sf::Image Test; if (!Test.LoadFromFile("Images\\01.bmp")) { //Error } int k=0; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { Images.push_back(sf::Image(20,20)); Images[k].Copy(Test, 0, 0, sf::IntRect(i*20, j*20, i*20+20, j*20+20)); } } }
Das funktioniert nicht, die Images im Vector sind null. Ich vermute mal das die sich selbst löschen nachdem der gültigkeitsbereich verlassen wurde?
-
Wo inkrementierst du eigentlich k?
PS: Zugriff auf das letzte Element bekommst du elegant durch .back()
-
ehhh, hab beim rumkopieren und schnippeln das k++ wegeschnippelt, es ist aber im code vorhanden...
-
In der Schleife steht es jetzt so:
Images.push_back(sf::Image(20,20)); Images.back().Copy(Test, 0, 0, sf::IntRect(i*20, j*20, i*20+20, j*20+20));
Funktioniert immernoch nicht, nur das letze Element ist != null
-
Hm.. also ich kann da keinen Fehler finden. Der Vektor löscht da jedenfalls erst was, wenn sein Gültigkeitsbereich verlassen wird, da wird das Problem wohl nicht liegen. Nach dem was ich der SFML Doku entnehme, sollte das auch funktionieren.
Was meinst du also genau mit "Element != Null"? Wie kann ein Bild denn Null sein? Poste am besten mal noch etwas mehr Code. :xmas1:
-
debugger für sowas benutzen. Haltepunkt in schleife und sich die werte fürs rect anschauen, ggf rückgabewert von copy falls vorhanden. Wenn nur das letze element ok ist scheinen die Werte fürs rect nicht in ordnung zu sein, sodass nur bei i und j = 1 was kopiert wird.
gib den richtigen code keinen zusammenkopierten.
-
class CAnimatedSprite { private: unsigned int next; std::vector<sf::Image> Images; std::vector<sf::Sprite> Sprites; public: //Constructor CAnimatedSprite() : next(0) { sf::Image Test; if (!Test.LoadFromFile("Images\\01.bmp")) { //Error } for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { Images.push_back(sf::Image(20,20)); Images.back().Copy(Test, 0, 0, sf::IntRect(i*20, j*20, i*20+20, j*20+20)); Sprites.push_back(sf::Sprite(Images.back())); } } } //mehr Methoden //... };
Genaus so steht es im Code.
Mit Null mein ich: wenn ich im Debugger über die vector einträge von Sprite gehe, dann ist myImage und myResource 0x00000000. Außer eben beim letzten, dort sehe ich dann eine Adresse != null und das letzte Bild kann ich auch rendern, die anderen sind weiß.Ich hab es jetzt umgeschrieben und ein Sprite mit einem Image geladen und dann die Methode setSubRect verwendet, so denke ich war es auch von den Machern der SFML gedacht^^.
-
nja push_back nimmt referenzen, kopiert nicht. probier es doch mal mit vector<sf::image* und allokier per new. ist zwar inkonsistent mit der tatsache dass ein bild noch da ist, aber nja...ich hätte jedenfalls intuitiv kein temporäres objekt an push back gegeben, erinnere mich dunkel dass das schiefgeht, habs jetzt aber nicht getestet..mach es aus gewohnheit nicht. :>
-
Hab das Problem gefunden.
Das push_back von Images setzt die Adressen auf null.
Wahrscheinlich fordert Images beim push_back neuen Speichern an und läßt den alten wieder frei. Damit sind die Bilder in Images gültig aber auf neuen Adressen.Sprites kann das natürlich nicht wissen und hat damit ungültige Adressen gespeichert.
So würdes es laufen:
for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { Images.push_back(sf::Image(20,20)); Images.back().Copy(Test, 0, 0, sf::IntRect(i*20, j*20, i*20+20, j*20+20)); } } for(int k=0; k<Images.size(); k++) { Sprites.push_back(sf::Sprite(Images[k])); }
Danach darf man aber nicht mehr Images.push_back verwenden, außerdem sieht das nicht ganz sauber aus, desshalb hab ich es wie gesagt schon komplett anderes gelöst.
-
Kontrasubjekt schrieb:
nja push_back nimmt referenzen, kopiert nicht.
Natürlich kopiert push_back().
JJ schrieb:
Wahrscheinlich fordert Images beim push_back neuen Speichern an und läßt den alten wieder frei.
Wenn sf::Sprite keine Kopie macht sondern nur die Referenz speichert, passiert genau das. (Wenn der Vektor keinen Speicher mehr hat, verlegt er Kurzerhand alles, weil die Elemente in einem Vektor immer hintereinander liegen müssen.)
Wenn du am Anfang eh schon weißt wie groß dein Vektor ist, kannst du auch resize() nutzen und push_back() vergessen. Dann hast du jedenfalls wieder nur noch eine Schleife. :xmas1:
-
cooky451 schrieb:
Kontrasubjekt schrieb:
nja push_back nimmt referenzen, kopiert nicht.
Natürlich kopiert push_back().
Jep, stimmt. Anfall von verwirrung.^^