Working with SFML - can't display image?

Started by
9 comments, last by Meerul264 11 years, 3 months ago

The screen is blank, no sprite shows up and I dunno what to do.

Main.cpp:

#include <SFML/Graphics.hpp>
#define SCREENWIDTH 800
#define SCREENHEIGHT 600
#include "Animation.h"
#include "Player.h"
int main()
{
sf::RenderWindow Window(sf::VideoMode(SCREENWIDTH,SCREENHEIGHT,32), "SFML ADVANCED ANIMATION TUTORIAL");
Player player;
player.Initialize();
player.LoadContent();
while(Window.isOpen())
{
sf::Event Event;
while(Window.pollEvent(Event))
{
if(Event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
Window.close();
}
player.Update(Window);
player.Draw(Window);
Window.clear();
Window.display();
}
return 0;
}

Animation.h:

#ifndef ANIMATION_H
#define ANIMATION_H
#include <SFML/Graphics.hpp>
class Animation
{
public:
Animation();
~Animation();
void Initialize(float x,float y, int FrameX, int FrameY);
void isOpen();
void Update(sf::RenderWindow &Window);
void Draw(sf::RenderWindow &Window);
bool getActive();
void setActive(bool value);
int getCurrentFrame(int axis);
void setCurrentFrame(int axis, int value);
float getPosition(int axis);
float setPosition(int axis, int value);
void setTexture(sf::Texture &spriteTexture);
protected:
int getFrameWidth();
int getFrameHeight();
private:
sf::Texture spriteTexture;
sf::Sprite spriteImage;
sf::Clock Clock;
int currentFrameX, currentFrameY;
float frameCounter, switchFrame;
float frameTime;
int amountOfFramesX, amountOfFramesY;
float x, y;
bool active;
};
#endif //ANIMATION_H

Animation.cpp:

#include <SFML/Graphics.hpp>
#include <iostream>
#include "Animation.h"
Animation::Animation()
{
}
Animation::~Animation()
{
}
int Animation::getFrameWidth()
{
return spriteTexture.getSize().x / amountOfFramesX;
}
int Animation::getFrameHeight()
{
return spriteTexture.getSize().y / amountOfFramesY;
}
bool Animation::getActive()
{
return active;
}
void Animation::setActive(bool value)
{
active = value;
}
int Animation::getCurrentFrame(int axis)
{
if(axis == 1)
return currentFrameX;
else
return currentFrameY;
}
void Animation::setCurrentFrame(int axis, int value)
{
if(axis == 1)
currentFrameX = value;
else
currentFrameY = value;
}
float Animation::getPosition(int axis)
{
if(axis == 1)
return x;
else
return y;
}
float Animation::setPosition(int axis, int value)
{
if(axis == 1)
x = value;
else
y = value;
}
void Animation::setTexture(sf::Texture &spriteTexture)
{
spriteImage.setTexture(spriteTexture);
std::cout << "loaded 2\n";
}
void Animation::Initialize(float x,float y, int FrameX, int FrameY)
{
frameCounter = 0;
switchFrame = 1;
active = false;
this->x = x;
this->y = y;
this->amountOfFramesX = FrameX;
this->amountOfFramesY = FrameY;
std::cout << "init2\n";
}
void Animation::isOpen()
{
Clock.restart();
}
void Animation::Update(sf::RenderWindow &Window)
{
frameTime = Clock.getElapsedTime().asSeconds();
if(active)
frameCounter += frameTime;
else
frameCounter = 0;
if(frameCounter >= switchFrame)
{
frameCounter = 0;
currentFrameX += getFrameWidth();
if(currentFrameX >= spriteTexture.getSize().x)
currentFrameX = 0;
}
spriteImage.setTextureRect(sf::IntRect(currentFrameX, currentFrameY * getFrameHeight(), currentFrameX + getFrameWidth(), currentFrameY * getFrameHeight() + getFrameHeight()));
spriteImage.setPosition(x, y);
}
void Animation::Draw(sf::RenderWindow &Window)
{
Window.draw(spriteImage);
}

Player.h:

#ifndef PLAYER_H
#define PLAYER_H
#include <SFML/Graphics.hpp>
#include "Animation.h"
class Player
{
public:
Player();
~Player();
void Initialize();
void LoadContent();
void Update(sf::RenderWindow &Window);
void Draw(sf::RenderWindow &Window);
protected:
Animation playerAnimation;
private:
sf::Texture playerTexture;
sf::Clock clock;
float x, y;
int currentFrameX, currentFrameY;
float moveSpeed;
};
#endif //PLAYER_H

Player.cpp:

#include <SFML/Graphics.hpp>
#include <iostream>
#include "Player.h"
Player::Player()
{
}
Player::~Player()
{
}
void Player::Initialize()
{
x = 0;
y = 0;
moveSpeed = 200;
currentFrameX = 0;
currentFrameY = 0;
playerAnimation.Initialize(x,y,3,4);
std::cout << "init\n";
}
void Player::LoadContent()
{
if(playerTexture.loadFromFile("C:/Program Files (x86)/CodeBlocks/Projects/SFML Animation Advanced tutorial/resource/Animation/Cloaked dude.png"))
playerAnimation.setTexture(playerTexture);
std::cout << "loaded" << std::endl;
}
void Player::Update(sf::RenderWindow &Window)
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)) //UP
{
y -= moveSpeed * clock.getElapsedTime().asSeconds();
currentFrameY = 3;
std::cout << "moved up\n";
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S)) //DOWN
{
y += moveSpeed * clock.getElapsedTime().asSeconds();
currentFrameY = 0;
std::cout << "moved down\n";
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)) //LEFT
{
x -= moveSpeed * clock.getElapsedTime().asSeconds();
currentFrameY = 1;
std::cout << "moved left\n";
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D)) //RIGHT
{
x += moveSpeed * clock.getElapsedTime().asSeconds();
currentFrameY = 2;
std::cout << "moved right\n";
}
else
{
playerAnimation.setActive(false); //if player not pressing any button
}
playerAnimation.setPosition(1,x);
playerAnimation.setPosition(2,y);
playerAnimation.setCurrentFrame(2,currentFrameY);
playerAnimation.Update(Window);
}
void Player::Draw(sf::RenderWindow &Window)
{
playerAnimation.Draw(Window);
}

