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

Author Topic: Spritesheet movement update  (Read 4154 times)

0 Members and 1 Guest are viewing this topic.

mos

  • Newbie
  • *
  • Posts: 19
    • View Profile
Spritesheet movement update
« on: September 03, 2016, 12:21:03 am »
Hello, I just started learning SFML and need help with sprite movement. I am able to get a specific frame in the sheet and face it the correct direction depending on the key pressed (left, down, up, right). However, sometimes the sprite faces in another direction when I move my mouse even though I have no mouse events. Another problem I have is that it is not that responsive. If I spam left and right arrow keys, there is sometimes a delay before it faces it another direction (same with any two key combination spams).

Spritesheet: http://i.imgur.com/mvqg4CI.png

Here is my code:

Player.h
#pragma once
#include <iostream>
#include <string>
#include <SFML/Graphics.hpp>

class Player
{
        private:
                sf::Texture texture;
                sf::Sprite sprite;
                sf::Vector2i source;
                sf::Vector2f position;

                unsigned int rows, columns;
                unsigned int spriteWidth, spriteHeight;
                unsigned int sheetWidth, sheetHeight;

                // Corresponds to the row
                enum Direction { Up, Left, Down, Right };

        public:
                Player(std::string filename, int rows, int columns, sf::Vector2f position);

                void update(sf::Event event);
                void draw(sf::RenderWindow &window);
};
 

Player.cpp
#include "Player.h"

Player::Player(std::string filename, int rows, int columns, sf::Vector2f position)
{
        // Load the texture
        if (!texture.loadFromFile(filename))
                std::cout << "Could not load " << filename << std::endl;

        // Sheet dimensions
        sheetWidth = texture.getSize().x;
        sheetHeight = texture.getSize().y;

        // Attach to player sprite
        sprite.setTexture(texture);

        // Set the position
        this->position.x = position.x;
        this->position.y = position.y;
        sprite.setPosition(this->position);

        // Get the sprite with and height
        spriteWidth = sheetWidth / columns;
        spriteHeight = sheetHeight / rows;

        // Set the source frame
        source.x = 0;
        source.y = Right;
}


void Player::update(sf::Event event)
{
        if (sf::Event::KeyPressed)
        {
                switch (event.key.code)
                {
                        case sf::Keyboard::Up:
                                source.y = Up;
                                break;

                        case sf::Keyboard::Down:
                                source.y = Down;
                                break;

                        case sf::Keyboard::Left:
                                source.y = Left;
                                break;

                        case sf::Keyboard::Right:
                                source.y = Right;
                                break;
                }
        }
}

void Player::draw(sf::RenderWindow &window)
{
        // Create rectangle in sheet around a sprite
        sprite.setTextureRect(sf::IntRect(source.x * spriteWidth, source.y * spriteHeight, spriteWidth, spriteHeight));

        // Draw the sprite
        window.draw(sprite);
}
 

Game.cpp
#include "Player.h"

int main()
{
        sf::RenderWindow window;

        // Initialize
        unsigned int width = 900;
        unsigned int height = 500;

        window.create(sf::VideoMode(width, height), "FPS");
        window.setFramerateLimit(60);
        window.setVerticalSyncEnabled(false);

        // Sprite stuff
        Player player("Sprites/Skeleton.png", 4, 9, sf::Vector2f(100, 100));

        // Game loop
        while (window.isOpen())
        {
                sf::Event event;

                while (window.pollEvent(event))
                {
                        switch (event.type)
                        {
                                case sf::Event::Closed:
                                        window.close();
                                        break;
                        }

                        player.update(event);
                }

                window.clear();
                player.draw(window);
                window.display();
        }
}

I am fairly new to C++, so sorry if there are any mistakes. I come from a Java background. Any help would be appreciated, thank you!
« Last Edit: September 03, 2016, 01:36:52 am by mos »

DarkRoku12

  • Full Member
  • ***
  • Posts: 203
  • Lua coder.
    • View Profile
    • Email
Re: Spritesheet movement update
« Reply #1 on: September 03, 2016, 01:25:55 am »
Can you provide the Sprite file.

Also for get smooth movement you should use ::isPressed/isKeyPressed() functions.

Quoted from SFML 2.4 tutorial:

Quote
Sometimes, people try to react to KeyPressed events directly to implement smooth movement. Doing so will not produce the expected effect, because when you hold a key you only get a few events (remember, the repeat delay). To achieve smooth movement with events, you must use a boolean that you set on KeyPressed and clear on KeyReleased; you can then move (independently of events) as long as the boolean is set.
The other (easier) solution to produce smooth movement is to use real-time keyboard input with sf::Keyboard (see the dedicated tutorial).
I would like a spanish/latin community...
Problems building for Android? Look here

mos

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Spritesheet movement update
« Reply #2 on: September 03, 2016, 01:46:10 am »
Here's the spritesheet: http://i.imgur.com/mvqg4CI.png

Using isKeyPressed() helped tremendously. Moving the mouse doesn't seem to change the direction anymore and it appears to be responsive.

Can you still look with the spritesheet and offer any further advice/suggestions? It would be greatly appreciated! Thank you.

Here is what I changed:

void Player::update()
{
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                source.y = Up;

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
                source.y = Down;

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                source.y = Left;

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                source.y = Right;
}

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Spritesheet movement update
« Reply #3 on: September 03, 2016, 09:15:08 pm »
This:
if (sf::Event::KeyPressed)
should most likely be:
if (event.type == sf::Event::KeyPressed)
(in your event code)

However, I agree that using real-time "isKeyPressed" states can be more useful for constant, regular movement.
You might want to conside using "else if" for all subsequent "isKeyPressed" after the first one as you've already decided which one to use and it can't take into account more than one direction (in this code).

Also, since the position member and the position parameter are both sf::Vector2fs, instead of this:
    this->position.x = position.x;
    this->position.y = position.y;
you can do this:
    this->position = position;
« Last Edit: September 03, 2016, 09:22:26 pm by Hapax »
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

mos

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Spritesheet movement update
« Reply #4 on: September 05, 2016, 03:37:17 am »
Thank you very much! I was able to make it walk smoothly.