Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Sprite animation problem (SFML 2.0)  (Read 6678 times)

0 Members and 1 Guest are viewing this topic.

Nezaja

  • Newbie
  • *
  • Posts: 6
    • View Profile
Sprite animation problem (SFML 2.0)
« on: March 16, 2013, 06:19:34 pm »
Firstly i want to say Hello! Im new to the SFML and i hope my questions and problems won't be incredibly stupid. I'm not very experienced programmer (at least in c++, i know Java better, but since C++ is the father/mother of object oriented programming languages it will not be a big problem for me to learn, well i can say that i can write sth :D). I love games and i play them a lot, but i want try to make my own (i already play with 3D graphics, i make 3D models, nothing special or fantastic, but it's mine and i like it, now i want to learn firstly 2D gaming development and then i can step higher to the 3D), because i feel that developing a game is much more fun than playing it ;). I have some ideas in my head and i want to make them come true, don't know if i win, but at least i will try ;)

So thats all about me, let's get to the topic ;). I'm sorry for my english, it is not perfect, but i always try my best so everyone can understand what i write/say ;)

Can anyone give me any advice what have i done wrong in my code, that my character doesn't move corectly? I want to animate character using sprite animation, with this crop thingy ;). I followed CodeMadeMeEasy tutorial about animations. When i made it while i was learning this thing, it was ok, but when i want to implement animation in my own game it doesn't work. I mean, the characeter moves, but he's movements are not animated (he just slides :D)

SFML 2.0
Microsoft Visual Studio 2012 Ultimate (student version :D)
Windows 7 x64

Player.h content

Code: [Select]
#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstdlib>
#include <ctime>
#pragma once;


class Player{

       private:
     
               sf::Texture ptexture;
       sf::Sprite pimage;

public:

int health, intelect, strenght, agility, mana,id;


Player(int a,int b,int c,int d,int e,int g) : health(a),intelect(b),strenght(c),agility(d),mana(e),id(g){

//loading sprite
if(!ptexture.loadFromFile("Player.png"))
std::cout << "Could not open the img from file!" << std::endl;

pimage.setTexture(ptexture);
};

Player& movement(Player* p);

};

Player.cpp content

Code: [Select]
#include "Player.h"


Player& Player::movement(Player* p){

float frameCounter = 0, switchFrame = 100, frameSpeed = 500;
enum Direction{Left,Right};

sf::Vector2i source(1,Right);
sf::Clock clock;


if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
source.y = Right;
p->pimage.move(2,0); //(x,y)
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
source.y = Left;
p->pimage.move(-2,0); //(x,y)
}

frameCounter += frameSpeed * clock.restart().asSeconds();
if(frameCounter >= switchFrame)
{
frameCounter = 0;
source.x++;
if(source.x * 32 >= p->ptexture.getSize().x)
source.x = 0;
}
//should crop the right image
p->pimage.setTextureRect(sf::IntRect(source.x * 32, source.y*32,32,32));

return *this;
}

main.cpp content

Code: [Select]
#include "Player.h"

int main(){

sf::Vector2f screenDimensions(800,600);

sf::RenderWindow Window(sf::VideoMode(screenDimensions.x,screenDimensions.y),"Magic Cataclysm");
Window.setFramerateLimit(60);
Player* player1 = new Player(1,2,3,4,5,6);
player1 -> pimage.setPosition(0,536);


//program works as long as window is open
while(Window.isOpen()){

sf::Event Event;

while(Window.pollEvent(Event)){

switch(Event.type){

//when the player click close, program terminates
case sf::Event::Closed:
Window.close();
break;
}

}
                         player1->movement(player1);
//render the player
Window.draw(player1->pimage);
Window.display();
Window.clear();


}

return 0;

}

In the attachment is an image that i try to animate generated by http://www.famitsu.com/freegame/tool/chibi/index1.html

Thanks in advance for any help :)

[attachment deleted by admin]
« Last Edit: March 16, 2013, 07:00:45 pm by Nezaja »

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #1 on: March 16, 2013, 07:14:45 pm »
float frameCounter = 0, switchFrame = 100, frameSpeed = 500;
...
frameCounter += frameSpeed * clock.restart().asSeconds();
if(frameCounter >= switchFrame)
This is what happens everytime you call movement.
frameCounter is greater than switchFrame (100) only when clock.restart().asSeconds() returns 0.2 (200 ms), which is a lot of time for a single frame and probably never happens.

There are animation classes in the wiki if you want some better example. ;)

BTW, use the [ code=cpp] tag when posting C++ code. :)
« Last Edit: March 16, 2013, 07:18:29 pm by G. »

Nezaja

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #2 on: March 16, 2013, 07:22:01 pm »


I used this tutorial, and everything worked when i wrote letter to letter code that this guy made. Unfortunately my version doesn't work. I know what u mean, but i dont understand why in other project when i use this guy code it works, but mine doesnt :). It is basicly the same, but i dont use Up and Down key event ;)

When i set switchFrame = 1 and frameSpeed = 500000 frameCounter is always greater than switchFrame, and animations still doesn't work

