Henke Henke -4 years ago 211
C++ Question

Sprites do not move in SFML

I am working with my first small project in SFML. I made a ball (projectile) which is bouncing around on the screen and a player which is movable. The problem however, occurred when I tried to make an Objecthandler to my objects. After letting the handler taking control of the drawing and updating of the objects, the player and the ball just stopped and became unmovable. My question is why?
The ball:

#ifndef PROJECTILE_H
#define PROJECTILE_H
#include <SFML\Graphics.hpp>
using namespace std;

class Projectile : public sf::Drawable {

private:
sf::Texture texture;
sf::Sprite sprite;
public:
Projectile();
virtual ~Projectile();
sf::Sprite getSprite() const;
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
};

#endif //PROJECTILE_H

#include "Projectile.h"
#include <iostream>

Projectile::Projectile() {

if (!this->texture.loadFromFile("../Resources/projectile.png")) {
cout << "Error! Projectile sprite could not be loaded!" << endl;
}
this->sprite.setPosition(sf::Vector2f(0.0f, 0.0f));
this->sprite.setTexture(this->texture);
sf::FloatRect boundingBoxProjectile = this->sprite.getGlobalBounds();
}

Projectile::~Projectile() {
}

sf::Sprite Projectile::getSprite() const{
return this->sprite;
}

void Projectile::draw(sf::RenderTarget & target, sf::RenderStates states) const {
target.draw(sprite, states);
}


The handler:

#ifndef OBJECTHANDLER_H
#define OBJECTHANDLER_H
#include "Block.h"
#include "Player.h"
#include "Projectile.h"
using namespace std;

class ObjectHandler : public sf::Drawable {

private:
Player player;
Block block;
Projectile projectile;
int hitX = 0;
int hitY = 0;
float checkX;
float checkY;
float keyFrameDuration = 0.0f;
float speed = 500.0f;
public:
ObjectHandler();
virtual ~ObjectHandler();
void updateProjectile(float dt);
void updatePlayer(float dt);
void updateBlock(float dt);
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
};

#endif OBJECTHANDLER_H

#include "ObjectHandler.h"

ObjectHandler::ObjectHandler() {
this->projectile = projectile;
this->block = block;
this->player = player;
}

ObjectHandler::~ObjectHandler() {
}

void ObjectHandler::updateProjectile(float dt) {
sf::Vector2f direction;

if (hitX == 0) {
direction = sf::Vector2f(0.5f, checkY);
checkX = 0.5f;
if (this->projectile.getSprite().getPosition().x >= 700) {
hitX = 1;
}
}
else if (hitX == 1) {
direction = sf::Vector2f(-0.5f, checkY);
checkX = -0.5f;
if (this->projectile.getSprite().getPosition().x <= 0) {
hitX = 0;
}
}

if (hitY == 0) {
direction = sf::Vector2f(checkX, 0.5f);
checkY = 0.5f;
if (this->projectile.getSprite().getPosition().y >= 460) {
hitY = 1;
}
}
else if (hitY == 1) {
direction = sf::Vector2f(checkX, -0.5f);
checkY = -0.5f;
if (this->projectile.getSprite().getPosition().y <= 0) {
hitY = 0;
}
}

this->projectile.getSprite().move(direction * speed * dt);
}

void ObjectHandler::draw(sf::RenderTarget & target, sf::RenderStates states) const {
this->block.draw(target, states);
this->projectile.draw(target, states);
this->player.draw(target, states);
}


And Game:

#ifndef GAME_H
#define GAME_H

#include <SFML\Graphics.hpp>
#include "ObjectHandler.h"

class Game : public sf::Drawable {
private:
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
sf::Texture backgroundTexture;
sf::Sprite backgroundSprite;
ObjectHandler object;
public:
Game();
virtual ~Game();
void update(float dt);
};

#endif // GAME_H

#include "Game.h"
#include <iostream>
using namespace std;

void Game::draw(sf::RenderTarget & target, sf::RenderStates states) const {
target.draw(backgroundSprite, states);
target.draw(this->object, states);
}

Game::Game() {
if (!backgroundTexture.loadFromFile("../Resources/levelOne.jpg")) {
cout << "The background could not be loaded!" << endl;
}
backgroundSprite.setTexture(backgroundTexture);
}

Game::~Game() {
}

void Game::update(float dt) {
this->object.updatePlayer(dt);
this->object.updateProjectile(dt);
this->object.updateBlock(dt);
}

Answer Source

The problem is your sf::Sprite Projectile::getSprite()const returns a copy of the actual sprite. Hence projectile.getSprite().move(...) are called by the copy.

Make a method move for your Projectile:

void Projectile::move(const sf::Vector2f& amount)
{
    sprite.move(amount);
} 

and call it in ObjectHandler: projectile.move(...).

You might also want to return a constant reference to your sprite in getSprite to avoid multiple copies: const sf::Sprite& Projectile::getSprite()const. It will cause an error when you try to modify it by calling projectile.getSprite().move(...) and you will see the bug faster.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download