SFML community forums

Help => Graphics => Topic started by: Engineer on August 14, 2013, 02:19:52 pm

Title: moving a character through a class and a spritesheet class
Post by: Engineer on August 14, 2013, 02:19:52 pm
Hello
I just started SFML and wanted to write a program that moves a ball.

here is the code:
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

sf::Event event;

class Ball
{
    int CircleR, Redd, Greenn, Bluee;
    sf::CircleShape shape;

    public:

    Ball(int CircleR,int Redd,int Greenn,int Bluee);
    Ball();
    sf::CircleShape getCircle();
    void moveCircle(int x, int y);

};

int main()
{
    Ball ball(100.f, 250, 0, 0);

    sf::RenderWindow window(sf::VideoMode(800,600), "SFML Test");
    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;

                default:
                break;
            }

        }

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            ball.moveCircle(-50,0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            ball.moveCircle(50,0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            ball.moveCircle(0,50);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            ball.moveCircle(0,-50);
        }
        window.clear(sf::Color::Black);

        window.draw(ball.getCircle());

        window.display();
    }
    return 0;

}


Ball::Ball(int CircleR, int Redd, int Greenn, int Bluee)
{
    CircleR = CircleR;
    Redd = Redd;
    Greenn = Greenn;
    Bluee = Bluee;

    shape.setRadius(CircleR);
    shape.setFillColor(sf::Color(Redd,Greenn,Bluee));
    shape.setPosition(100,100);
}

Ball::Ball()
{
    shape.setRadius(50);
    shape.setFillColor(sf::Color(100,100,100));
    shape.setPosition(100,100);
}

sf::CircleShape Ball::getCircle()
{
    return shape;
}

void Ball::moveCircle(int x, int y)
{
    getCircle().move(x, y);
}
 

When I press left/up/down/right nothing happens. Some insight? Thanks
Title: Re: moving a circle through a class
Post by: G. on August 14, 2013, 02:39:29 pm
Quote
sf::CircleShape Ball::getCircle()
{
    return shape;
}

void Ball::moveCircle(int x, int y)
{
    getCircle().move(x, y);
}
It's not SFML related but C++ related.
getCircle() returns a copy of shape, and moveCircle calls move() on the copy. It essentially does nothing.
Either directly use shape in your moveCircle method, or make getCircle return a reference.
Title: Re: moving a circle through a class
Post by: Engineer on August 14, 2013, 02:52:36 pm
Thanks. But even if I use shape, it will disappear. And I tried to lower down the move(50,0) to move(10,0).
Since I really need to make the getcircle function to work (otherwise it will draw a copy of ball), can you tell me how I can return an address? I thought I would have needed to use pointers but I really don't know how I could do that. I want to do it with pointers that are more familiar with me. I recognize its my first time trying to use libraries and classes altogether, I already did functions that worked on pointers but never functions that returns pointers. For example how can I call the draw function with the pointer ?

Here is my new code:
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

sf::Event event;

class Ball
{
    int CircleR, Redd, Greenn, Bluee;
    sf::CircleShape * shape;

    public:

    Ball(int CircleR,int Redd,int Greenn,int Bluee);
    Ball();
    sf::CircleShape * getCircle();
    void moveCircle(int x, int y);

};

int main()
{
    Ball ball(100.f, 250, 0, 0);

    sf::RenderWindow window(sf::VideoMode(800,600), "SFML Test");
    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;

                default:
                break;
            }

        }

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            ball.moveCircle(-10,0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            ball.moveCircle(10,0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            ball.moveCircle(0,10);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            ball.moveCircle(0,-10);
        }
        window.clear(sf::Color::Black);

        window.draw(&(ball.getCircle()));

        window.display();
    }
    return 0;

}


Ball::Ball(int CircleR, int Redd, int Greenn, int Bluee)
{
    CircleR = CircleR;
    Redd = Redd;
    Greenn = Greenn;
    Bluee = Bluee;

    shape->setRadius(CircleR);
    shape->setFillColor(sf::Color(Redd,Greenn,Bluee));
    shape->setPosition(100,100);
}

Ball::Ball()
{
    shape->setRadius(50);
    shape->setFillColor(sf::Color(100,100,100));
    shape->setPosition(100,100);
}

sf::CircleShape * Ball::getCircle()
{
    return shape;
}

void Ball::moveCircle(int x, int y)
{
    getCircle()->move(x, y);
}
 