Advertisement

read over your rendering logic:


player.draw(); //draw the player
window.clear(); //clear what we've drawn
window.display(); //output what we drew, but since we've cleared it, their's nothing to display.

i'm not familiar with sfml's internal workings, but if it's like any other sane rendering api, then your problem is that you clear w/e you draw, before you display it.

Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

Thanks, but the sprite still isn't showing up :(

I think something's wrong with the updating part, since the image of Coaked dude.png shows up (and obviously its the full pic not the cropped ones) when I commented out the player.Update(Window).

Problems

one:

  • player.Update(Window);
  • player.Draw(Window);
  • Window.clear();
  • Window.display();

Window.clear();

Clears whole buffer with black color

move the Window.clear() before all drawing or do all drawings after the function

Rest seams fine, your image is loaded and sfml has its own system to display to console if the image location is invalid

Also from glimpse of your code at Player::Update() when you don't move you set


playerAnimation.setActive(false); //if player not pressing any button

but when you move you don't set it to true

Two

This in "Animation.cpp" At line 99

  • if(active)
  • frameCounter += frameTime;
  • else
  • frameCounter = 0;
  • if(frameCounter >= switchFrame)
  • {
  • frameCounter = 0;
  • currentFrameX += getFrameWidth();
  • if(currentFrameX >= spriteTexture.getSize().x)
  • currentFrameX = 0;
  • }
  • spriteImage.setTextureRect(sf::IntRect(currentFrameX, currentFrameY * getFrameHeight(), currentFrameX + getFrameWidth(), currentFrameY * getFrameHeight() + getFrameHeight()));
  • spriteImage.setPosition(x, y);
  • }

You set the crop here as it seems.

spriteImage.setTextureRect(sf::IntRect(X, Y, Width, Height));

If there is problem with crop, check values your passing here.

Getting closer: it seems that the

  1. int Animation::getFrameWidth()
  2. {
  3. return spriteTexture.getSize().x / amountOfFramesX;
  4. }

from Animation.cpp, the spriteTexture.getSize().x returns value 0. So does the Y part. Anyone have any clue why it gives 0, instead of the actual size of the image, which is 96 by 128?

I even tried cast it to float but still

it seems that I have trouble with currentFrameX. All the varaibles in

spriteImage.setTextureRect(sf::IntRect(currentFrameX, currentFrameY * getFrameHeight(), currentFrameX + getFrameWidth(), currentFrameY * getFrameHeight() + getFrameHeight()));

Have the correct values, except for currentFrameX, with values of 1900000yadayada.

I highly suggest finding the mistake you self, you will learn to fix code / find errors and dozen other essential skills needed for programing.

Well, the code for changing frames is slightly convoluted.

How about using a single variable to mark the current frame:

unsigned int currentFrame = 0;

To change a frame you increment it, then check if we've reached the end.

currentFrame++; if(currentFrame >= (numFramesWide * numFramesHigh)) { currentFrame = 0; }

