I'm not sure myself what has caused this problem. It seems to me that the code that I wrote was right. Even when I cropped it manually (without the getSize().x function to check the sprite's width and pass it to setTextureRect(..) automatically),
the sprite still show unwanted frame.
Sorry if I can't explain the problem well. In short, the
tempSprite.setTextureRect(...) should show 1 frame corresponding to user's input (WSAD movement). Instead, the sprite shown is more than 1 frames, and all of them appear to move (or do run animation) simultaneously.
What's more confusing to me is the "line" that appears behind the character sprite (happens when the sprite 'move up', which is at the bottom of the image)
Here's the sprite image (96 by 128):
And here's the codes:
Main.cpp
Code:
#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
Code:
#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, float textureWidth, float 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
Code:
#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, float textureWidth, float 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
Code:
#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
Code:
#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"))
{
std::cout << "Error loading image\n";
}
else
{
playerAnimation.setTexture(playerTexture);
std::cout << "Loaded the image.png" << std::endl;
// system("pause");
}
}
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 <<"[MoveActive_activated is now FALSE] " << std::endl;
}
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);
}