Also forget my last code for the key events, I just wanted to replace the if with a switch statement but it doesn't look like you can replace it with a switch. Thanks for your help.
Title: Re: moving a circle through a class
Post by: G. on August 14, 2013, 03:00:13 pm
Try to avoid pointers as long as they aren't needed.
You should really learn how to use references, pointers or copies before toying with SFML, it's mandatory basic C++ knowledge.

To return a reference in your former code (not in your new one with pointers) you only have to change one thing:
sf::CircleShape& Ball::getCircle()
{
    return shape;
}

Oh and the shape disappears yeah, you're moving it by 50 pixels (now 10) per frame, it's a lot! There is a good chance that if you press a key for a little time the shape will move out of the screen so fast that you won't even see it.
Title: Re: moving a circle through a class
Post by: Engineer on August 14, 2013, 03:09:35 pm
Thanks a lot. I'll try to practice a few times more with references and pointers.
But just to know, for the pointer version, I would need to put CircleShape * shape, name the function getcircle to * getcircle and give &(ball.getCircle()) to .draw() and put getCircle()-> move(x,y) in the last function of my code (Ball::moveCircle) ? Or I miss something?

EDIT: and use "->" in the constructors of Ball. Only thing I do not understand is how to give the shape to draw. :/
Thanks a lot again.
Title: Re: moving a circle through a class
Post by: G. on August 14, 2013, 03:17:19 pm
If I understood correctly, no.
In your code with the pointer, getCircle() return a pointer to an sf::CircleShape. You need to give the CircleShape pointed by your pointer to window.draw().
You need to dereference your pointer and the syntax would be:
window.draw(*(ball.getCircle()));

You also never dynamically allocate memory to your sf::CircleShape pointer. (use new)
Title: Re: moving a circle through a class
Post by: Engineer on August 14, 2013, 03:24:04 pm
Yeah exactly what I needed thanks. I admit references look to be simpler to use but from what I understood you can't change references, reference to NULL and must initialize references when you create them, thats why I wanted to use pointers that are more flexible.
The draw function is good but I don't know in the getCircle if I return *shape or shape;
actual code:
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

sf::Event event;

class Ball
{
    int CircleR, Redd, Greenn, Bluee;
    sf::CircleShape * shape;

    public:

    Ball(int CircleR,int Redd,int Greenn,int Bluee);
    Ball();
    sf::CircleShape * getCircle();
    void moveCircle(int x, int y);

};

int main()
{
    Ball ball(30, 250, 0, 0);

    sf::RenderWindow window(sf::VideoMode(800,600), "SFML Test");
    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;

                default:
                break;
            }

        }

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            ball.moveCircle(-1,0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            ball.moveCircle(1,0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            ball.moveCircle(0,1);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            ball.moveCircle(0,-1);
        }
        window.clear(sf::Color::Black);

        window.draw(*(ball.getCircle()));

        window.display();
    }
    return 0;

}


Ball::Ball(int CircleR, int Redd, int Greenn, int Bluee)
{
    CircleR = CircleR;
    Redd = Redd;
    Greenn = Greenn;
    Bluee = Bluee;

    shape->setRadius(CircleR);
    shape->setFillColor(sf::Color(Redd,Greenn,Bluee));
    shape->setPosition(100,100);
}

Ball::Ball()
{
    shape->setRadius(50);
    shape->setFillColor(sf::Color(100,100,100));
    shape->setPosition(100,100);
}

sf::CircleShape * Ball::getCircle()
{
    return shape;
}

void Ball::moveCircle(int x, int y)
{
    getCircle()->move(x, y);
}
 

Thanks you a billion times and sorry for abusing of your kindness :p
EDIT: it compiles but crashes.
Title: Re: moving a circle through a class
Post by: G. on August 14, 2013, 03:41:47 pm
Your pointer is uninitialized, it points to an unknown location (could be anywhere) and you're using it nevertheless.
You need to initialize it, with new.
shape = new sf::CircleShape;

If shape is an sf::CircleShape* and you want getCircle() to return an sf::CircleShape*, then you just have to
return shape;

Everything will be clearer when you learn/understand it. :p
Title: Re: moving a circle through a class
Post by: Engineer on August 14, 2013, 03:53:52 pm
Yeah true I always forget about initializing pointers. F***. Thanks a lot. :)
I come from C where I was using malloc() and free(), I suppose that in C++ the object is deleted in the end of the scope of the file.
Thanks a lot again. :)
Title: Re: moving a circle through a class
Post by: Nexus on August 14, 2013, 04:18:10 pm
I suppose that in C++ the object is deleted in the end of the scope of the file.
No, it's not. If you use new, you have to clean up with delete. Same for new[] and delete[].