To calculate the x,y image in the imagesheet:

imageX = (currentFrame % numFramesWide); imageY = (currentFrame / numFramesWide);

To calculate the pixel location of the image:

pixelX = (imageX * ImageWidth); pixelY = (imageY * imageHeight);

It's easier to just keep track of one variable (currentFrame), then to juggle multiple variables, especially when you can calculate the multiple variables from currentFrame and the constants.

Also the whole 'axis' thing with your functions, where the functions return a different variable with different meaning depending on what magic numbers you pass in is not a good programming idea unless there is a very good reason to do so.

I'm talking about this:

float setPosition(int axis, int value);

And this:

playerAnimation.setPosition(1,x); playerAnimation.setPosition(2,y);

And why does setPosition() say it returns a float, but never does? It'll return gibberish, which you might accidentally be assigning to your currentFrameX somewhere.

setPosition() should take the x AND y positions, or else should have a separate function for each one.

setPositionX(int x); setPositionY(int y); getPositionX(); getPositionY();

Personally, I prefer using some kind of "Point" struct myself. SFML provides one for you if you don't want to use your own: sf::Vector2i (for ints) and sf::Vector2f (for floats).

Thanks for all the replies. Now I redo the codes and make a little change to the previous codes. The problem now is that there are more than one frame being drawn on the screen. I checked the x1 y1 and x2 y2 of the cropped image using sf::setTextureRect(..), and it shows the correct frames with corresponding input. But it also shows the frame next to the right of 'correct frames'.

Please help I've spent hours checking but failed to see the cause of this problem.

main.cpp

#include <SFML/Graphics.hpp>
#include <iostream>
#define ScreenWidth 800
#define ScreenHeight 600
#include "Player.h"
int main()
{
sf::RenderWindow Window(sf::VideoMode(ScreenWidth,ScreenHeight,32),"SFML ADVANCED SPRITE TUTORIAL 2");
Player player;
player.LoadTexture();
player.Initialize();
while(Window.isOpen())
{
sf::Event Event;
while(Window.pollEvent(Event))
{
if(Event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
Window.close();
}
}//END EVENT LOOP
Window.clear();
player.Update(Window);
player.Draw(Window);
Window.display();
system("cls");
}
return 0;
}
Animation.h
#ifndef ANIMATION_H
#define ANIMATION_H
class Animation
{
public:
Animation();
virtual ~Animation();
void setTexture(sf::Texture &tempTexture);
void Draw(sf::RenderWindow &Window);
void Update(sf::RenderWindow &Window);
void Initialize(float &x, float &y, int amountOfFramesX, int amountOfFramesY, int textureWidth, int textureHeight);
float getPositionX(float &x);
float getPositionY(float &y);
float getFrameHeight();
float getFrameWidth();
bool getMoveActive();
void setMoveActive(bool MoveActive);
void setCurrentFrameY(int FrameY);
protected:
private:
sf::Texture tempTexture;
sf::Sprite tempSprite;
float x, y;
float move_x;
float move_y;
float frameHeight, frameWidth;
int amountOfFramesX, amountOfFramesY;
int textureWidth, textureHeight;
bool MoveActive_activated;
int currentFrameX, currentFrameY;
};
#endif // ANIMATION_H

Animation.cpp