also this works like every frame it counts frameCount so in my case it is 0.003 * 500 wchich gives 1,5 and when sum of 1,5+1,5+1,5+1,5.......... is greater or equal to Swtich frame (100) it takes second sprite for animations so the animations doesn't update every frame per sec :).

In my case i see that frameCounter doesn't udpate it is all the tame same as frameSpeed * clock.restart().asSeconds().


« Last Edit: March 16, 2013, 07:50:18 pm by Nezaja »

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #3 on: March 16, 2013, 10:39:21 pm »
As I said, what I quoted is what happens every frame.
Your frameCounter has no persistence and is always 0 at the start of the movement function. There is no "sum of 1,5+1,5+1,5+1,5+..." in your code, there is only a sum of 0 + 1,5. ;)

In CME video, there is only one frameCounter variable, it is initialized only once, and resetted to 0 only when the animation is switched.

Nezaja

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #4 on: March 17, 2013, 06:53:58 am »
So i did and update, now i have

Player.h

#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstdlib>
#include <ctime>
#pragma once;


class Player{


        public:
               
                int health, intelect, strenght, agility, mana,id;
                sf::Texture ptexture;
                sf::Sprite pimage;


                Player(int a,int b,int c,int d,int e,int g) : health(a),intelect(b),strenght(c),agility(d),mana(e),id(g){

                        //loading sprite
                        if(!ptexture.loadFromFile("Player.png"))
                                std::cout << "Could not open the img from file!" << std::endl;

                        pimage.setTexture(ptexture);
                };

                float movement(Player* p, float frameCounter, float switchFrame, float frameSpeed, sf::Clock clock);
                //float frameUpdate(float frameCounter);
               
};
 

Player.cpp

#include "Player.h"


float Player::movement(Player* p, float frameCounter, float switchFrame, float frameSpeed, sf::Clock clock){

       
        enum Direction{Left,Right};

        sf::Vector2i source(1,Right);
               
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
                        source.y = Right;
                        p->pimage.move(2,0); //(x,y)
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
                        source.y = Left;
                        p->pimage.move(-2,0); //(x,y)
                }

                frameCounter += frameSpeed * clock.restart().asSeconds();
                std::cout << "FRAME " << frameCounter << std::endl;
                if(frameCounter >= switchFrame)
                {
                        std::cout << "FRAME COUNTER INSIDE IF" << frameCounter << std::endl;
                        frameCounter = 0;
                        std::cout << "FRAME COUNTER INSIDE IF AFTER 0" << frameCounter << std::endl;
                        source.x++;
                        if(source.x * 32 >= p->ptexture.getSize().x)
                                source.x = 0;
                       
                }
                //should crop the right image
                p->pimage.setTextureRect(sf::IntRect(source.x * 32, source.y*32,32,32));
               
                return frameCounter;
               
}
 

main.cpp

#include "Player.h"

int main(){

        sf::Vector2f screenDimensions(800,600);

        sf::RenderWindow Window(sf::VideoMode(screenDimensions.x,screenDimensions.y),"Magic Cataclysm");
        Window.setFramerateLimit(30);
        Player* player1 = new Player(1,2,3,4,5,6);
        player1 -> pimage.setPosition(0,536);
        /*this i changed*/
        float frameCounter = 0, switchFrame = 100, frameSpeed = 500;
        sf::Clock clock;

        //program works as long as window is open
        while(Window.isOpen()){

                sf::Event Event;

                        while(Window.pollEvent(Event)){

                                switch(Event.type){

                                //when the player click close, program terminates
                                case sf::Event::Closed:
                                        Window.close();
                                        break;

                                }

                        }
                        /*this is what i changed*/
                        frameCounter = player1->movement(player1, frameCounter, switchFrame, frameSpeed, clock);
                        std::cout << "FRAME COUNTER OUTSIDE " << frameCounter << std::endl;
                        //render the player
                        Window.draw(player1->pimage);
                        Window.display();
                        Window.clear();


        }

        return 0;

}

 

i commented the stuff i changed, now my method returns frameCounter

float frameCounter = 0, switchFrame = 100, frameSpeed = 500;
 

I initialized it outside the loop and outside the movement method, so the frameCounter is not 0 all the time. It updates now, but, animation still does not work  properly. I did some console check



It appears that my method does not return frameCounter properly but the cout outside the method shows frameCounter = 0, but it still goes infinity inside this function.

When i run CME tutorial code it gives me this



FRAME is frameCounter before if statement
FRAME2 is frameCounter after "if" statement

This is the tutorial code

#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
//#include <cstdlib>
//#include <ctime>