But in C++ you usually don't do that, memory is managed automatically by means of the RAII idiom. Instead of sf::CircleShape*, you simply use sf::CircleShape. If you ever need pointers (e.g. for polymorphism), you replace sf::Shape* with std::unique_ptr<sf::Shape> which automatically invokes delete for you.
Title: Re: moving a circle through a class
Post by: Engineer on August 14, 2013, 04:45:53 pm
Okay thanks a lot. By the way is it normal that when I press left/right/down/up the circle move more than one pixel (I put 1 in each move) ? It moves way too fast :/
Title: Re: moving a circle through a class
Post by: Nexus on August 14, 2013, 05:31:27 pm
Yes, since you have a loop that is continuously iterated. For the beginning, you can set a frame rate limit (sf::RenderWindow::setFramerateLimit()), later you can use a more elaborated technique for frame-independent movement.
Title: Re: moving a circle through a class
Post by: Engineer on August 14, 2013, 06:27:47 pm
Thanks a lot. By the way I made a new program that got no error and crash :
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <string>
#include <vector>

#define SIZE 3

sf::Event event;
bool failtoOpenFile = false;

class Spritesheet
{
    public:
    sf::Sprite mainSprite;
    sf::Texture textureHero[SIZE];
    int vectorPX[SIZE], vectorPY[SIZE];
    void setVectorSprite(int vectorX[SIZE], int vectorY[SIZE]);
    void setFileName(std::string filename);
    std::vector<sf::Sprite> & getVectorSprite();

    private:
    std::string filenameS;
    std::vector<sf::Sprite> vectorSprite;


};




class Hero
{
public:
    Spritesheet spriteSheetHero;
    void setHealth(int health);
    int lastposX, lastposY;
private:
    int health;
    int curX, curY;


};



int main()
{


    sf::RenderWindow window(sf::VideoMode(800,600), "SFML Char test");
    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;

                default:
                break;
            }

        }
        // setting the hero
        Hero hero;
        hero.setHealth(100);
        hero.spriteSheetHero.setFileName("spritesheet.png");
        int testX[3], testY[3];
        testX[0] = 14;
        testX[1] = 49;
        testX[2] = 78;
        testY[0] = 9;
        testY[1] = 9;
        testY[2] = 9;
        hero.spriteSheetHero.setVectorSprite(testX, testY );
        hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSprite()[2];

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSprite()[1];
            hero.spriteSheetHero.mainSprite.move(-1, 0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSprite()[1];
            hero.spriteSheetHero.mainSprite.rotate(180);
            hero.spriteSheetHero.mainSprite.move(1, 0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSprite()[0];
            hero.spriteSheetHero.mainSprite.move(0, -1);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSprite()[2];
            hero.spriteSheetHero.mainSprite.move(0, 1);
        }
        window.clear(sf::Color::Blue);

        window.draw(hero.spriteSheetHero.mainSprite);

        window.display();
    }
    return 0;

}

void Hero::setHealth(int health)
{
    health = health;
}

void Spritesheet::setVectorSprite(int vectorX[3], int vectorY[3])
{
    for(int i = 0; i < SIZE; i++)
    {
        vectorPX[i] = vectorX[i];
        vectorPY[i] = vectorY[i];
        if(!(textureHero[i].loadFromFile("spritesheet.png", sf::IntRect(vectorPX[i], vectorPY[i], 18, 26))))
        {
            failtoOpenFile = true;
        }
        else
        {
            textureHero[i].loadFromFile("spritesheet.png", sf::IntRect( vectorPX[i],vectorPY[i] , 18,26 ));
            getVectorSprite()[i].setTexture(textureHero[i]);
        }
    }


}
void Spritesheet::setFileName(std::string filename)
{
    filenameS = filename;
}

std::vector<sf::Sprite> & Spritesheet::getVectorSprite()
{
    return vectorSprite;
}
 

Maybe it comes from the fact that I use arrays to initialize the sprite, but can somebody confirm me this?
Thanks a lot. :)

BTW, the file and all the .dll are next to the .exe in the same directory and I'm TOTALLY SURE it's the working directory (did programs to see where files goes when I create them using filestreams before). :)
Title: Re: moving a hero through a class and a spritesheet class
Post by: Engineer on August 14, 2013, 07:56:19 pm
Now I updated my code with better functions on things that could have possibly gone wrong (aka, get a vector<sf::Sprite> from a class, now I return the <sf::Sprite> I need from the vector).
EDIT: It indeeds come from there, because if I remove my functions and load the sprite with mainsprite it works and render correctly my sprite so it must come from the arrays.
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <string>
#include <vector>

