I am trying to use spritesheets in SFML. My Player class inherits from the Creature class which inherits from the Entity class. I only see a white square when I render the player. However, this is not the case when I create the sprite and render it in the same function. It does not work if I return a copy or even a reference or a pointer of the sprite. So, I tried constructing my sprite in the constructor rather than the init()
method. It still does not work when I return the sprite for drawing via the draw()
method in entity.cpp. I do not want to load the sprite from the spritesheet in the draw method as that would be fairly inefficient. Please help.
spritehseet.png: https://i.sstatic.net/H9JzO.jpg
main.cpp:
bool init() {
/*Code to determine if a player should be added to entities and creatures vectors*/
case 'P':
player = new Player(i*64, y*64, 64, 64, sf::IntRect(0, 0, 64, 64), "spritesheet.png", &entities);
entities.push_back(player);
creatures.push_back(player);
break;
/*more code for quitting and error reporting*/
}
int main() { // vertical sync works well only in full screen mode
sf::RenderWindow window(sf::VideoMode(0, 0), "My First SFML Game", sf::Style::Fullscreen);
int frames = 0;
window.setVerticalSyncEnabled(true);
if(!init()) {
std::cout << "Could not initialize\n";
return 1;
}
sf::Clock clock, frameClock;
/*keyboard and event polling code here*/
if(frameClock.getElapsedTime().asSeconds() >= 1/FPS) {
update();
draw(window);
window.display();
window.clear();
frames++;
frameClock.restart();
}
if(clock.getElapsedTime().asSeconds() >= 1) {
std::cout << frames << " frames per second\n";
clock.restart();
frames = 0;
}
}
std::cout << "Quitting\n";
quit();
}
void quit() {
std::vector<Entity*>::iterator it;
for(it = entities.begin(); it != entities.end(); it++) {
delete *it;
*it = nullptr;
}
entities.clear();
player = nullptr;
std::vector<Creature*>::iterator it2;
for(it2 = creatures.begin(); it2 != creatures.end(); it2++) {
*it2 = nullptr;
}
}
void update() {
std::vector<Creature*>::iterator it;
for(it = creatures.begin(); it != creatures.end(); it++) {
Creature* creature = *it;
creature->update();
}
}
void draw(sf::RenderWindow& window) {
std::vector<Entity*>::iterator it;
for(it = entities.begin(); it != entities.end(); it++) {
Entity* entity = *it;
window.draw(entity->draw());
}
}
entity.h:
#ifndef ENTITY_H
#define ENTITY_H
#include <SFML/Graphics.hpp>
#include <string>
class Entity {
private:
int _x, _y, _width, _height;
sf::Sprite _sprite;
public:
Entity(int x, int y, int width, int height, sf::IntRect rect, std::string path);
int getX() { return _x; }
int getY() { return _y; }
int getWidth() { return _width; }
int getHeight() { return _height; }
void setX(int x) { _x = x; }
void setY(int y) { _y = y; }
void setWidth(int width) { _width = width; }
void setHeight(int height) { _height = height; }
sf::Sprite draw();
};
#endif // ENTITY_H
entity.cpp:
#include <entity.h>
#include <string>
#include <iostream>
#include <SFML/Graphics.hpp>
Entity::Entity(int x, int y, int width, int height, sf::IntRect rect, std::string path) {
_x = x;
_y = y;
_width = width;
_height = height;
sf::Texture texture;
if(!texture.loadFromFile(path, rect)) std::cout << "Could not load intrect " << rect.left << ", "
<< rect.top << ", "
<< rect.width << ", "
<< rect.height << " from" << path;
else std::cout << "loaded texture\n";
_sprite.setTexture(texture);
}
sf::Sprite Entity::draw() {
_sprite.setPosition(sf::Vector2f(_x, _y));
return _sprite;
}
The rest of the constructors don't do anything with the sprite.