int main(){

        enum Direction {Down,Left,Right,Up};

        sf::Vector2i source(1,Down);
        sf::Vector2i screenDimensions(800,600);
        sf::Vector2i blockDimensions(10,10);

        float frameCounter = 0, switchFrame = 100, frameSpeed = 500;

        sf::RenderWindow Window(sf::VideoMode(screenDimensions.x,screenDimensions.y),"My First Game");
        Window.setFramerateLimit(30);

        sf::Texture pTexture;
        sf::Sprite playerImage;
        sf::Clock clock;

        bool updateFrame = true;

        if(!pTexture.loadFromFile("Player.png"))
                std::cout <<"Error could not load player image" <<std::endl;

        playerImage.setTexture(pTexture);

while(Window.isOpen()){

                sf::Event Event;
                while(Window.pollEvent(Event)){

                        switch(Event.type){

                        case sf::Event::Closed:
                                Window.close();
                                break;
                        }

                }

               

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
                        source.y = Up;
                        playerImage.move(0,-2); //(x,y)
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){
                        source.y = Down;
                        playerImage.move(0,2); //(x,y)
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
                        source.y = Right;
                        playerImage.move(2,0); //(x,y)
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
                        source.y = Left;
                        playerImage.move(-2,0); //(x,y)

                        //kalwiatura
                }
               
                frameCounter += frameSpeed * clock.restart().asSeconds();
                std::cout << "FRAME " << frameCounter << std::endl;
                if(frameCounter >= switchFrame)
                {
                        frameCounter = 0;
                        source.x++;
                        if(source.x * 32 >= pTexture.getSize().x)
                                source.x = 0;
                }
                std::cout << "FRAME2  " << frameCounter << std::endl;
                playerImage.setTextureRect(sf::IntRect(source.x * 32, source.y*32,32,32));

                Window.draw(playerImage);
                Window.display();
                Window.clear();
        }

        return 0;
}

 

and Player.png attachment from CME tutorial

I think my code does the same, but inside method, but results aren't the same :(

[attachment deleted by admin]
« Last Edit: March 17, 2013, 07:13:11 am by Nezaja »

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #5 on: March 17, 2013, 08:47:49 am »
In C++ arguments are passed by copy.
Use a reference or a pointer or make it a member of player.

Nezaja

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #6 on: March 17, 2013, 09:47:03 am »
Player.cpp

void Player::movement(Player* p, float* frameCounter, float switchFrame, float frameSpeed, sf::Clock* clock)

//...


                *frameCounter += frameSpeed * clock->restart().asSeconds();
                std::cout << "FRAME " << *frameCounter << std::endl;
                if(*frameCounter >= switchFrame)
                {
                        std::cout << "FRAME COUNTER INSIDE IF" << *frameCounter << std::endl;
                        *frameCounter = 0;
                        std::cout << "FRAME COUNTER INSIDE IF AFTER 0" << *frameCounter << std::endl;
                        source.x++;
                        if(source.x * 32 >= p->ptexture.getSize().x)
                                source.x = 0;
                       
                }
 

main.cpp


//...

player1->movement(player1, &frameCounter, switchFrame, frameSpeed, &clock);
                        std::cout << "FRAME COUNTER OUTSIDE " << frameCounter << std::endl;

//...

 

Now the problem is that animation is lightning fast :)

this is the problem :d

http://www.youtube.com/watch?v=Mv5ER2gnv-Y&feature=youtu.be

Edit:

Ok problem solved i had to put vector2i outside the method :) and send it by reference :)
« Last Edit: March 17, 2013, 11:16:36 am by Nezaja »

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #7 on: March 17, 2013, 10:19:37 pm »
Ok cool, but you should seriously learn C++ if you want to make games in C++. :p Your code is terribad.

Nezaja

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #8 on: March 18, 2013, 06:58:31 am »
Explain, "terribad" is not constructive.

The purpose of this game is to learn programming, making console programms is boring. Well i will make You happy, with future problems i won't make "stupid" topics, i'll just try to solve my problems for my own :), so i will not trash this forum :)

I agree, maybe for You this topic was stupid, cuz it was related to the core C++ knowledge, not SFML, but thanks to that i made one step further, so for me it was important and constructive, everything depends on the point of view. Maybe You, as experienced programmer and dev, see that kinds of topic as stupid, i understand that, we can always say "Firstly learn, then ask", but for ppl like me it's important if some more experienced ppl share their knoweldge. I can say i'm good at 3D modeling and texturing, and if someone ask me with even basic question i try to explain the best i can, because i was a beginner too and i know how much work it takes to achieve some lvl. Maybe it's stupid, cuz i make someones live easier, because some ppl think all folks have to study on their own, but i am who i am, if i can share my knowledge i do this.

As i said in the first post, i'm not experienced C++ user, i'm learning, but everyday i know more and thanks to ppl like You my learning process is faster and nicer. I hope i will not make such stupid mistakes from now, also i will try to make my code not to be "terribad".

Thanks for help G. ;)
« Last Edit: March 18, 2013, 07:12:05 am by Nezaja »

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #9 on: March 18, 2013, 08:44:45 am »
Well i will make You happy, with future problems i won't make "stupid" topics, i'll just try to solve my problems for my own :), so i will not trash this forum :)
I didn't even say you or your topic were stupid. ??? You can keep on posting your questions on this forum, this time I'll just let other people answer them so I won't make you pout. ;)

Nezaja

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Sprite animation problem (SFML 2.0)
« Reply #10 on: March 18, 2013, 09:47:23 am »
I'm not pouting ;)