#define SIZE 3

sf::Event event;

class Spritesheet
{
    public:
    sf::Sprite mainSprite;
    sf::Texture textureHero[SIZE];
    int vectorPX[SIZE], vectorPY[SIZE];
    void setVectorSprite(int vectorX[SIZE], int vectorY[SIZE]);
    void setFileName(std::string filename);
    std::vector<sf::Sprite> & getVectorSprite();
    sf::Sprite & getVectorSpriteJ(int j);

    private:
    std::string filenameS;
    std::vector<sf::Sprite> vectorSprite;


};




class Hero
{
public:
    Spritesheet spriteSheetHero;
    void setHealth(int health);
    int getlastX();
    int getlastY();
    void setPos(int posX, int posY);

private:
    int health;
    int lastposX, lastposY;
    int curX, curY;


};



int main()
{


    sf::RenderWindow window(sf::VideoMode(800,600), "SFML Char test");
    // window.setFramerateLimit(10);
    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;

                default:
                break;
            }

        }
        // setting the hero
        Hero hero;
        hero.setHealth(100);
        hero.spriteSheetHero.setFileName("spritesheet.png");
        int testX[3], testY[3];
        testX[0] = 14;
        testX[1] = 49;
        testX[2] = 78;
        testY[0] = 9;
        testY[1] = 9;
        testY[2] = 9;
        hero.spriteSheetHero.setVectorSprite(testX, testY );
        hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSpriteJ(2);

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSpriteJ(1);
            hero.spriteSheetHero.mainSprite.move(-1, 0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSpriteJ(1);
            hero.spriteSheetHero.mainSprite.rotate(180);
            hero.spriteSheetHero.mainSprite.move(1, 0);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSpriteJ(0);
            hero.spriteSheetHero.mainSprite.move(0, -1);
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            hero.spriteSheetHero.mainSprite = hero.spriteSheetHero.getVectorSpriteJ(2);
            hero.spriteSheetHero.mainSprite.move(0, 1);
        }
        window.clear(sf::Color::Blue);

        window.draw(hero.spriteSheetHero.mainSprite);

        window.display();
    }
    return 0;

}

void Hero::setHealth(int health)
{
    health = health;
}

void Spritesheet::setVectorSprite(int vectorX[3], int vectorY[3])
{
    for(int i = 0; i < SIZE; i++)
    {
        vectorPX[i] = vectorX[i];
        vectorPY[i] = vectorY[i];
        textureHero[i].loadFromFile("spritesheet.png", sf::IntRect( vectorPX[i],vectorPY[i] , 18,26 ));
        getVectorSpriteJ(i).setTexture(textureHero[i]);
    }
}

void Spritesheet::setFileName(std::string filename)
{
    filenameS = filename;
}

std::vector<sf::Sprite> & Spritesheet::getVectorSprite()
{
    return vectorSprite;
}

int Hero::getlastX()
{
    return lastposX;
}

int Hero::getlastY()
{
    return lastposY;
}

void Hero::setPos(int posX, int posY)
{
    curX = posX;
    curY = posY;
    spriteSheetHero.mainSprite.setPosition(curX, curY);
}

sf::Sprite & Spritesheet::getVectorSpriteJ(int j)
{
    return vectorSprite[j];
}
 
