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

Author Topic: Sprite movement/animation question.  (Read 1920 times)

0 Members and 1 Guest are viewing this topic.

GunnDawg

  • Newbie
  • *
  • Posts: 22
    • View Profile
    • Email
Sprite movement/animation question.
« on: December 30, 2014, 11:52:13 am »
Before I re-factored my code and created a player class, I had this working correctly. Now for whatever reason I cannot seem to get this working. You'll see in my Player.cpp file that based on players movement it will change the source.y to either Left, Right, Up, or Down which will/should call for the correct sprite in the sheet. Left would be left facing, Right would be right facing, etc, etc. I have not included the actual animation code yet, so that I am not worried about. Just curious as to why it's not properly changing and displaying the source.y. Player moves fine with the right mouse button but he stays facing right. Code is below. Thanks.

Player.cpp
#include "Player.h"

enum Direction { Up, Left, Down, Right };
float frameCounter = 0;
float switchFrame = 100;
float frameSpeed = 800;
sf::Vector2i source(0, Right);
sf::Vector2f totalMovement = sf::Vector2f();
sf::Vector2f mousePoint = sf::Vector2f();
sf::RenderWindow window;
bool totalMovementSet = false;

Player::Player()
{
        if (!playerTexture.loadFromFile("Sprites/player_sheet.png"))
        {
                std::cout << "Cannot find player Texture PNG file" << std::endl;
        }

        playerSprite.setTexture(playerTexture);
        playerSprite.setOrigin(sf::Vector2f(32, 64));
        playerSprite.setPosition(sf::Vector2f(400, 300));
        playerSprite.setTextureRect(sf::IntRect(source.x * 64, source.y * 64, 64, 64));
}

Player::~Player()
{

}

//Get class data.
void Player::update(float dt)
{

}

void Player::movement(sf::RenderWindow &window)
{
        if (sf::Mouse::isButtonPressed(sf::Mouse::Right))
        {
                totalMovementSet = true;
                totalMovement.x = sf::Mouse::getPosition(window).x - playerSprite.getPosition().x;
                totalMovement.y = sf::Mouse::getPosition(window).y - playerSprite.getPosition().y;

                mousePoint.x = sf::Mouse::getPosition(window).x;
                mousePoint.y = sf::Mouse::getPosition(window).y;
        }

        if (totalMovementSet == true)
        {
                float tanResult = atan2(totalMovement.y, totalMovement.x);
                double speed = 0.03;
                const double pi = 3.1415926535897;

                if ((tanResult > 3 * pi / 4 && tanResult < pi) || (tanResult < -3 * pi / 4 && tanResult > -pi))
                        source.y = Left;
                else if (tanResult > -pi / 4 && tanResult < pi / 4)
                {
                        source.y = Right;
                }
                else if (tanResult > -3 * pi / 4 && tanResult < -pi / 4)
                {
                        source.y = Up;
                }
                else if (tanResult > pi / 4 && tanResult < 3 * pi / 4)
                {
                        source.y = Down;
                }

                playerSprite.move(cos(tanResult)*speed, sin(tanResult)*speed);
        }

        if (playerSprite.getPosition().x > mousePoint.x - 10 && playerSprite.getPosition().x < mousePoint.x + 10 && playerSprite.getPosition().y > mousePoint.y - 10 &&
                playerSprite.getPosition().y < mousePoint.y + 10)
        {
                totalMovementSet = false;
        }
}

void Player::draw(sf::RenderWindow &window)
{
        window.draw(playerSprite);
}

std::string Player::getName()
{
        return Name;
}

int Player::getHealth()
{
        return newHealth;
}

int Player::getMana()
{
        return newMana;
}

//Set class data.
void Player::setName(std::string p_Name)
{
        Name = p_Name;
}

void Player::setHealth(int p_Health)
{
        newHealth = p_Health;
}

void Player::setMana(int p_Mana)
{
        newMana = p_Mana;
}

 

Player.h
#pragma once
#ifndef PLAYER_H
#define PLAYER_H

#include <iostream>
#include <string>
#include "SFML/Graphics.hpp"

class Player
{
public:
        Player();

