jburn7 jburn7 - 1 month ago 10
C++ Question

Where is my sfml texture going out of scope at?

So I have the infamous white square issue (again) and this time I'm returning references wherever possible, but to no avail. I have a

Level
that holds a vector of
GamePieces
, and each
GamePiece
object holds an
sf::sprite
. Here's the code trying to draw a sprite from
GamePiece
:

Engine.h:

#pragma once
#include "stdafx.h"
#include "SFML/Graphics.hpp"
#include "ImageManager.h"
#include "Level.h"
#include "GamePiece.h"

class Engine{
public:
Engine();
~Engine();

void Go();
private:
void ProcessInput();
void UpdateCPU();
void Render();

sf::RenderWindow window;

ImageManager imgr;
Level level;
};


Engine's function that does the drawing:

void Engine::Render(){
window.clear();
//draw wall tiles
for(int i = 0; i < 160; i++){
if(i < 60){
level.GetWallTile().setPosition(0, i * 10);
window.draw(level.GetWallTile());
}
if(i >= 60 && i < 100){
level.GetWallTile().setPosition((i - 60) * 10, 590);
window.draw(level.GetWallTile());
}
if(i >= 100){
level.GetWallTile().setPosition(390, (i - 100) * 10);
window.draw(level.GetWallTile());
}
}

//draw BG tiles
for(int i = 1; i < 39; i++){
for(int j = 0; j < 59; j++){
level.GetBGTile().setPosition(i * 10, j * 10);
window.draw(level.GetBGTile());
}
}
for(int i = 0; i < level.GetGamePieces().size(); i++){
window.draw(level.GetGamePieces()[i].GetPieceSprite());
}

window.display();
}


Keep in mind that the
wallTile
's and
bgTile
's are drawing just fine, it's that last for loop that's giving me white squares.

Here are the relevant functions and classes:

//level.h
#pragma once
#include "stdafx.h"
#include "SFML/Graphics.hpp"
#include "ImageManager.h"
#include "GamePiece.h"

class Level{
public:
Level(ImageManager &im);
~Level();

sf::Sprite &GetWallTile();
sf::Sprite &GetBGTile();

void AddPiece();
std::vector<GamePiece> &GetGamePieces();
private:
ImageManager &imgr;
//not sure if vector needed, or one sprite
//std::vector<sf::Sprite> wallTiles_;
sf::Sprite wallTile;
//std::vector<sf::Sprite> bgTiles_;
sf::Sprite bgTile;
std::vector<GamePiece> gamePieces_;
};
//Level.cpp
#include "stdafx.h"
#include "Level.h"

Level::Level(ImageManager &im) : imgr(im){
im.AddResourceDirectory("images/");
wallTile.setTexture(im.GetImage("walltile1.png"));
bgTile.setTexture(im.GetImage("bgtile1.png"));
AddPiece();
}

Level::~Level(){

}

void Level::AddPiece(){
GamePiece piece(imgr);
gamePieces_.push_back(piece);
}

std::vector<GamePiece> &Level::GetGamePieces(){
return gamePieces_;
}

//GamPiece.h
class GamePiece{
public:
GamePiece(ImageManager &im);
~GamePiece();

void SetShape();
sf::Sprite &GetPieceSprite();
private:
ImageManager &imgr;
sf::Sprite pieceShape;
};
//and GamePiece.cpp

#include "stdafx.h"
#include "GamePiece.h"

GamePiece::GamePiece(ImageManager &im) : imgr(im){
SetShape();
}

GamePiece::~GamePiece(){

}

void GamePiece::SetShape(){
//int temp = rand() % 7;
int temp = 0;
switch(temp){
case 0:
pieceShape.setTexture(imgr.GetImage("line.png"));
case 1:
pieceShape.setTexture(imgr.GetImage("llblock.png"));
case 2:
pieceShape.setTexture(imgr.GetImage("rlblock.png"));
case 3:
pieceShape.setTexture(imgr.GetImage("square.png"));
case 4:
pieceShape.setTexture(imgr.GetImage("lsquiggly.png"));
case 5:
pieceShape.setTexture(imgr.GetImage("rsquiggly.png"));
case 6:
pieceShape.setTexture(imgr.GetImage("tblock.png"));
}
}

sf::Sprite &GamePiece::GetPieceSprite(){
return pieceShape;
}


Lots of code, I know, but I really don't know where the texture is going out of scope, assuming that's what's wrong. Looking at similar posts, that's probably the issue, but again, I need help finding it.

Answer
void Level::AddPiece() {
    GamePiece piece(imgr);
    gamePieces_.push_back(piece);
    piece.SetShape();
}

piece is being copied into the vector. The element that resides in the vector is not associated with the object that it was copied from (the one that is bound to the scope of AddPiece()). Therefore any actions taken on piece do not affect the element that was inserted.

If you need to access the element that previously push_back()'ed, then use back() to return a reference to it:

gamePieces_.back().SetShape();

You could have also just called SetShape() before inserting it into the vector.

Comments