Title: Re: moving a hero through a class and a spritesheet class
Post by: Engineer on August 14, 2013, 11:29:20 pm
Just discovered I was dumb and couldn't simply do sf::that sprite = sf::thatothersprite...
Here is another code that takes care of that (don't mind the comments its for one animation system) :
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <string>
#include <vector>

#define SIZE 3

sf::Event event;

class Spritesheet
{
    public:
    sf::Sprite mainSprite;
    sf::Texture textureHero[SIZE];
    int vectorPX[SIZE], vectorPY[SIZE];
    void setVectorSprite(int vectorX[SIZE], int vectorY[SIZE]);
    void setFileName(std::string filename);
    std::string & getFileName();
    std::vector<sf::Sprite> & getVectorSprite();
    sf::Sprite & getVectorSpriteJ(int j);

    private:
    std::string filenameS;
    std::vector<sf::Sprite> vectorSprite;


};




class Hero
{
public:
    Spritesheet spriteSheetHero;
    void setHealth(int health);
    int & getlastX();
    int & getlastY();
    void setPos(int posX, int posY);

private:
    int healthH;
    int lastposX, lastposY;
    int curX, curY;


};



int main()
{

    sf::RenderWindow window(sf::VideoMode(800,600), "SFML Char test");
    // window.setFramerateLimit(10);
    while(window.isOpen())
    {
        sf::Clock clock;
        sf::Time elapse = clock.getElapsedTime();
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;

                default:
                break;
            }

        }
        window.clear(sf::Color::Blue);
        // setting the hero
        Hero hero;
        hero.setHealth(100);
        hero.spriteSheetHero.setFileName("spritesheet.png");
        int testX[3] = { 14, 49, 78 };
        int testY[3] = { 9, 9, 9 };
        hero.spriteSheetHero.setVectorSprite(testX, testY );
        hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(2)).getTexture()));

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            clock.restart();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(1)).getTexture()));
            hero.spriteSheetHero.mainSprite.move(-1, 0);
            /*if(elapse == 300)
            {
                hero.spriteSheetHero.mainSprite.setTexture((hero.spriteSheetHero.getVectorSpriteJ()).getTexture());
            }
            if(elapse == 600)
            {
                hero.spriteSheetHero.mainSprite.setTexture((hero.spriteSheetHero.getVectorSpriteJ()).getTexture());
            }
            clock.restart();*/

        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            clock.restart();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(1)).getTexture()));
            hero.spriteSheetHero.mainSprite.rotate(180);
            hero.spriteSheetHero.mainSprite.move(1, 0);
            /*if(elapse == 300)
            {
                hero.spriteSheetHero.mainSprite.setTexture((hero.spriteSheetHero.getVectorSpriteJ()).getTexture());
            }
            if(elapse == 600)
            {
                hero.spriteSheetHero.mainSprite.setTexture((hero.spriteSheetHero.getVectorSpriteJ()).getTexture());
            }
            clock.restart();*/

        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            clock.restart();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(0)).getTexture()));
            hero.spriteSheetHero.mainSprite.move(0, -1);
            /*if(elapse == 300)
            {
                hero.spriteSheetHero.mainSprite.setTexture((hero.spriteSheetHero.getVectorSpriteJ()).getTexture());
            }
            if(elapse == 600)
            {
                hero.spriteSheetHero.mainSprite.setTexture((hero.spriteSheetHero.getVectorSpriteJ()).getTexture());
            }
            clock.restart();*/

        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            clock.restart();
            hero.spriteSheetHero.mainSprite.setTexture(*(((hero.spriteSheetHero.getVectorSpriteJ(2)).getTexture())));
            hero.spriteSheetHero.mainSprite.move(0, 1);
            /*if(elapse == 300)
            {
                hero.spriteSheetHero.mainSprite.setTexture((hero.spriteSheetHero.getVectorSpriteJ()).getTexture());
            }
            if(elapse == 600)
            {
                hero.spriteSheetHero.mainSprite.setTexture((hero.spriteSheetHero.getVectorSpriteJ()).getTexture());
            }
            clock.restart();*/

        }
        hero.setPos(100,100);
        window.draw(hero.spriteSheetHero.mainSprite);

        window.display();
    }
    return 0;

}

void Hero::setHealth(int health)
{
    healthH = health;
}

void Spritesheet::setVectorSprite(int vectorX[3], int vectorY[3])
{
    for(int i = 0; i < SIZE; i++)
    {
        vectorPX[i] = vectorX[i];
        vectorPY[i] = vectorY[i];
        textureHero[i].loadFromFile(getFileName(), sf::IntRect(vectorPX[i] ,vectorPY[i] ,18 ,26 ));
        getVectorSpriteJ(i).setTexture(textureHero[i]);
    }
}

void Spritesheet::setFileName(std::string filename)
{
    filenameS = filename;
}

std::vector<sf::Sprite> & Spritesheet::getVectorSprite()
{
    return vectorSprite;
}

int & Hero::getlastX()
{
    return lastposX;
}

int & Hero::getlastY()
{
    return lastposY;
}

void Hero::setPos(int posX, int posY)
{
    curX = posX;
    curY = posY;
    spriteSheetHero.mainSprite.setPosition(curX, curY);
}

sf::Sprite & Spritesheet::getVectorSpriteJ(int j)
{
    return vectorSprite[j];
}
std::string & Spritesheet::getFileName()
{
    return filenameS;
}
 