        ~Player();

        std::string getName();
        int getHealth();
        int getMana();
        void update(float dt);
        void draw(sf::RenderWindow &window);
        void setName(std::string);
        void setHealth(int);
        void setMana(int);
        void movement(sf::RenderWindow &window);

private:
        std::string Name;
        int newHealth;
        int newMana;
        sf::Texture playerTexture;
        sf::Sprite playerSprite;
};

#endif
 

main.cpp
#include "SFML/Graphics.hpp"
#include "SFML/Window.hpp"
#include "Player.h"
#include <conio.h>
#include <iostream>
#include <string>

int main()
{
        sf::RenderWindow window(sf::VideoMode(800, 600), "Meet Ed");

        Player player1;

        sf::Clock clock;

        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                        {
                                window.close();
                        }
                }

                /*sf::Time time = clock.getElapsedTime();
                player1.update(time.asMilliseconds());
                clock.restart().asMilliseconds();*/


                window.clear(sf::Color(255, 255, 255));

                player1.draw(window);
                if (sf::Mouse::isButtonPressed(sf::Mouse::Right))
                {
                        player1.movement(window);
                }

                window.display();
        }
       
        return 0;
}
 
« Last Edit: December 30, 2014, 12:02:59 pm by GunnDawg »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Sprite movement/animation question.
« Reply #1 on: December 30, 2014, 12:18:54 pm »
This is almost certainly something you could solve with a debugger or a few more cout statements, since it's a simple matter of the movement() function not doing what you think it's doing.

That said, determining the direction with trigonometric functions and angles is fairly unusual, considering you can do the same thing with the x/y components.  For instance, if abs(x) > abs(y) and x > 0, then the player is facing right.  I'm fairly sure that would provide slightly shorter, clearer, faster code and no risk of floating point rounding errors.  Similarly, for the move() call you can normalize the totalMovement vector and multiply it by speed.



Also, I know I said this in your previous thread, but use the Vector2f operators!
        totalMovement.x = sf::Mouse::getPosition(window).x - playerSprite.getPosition().x;
        totalMovement.y = sf::Mouse::getPosition(window).y - playerSprite.getPosition().y;

        mousePoint.x = sf::Mouse::getPosition(window).x;
        mousePoint.y = sf::Mouse::getPosition(window).y;
is so much easier to read as:
        totalMovement = sf::Mouse::getPosition(window) - playerSprite.getPosition();
        mousePoint = sf::Mouse::getPosition(window);

GunnDawg

  • Newbie
  • *
  • Posts: 22
    • View Profile
    • Email
Re: Sprite movement/animation question.
« Reply #2 on: December 30, 2014, 12:41:35 pm »
I'll look into cleaning the code up. And you're right that the movement function isn't doing what I think it is doing, hence why I created this post. I added a cout for each one and the console output shows that's the source.y IS changing, but the sprite it self, IS NOT.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sprite movement/animation question.
« Reply #3 on: December 30, 2014, 12:52:02 pm »
So if everything is ok but the sprite is not moving, the next step is to check the values passed to playerSprite.move, right? Only you can do it, but I'm pretty sure that they will be too low: with a framerate of 60 FPS, your sprite will move 1.8 pixels per second, which is almost unnoticeable.

And as Ixrec already pointed out, using trigonometric functions here is overkill: direction can be deduced from the sign of X and Y, and (cos(atan2(y, x)), sin(atan2(y, x))) is just (x, y) normalized.
Laurent Gomila - SFML developer

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Sprite movement/animation question.
« Reply #4 on: December 30, 2014, 12:55:46 pm »
That might be because you never call setTextureRect() after the constructor.  The source variable by itself doesn't do anything since nobody else is looking at it.  Perhaps a private function setTextureRect(Direction) would be useful.

@Laurent: I believe he said the sprite is moving but the texture never changes.


And yet another code cleanliness thing: source.y being a Direction instead of an actual y coordinate is fairly strange.  It might be better to have a single Direction variable, a const array of IntRects for each sprite in the spritesheet, and use the enum as the index into that array (since you can explicitly specify the integer value of each Direction value).