#include <SFML/Graphics.hpp>
#include <iostream>
#include "Animation.h"
Animation::Animation()
{
//ctor
}
Animation::~Animation()
{
//dtor
}
bool Animation::getMoveActive()
{
return MoveActive_activated;
}
void Animation::setMoveActive(bool MoveActive)
{
MoveActive_activated = MoveActive;
}
void Animation::setCurrentFrameY(int FrameY)
{
currentFrameY = FrameY;
}
void Animation::Initialize(float &x, float &y, int amountOfFramesX , int amountOfFramesY, int textureWidth, int textureHeight)
{
this-> x = x;
this-> y = y;
this-> amountOfFramesX = amountOfFramesX;
this-> amountOfFramesY = amountOfFramesY;
this-> textureWidth = textureWidth;
this-> textureHeight = textureHeight;
currentFrameY = 0;
}
float Animation::getFrameWidth()
{
frameWidth = (float) textureWidth / amountOfFramesX;
return frameWidth;
}
float Animation::getFrameHeight()
{
frameHeight = (float) textureHeight / amountOfFramesY;
return frameHeight;
}
float Animation::getPositionX(float &x)
{
move_x = x;
return move_x;
}
float Animation::getPositionY(float &y)
{
move_y = y;
return move_y;
}
void Animation::Update(sf::RenderWindow &Window)
{
std::cout << "setPosition move_x: " << move_x << std::endl;
std::cout << "setPosition move_y: " << move_y << std::endl;
std::cout << "frameWidth: " << getFrameWidth() << std::endl;
std::cout << "frameHeight: " << getFrameHeight() << std::endl;
std::cout << "Texture width: " << textureWidth << std::endl;
std::cout << "Texture height: " << textureHeight << std::endl;
std::cout << "Amount of frames X: " << amountOfFramesX << std::endl;
std::cout << "Amount of frames Y: " << amountOfFramesY << std::endl;
std::cout << "-----------" << std::endl;
std::cout << "currentFrameX: " << currentFrameX << std::endl;
std::cout << "currentFrameY: " << currentFrameY << std::endl << std::endl;
std::cout << "In tempSprite.setTextureRect(sf::IntRect(x1,y1,x2,y2)) : " << std::endl << std::endl;
std::cout << "x1: " << currentFrameX * frameWidth << std::endl;
std::cout << "y1: " << currentFrameY * frameHeight << std::endl;
std::cout << "x2: " << currentFrameX * frameWidth + frameWidth << std::endl;
std::cout << "y2: " << currentFrameY * frameWidth + frameHeight << std::endl;
if(MoveActive_activated)
{
std::cout <<"[MoveActive_activated is now TRUE] " << std::endl;
currentFrameX++;
if((frameWidth * currentFrameX) >= (frameWidth*amountOfFramesX))
{
currentFrameX = 0;
}
}
else
{
currentFrameX = 1;
}
tempSprite.setTextureRect(sf::IntRect( currentFrameX * frameWidth , currentFrameY * frameHeight , (currentFrameX * frameWidth) + frameWidth , (currentFrameY * frameHeight) + frameHeight ));
tempSprite.setPosition(move_x,move_y);
}
void Animation::setTexture(sf::Texture &tempTexture)
{
tempSprite.setTexture(tempTexture);
}
void Animation::Draw(sf::RenderWindow &Window)
{
Window.draw(tempSprite);
}
Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "Animation.h"
class Player
{
public:
Player();
virtual ~Player();
Animation playerAnimation;
void LoadTexture();
void Initialize();
void Draw(sf::RenderWindow &Window);
void Update(sf::RenderWindow &Window);
protected:
private:
sf::Texture playerTexture;
int textureWidth, textureHeight;
float x , y;
float moveSpeed;
};
#endif // PLAYER_H

Player.cpp

#include <SFML/Graphics.hpp>
#include <iostream>
#include "Player.h"
#include "Animation.h"
Player::Player()
{
//ctor
}
Player::~Player()
{
//dtor
}
void Player::LoadTexture()
{
if(playerTexture.loadFromFile("C:/Program Files (x86)/CodeBlocks/Projects/SFML ANIMATION ADVANCED TUTORIAL 2/resources/Cloaked dude.png"))
{
playerAnimation.setTexture(playerTexture);
std::cout << "Loaded the image Cloaked dude.png" << std::endl;
}
}
void Player::Initialize()
{
std::cout << "Initializing from Player::Initialize()..." << std::endl;
x = 0;
y = 0;
moveSpeed = 10;
textureWidth = playerTexture.getSize().x;
textureHeight = playerTexture.getSize().y;
playerAnimation.Initialize(x,y,3,4,textureWidth,textureHeight);
}
void Player::Update(sf::RenderWindow &Window)
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)) //UP
{
playerAnimation.setMoveActive(true);
y -= moveSpeed;
playerAnimation.setCurrentFrameY(3);
std::cout << "Moved up" << std::endl;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S)) //DOWN
{
playerAnimation.setMoveActive(true);
y += moveSpeed;
playerAnimation.setCurrentFrameY(0);
std::cout << "Moved down" << std::endl;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)) //LEFT
{
playerAnimation.setMoveActive(true);
x -= moveSpeed;
playerAnimation.setCurrentFrameY(1);
std::cout << "Moved left" << std::endl;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D)) //RIGHT
{
playerAnimation.setMoveActive(true);
x += moveSpeed;
playerAnimation.setCurrentFrameY(2);
std::cout << "Moved right" << std::endl;
}
else
{
playerAnimation.setMoveActive(false);
}
std::cout << "x-position: " << x << std::endl;
std::cout << "y-position: " << y << std::endl;
std::cout << "moveSpeed : " << moveSpeed << std::endl;
playerAnimation.getPositionX(x);
playerAnimation.getPositionY(y);
playerAnimation.Update(Window);
}
void Player::Draw(sf::RenderWindow &Window)
{
playerAnimation.Draw(Window);
}

This topic is closed to new replies.

Advertisement