Title: Re: moving a character through a class and a spritesheet class
Post by: Engineer on August 15, 2013, 02:03:12 am
I'm so dumb I had to forget that I needed to push_back the sprite. Forgive me.
Problem now is that my sprites got a white background (even if those are transparent background!) and they don't move when I press the keys up/down/right/left :(
working code:
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <string>
#include <vector>

#define SIZE 12

sf::Event event;

class Spritesheet
{
    public:
    sf::Sprite mainSprite;
    sf::Texture textureHero[SIZE];
    int vectorPX[SIZE];
    int vectorPY[SIZE];
    void setVectorSprite(int vectorX[SIZE], int vectorY[SIZE]);
    std::vector<sf::Sprite> & getVectorSprite();
    sf::Sprite & getVectorSpriteJ(int j);
    std::string filenameS;
    std::vector<sf::Sprite> vectorSprite;

    private:
    //std::vector<sf::Sprite> vectorSprite;


};




class Hero
{
public:
    Spritesheet spriteSheetHero;
    void setHealth(int health);
    int & getlastX();
    int & getlastY();
    void setPos(int posX, int posY);

private:
    int healthH;
    int lastposX, lastposY;
    int curX, curY;


};



int main()
{
    sf::Clock clock;
    sf::Time elapse;
    // sf::Time elapse;
    // elapse = clock.getTimeElapsed();
    sf::RenderWindow window(sf::VideoMode(800,600), "SFML Hero");
    // window.setFramerateLimit(10);
    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;

                default:
                break;
            }

        }
        window.clear(sf::Color::White); // orange = sf::Color(250,127,0)
        // setting the hero
        Hero hero;
        hero.setHealth(100);
        int testX[SIZE] = { 14, 49, 78, 109, 170, 360, 536, 695, 861, 1020, 1145, 1180 };
        int testY[SIZE] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
        hero.spriteSheetHero.setVectorSprite(testX, testY );
        hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(2)).getTexture()));

        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            elapse = clock.getElapsedTime();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(1)).getTexture()));
            hero.spriteSheetHero.mainSprite.move(-10, 0);
            if(elapse.asMilliseconds() == 300)
            {
                hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(4)).getTexture());
            }
            if(elapse.asMilliseconds() == 600)
            {
                hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(5)).getTexture());
                clock.restart();
            }
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            elapse = clock.getElapsedTime();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(3)).getTexture()));
            hero.spriteSheetHero.mainSprite.move(10, 0);
            if(elapse.asMilliseconds() == 300)
            {
                hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(10)).getTexture());
            }
            if(elapse.asMilliseconds() == 600)
            {
                hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(11)).getTexture());
            }
            clock.restart();
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            elapse = clock.getElapsedTime();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(0)).getTexture()));
            hero.spriteSheetHero.mainSprite.move(0, 10);
            if(elapse.asMilliseconds() == 300)
            {
                hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(8)).getTexture());
            }
            if(elapse.asMilliseconds() == 600)
            {
                hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(9)).getTexture());
            }
            clock.restart();
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            elapse = clock.getElapsedTime();
            hero.spriteSheetHero.mainSprite.setTexture(*(((hero.spriteSheetHero.getVectorSpriteJ(2)).getTexture())));
            hero.spriteSheetHero.mainSprite.move(0, -10);
            if(elapse.asMilliseconds() == 300)
            {
                hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(6)).getTexture());
            }
            if(elapse.asMilliseconds() == 600)
            {
                hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(7)).getTexture());
            }
            clock.restart();
        }
        hero.setPos(100,100);
        window.draw(hero.spriteSheetHero.mainSprite);

        window.display();
    }
    return 0;

}

void Hero::setHealth(int health)
{
    healthH = health;
}

void Spritesheet::setVectorSprite(int vectorX[3], int vectorY[3])
{
    sf::Sprite spritetest;
    for(int i = 0; i < SIZE; i++)
    {
        vectorPX[i] = vectorX[i];
        vectorPY[i] = vectorY[i];
        textureHero[i].loadFromFile("spritesheet.png", sf::IntRect(vectorX[i] ,vectorY[i] ,18 , 26 ));
        //getVectorSpriteJ(i).setTexture(textureHero[i]);
        spritetest.setTexture(textureHero[i]);
        getVectorSprite().push_back(spritetest);
    }
}


std::vector<sf::Sprite> & Spritesheet::getVectorSprite()
{
    return vectorSprite;
}

int & Hero::getlastX()
{
    return lastposX;
}

int & Hero::getlastY()
{
    return lastposY;
}

void Hero::setPos(int posX, int posY)
{
    curX = posX;
    curY = posY;
    spriteSheetHero.mainSprite.setPosition(curX, curY);
}

sf::Sprite & Spritesheet::getVectorSpriteJ(int j)
{
    return vectorSprite[j];
}

 

But the sprites can't move :/
Title: Re: moving a character through a class and a spritesheet class
Post by: Ixrec on August 15, 2013, 02:37:48 am
That might be because of the hero.setPos(100,100); line just after you finish processing all the keyboard input.

Incidentally, you should learn to use a debugger. If you stepped through your code after it detected a key press you'd have very quickly noticed the erroneous setPos line.
Title: Re: moving a character through a class and a spritesheet class
Post by: Engineer on August 15, 2013, 02:42:59 am
had seen that long ago before your post and removed and still doesn't work... :(
also, I'm using this spritesheet http://www.spriters-resource.com/gameboy_advance/lozminish/sheet/6369/ and its transparent but when displaying sprite, background is white. If somebody can tell me if the spritesheet is really transparent or not, I will need to do a sf::Image for each sprite and remove mask, that would be boring :(
Title: Re: moving a character through a class and a spritesheet class
Post by: Ixrec on August 15, 2013, 03:05:41 am
Or you could get a decent image editor like Paint.net and make those sections transparent yourself.  Just click the white parts with the magic wand tool and use ctrl+x to delete those pixels (which in Paint.net makes them transparent).

Also, could you upload your spritesheet so I can test your code myself?
Title: Re: moving a character through a class and a spritesheet class
Post by: Engineer on August 15, 2013, 12:21:09 pm
Here you go http://imgur.com/P9rhBlx (by the way its just a test for my sprite). And thanks for the tip for PAINT.NET, I didn't know that :)
Title: Re: moving a character through a class and a spritesheet class
Post by: Engineer on August 15, 2013, 12:32:35 pm
I figured that if I put the intializations of the hero outside of the window.isOpen loop, it would make the character move, but if I remove the "hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(2)).getTexture()));" it would make him disappear. Why is that?
Here is a code where you can move the character, also got one problem with my animation system :  it only display one frame of the two

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <string>
#include <vector>

#define SIZE 12

sf::Event event;

class Spritesheet
{
    public:
    sf::Sprite mainSprite;
    sf::Texture textureHero[SIZE];
    int vectorPX[SIZE];
    int vectorPY[SIZE];
    void setVectorSprite(int vectorX[SIZE], int vectorY[SIZE]);
    std::vector<sf::Sprite> & getVectorSprite();
    sf::Sprite & getVectorSpriteJ(int j);
    std::string filenameS;
    std::vector<sf::Sprite> vectorSprite;

    private:
    //std::vector<sf::Sprite> vectorSprite;


};




class Hero
{
public:
    Spritesheet spriteSheetHero;
    void setHealth(int health);
    int & getlastX();
    int & getlastY();
    void setPos(int posX, int posY);

private:
    int healthH;
    int lastposX, lastposY;
    int curX, curY;


};



int main()
{
    sf::Clock clock;
    sf::Time elapse;
    Hero hero;
    hero.setHealth(100);
    int testX[SIZE] = { 14, 49, 78, 109, 170, 360, 536, 695, 861, 1020, 1145, 1180 };
    int testY[SIZE] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
    hero.spriteSheetHero.setVectorSprite(testX, testY );
    sf::RenderWindow window(sf::VideoMode(800,600), "SFML Hero");
    window.setFramerateLimit(30);
    while(window.isOpen())
    {
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;

                default:
                break;
            }

        }
        window.clear(sf::Color(250,127,0)); // orange = sf::Color(250,127,0)
        hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(2)).getTexture()));
        // setting the herz
        clock.restart();
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            elapse = clock.getElapsedTime();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(1)).getTexture()));
            hero.spriteSheetHero.mainSprite.move(-5, 0);
                if(elapse.asMilliseconds() <= 300)
                {
                    hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(4)).getTexture());
                }
                if(elapse.asMilliseconds() >= 600)
                {
                    hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(5)).getTexture());
                    clock.restart();
                }
        }
        clock.restart();
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            elapse = clock.getElapsedTime();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(3)).getTexture()));
            hero.spriteSheetHero.mainSprite.move(5, 0);
                if(elapse.asMilliseconds() <= 300)
                {
                    hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(10)).getTexture());
                }
                if(elapse.asMilliseconds() >= 600)
                {
                    hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(11)).getTexture());
                    clock.restart();
                }
        }
        clock.restart();
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            elapse = clock.getElapsedTime();
            hero.spriteSheetHero.mainSprite.setTexture(*((hero.spriteSheetHero.getVectorSpriteJ(0)).getTexture()));
            hero.spriteSheetHero.mainSprite.move(0, 5);
                if(elapse.asMilliseconds() <= 300)
                {
                    hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(8)).getTexture());
                }
                if(elapse.asMilliseconds() >= 600)
                {
                    hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(9)).getTexture());
                    clock.restart();
                }
        }
        clock.restart();
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            elapse = clock.getElapsedTime();
            hero.spriteSheetHero.mainSprite.setTexture(*(((hero.spriteSheetHero.getVectorSpriteJ(2)).getTexture())));
            hero.spriteSheetHero.mainSprite.move(0, -5);

                if(elapse.asMilliseconds() <= 300)
                {
                    hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(6)).getTexture());
                }
                if(elapse.asMilliseconds() >= 600)
                {
                    hero.spriteSheetHero.mainSprite.setTexture(*(hero.spriteSheetHero.getVectorSpriteJ(7)).getTexture());
                    clock.restart();
                }
        }
        clock.restart();
        window.draw(hero.spriteSheetHero.mainSprite);

        window.display();
    }
    return 0;

}

void Hero::setHealth(int health)
{
    healthH = health;
}

void Spritesheet::setVectorSprite(int vectorX[3], int vectorY[3])
{
    sf::Sprite spritetest;
    for(int i = 0; i < SIZE; i++)
    {
        vectorPX[i] = vectorX[i];
        vectorPY[i] = vectorY[i];
        textureHero[i].loadFromFile("spritesheet.png", sf::IntRect(vectorX[i] ,vectorY[i] ,18 , 26 ));
        spritetest.setTexture(textureHero[i]);
        getVectorSprite().push_back(spritetest);
    }
}


std::vector<sf::Sprite> & Spritesheet::getVectorSprite()
{
    return vectorSprite;
}

int & Hero::getlastX()
{
    return lastposX;
}

int & Hero::getlastY()
{
    return lastposY;
}

void Hero::setPos(int posX, int posY)
{
    curX = posX;
    curY = posY;
    spriteSheetHero.mainSprite.setPosition(curX, curY);
}

sf::Sprite & Spritesheet::getVectorSpriteJ(int j)
{
    return vectorSprite[j];
}
 
Title: Re: moving a character through a class and a spritesheet class
Post by: Ixrec on August 15, 2013, 05:40:09 pm
That line should also be outside the isOpen loop in the initialization block, because it's giving the hero his initial sprite.  With it there, he always reverts to that same sprite when you stop holding a key.  If it's not there at all, then he has no initial sprite, which I assume is what you meant by "make him disappear," even though simply pressing an arrow key will give him a sprite.

The movement/animation stuff is a totally different set of issues.  Basically, your code is trying to assume that certain things always take the exact same amount of time, and that just isn't true.
1) You have if statements testing if *exactly* 30 or *exactly* 60 milliseconds have passed.  Nothing but dumb luck determines whether that happens or not.
2) Not only that, but your tests for whether to use the "running" sprites use only the elapsed time since the previous frame.  It doesn't make any sense to use that as a running test.  What you should be doing is keeping track of how long the key has been pressed (say, adding elapse to a variable like "up_held_for") and then use the other sprites based on that value (you might use a condition like up_held_for%1000 > 300)
3) Perhaps most important, you have your character move 10 pixels every frame.  Not only is that probably a lot faster than you want, but frames don't always take the same amount of time.  You need to multiply the speed by the elapsed time between frames so that you get the same movement speed regardless of framerate (that or you can try artificially limiting the framerate, but I don't really understand why people like to do that).
Title: Re: moving a character through a class and a spritesheet class
Post by: Engineer on August 15, 2013, 09:16:10 pm
Thanks, I removed the line,
maked one variable for each key pressed (a, b, c, d) for which I add the elapsed time as milliseconds,
changed the speed to 5 pixels, but animation still doesn't work :(
Here is the code:
Title: Re: moving a character through a class and a spritesheet class
Post by: hipsterdufus on August 16, 2013, 08:41:43 am
I would guess you're not seeing any animation because

<code>
        clock.restart();
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            elapse = clock.getElapsedTime();

</code>

since you reset your clock right before you set elapse the time passed is always going to be very small. Just a quick guess from glancing at your code.