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

Author Topic: How to make the sprite move when pushed by another sprite  (Read 1962 times)

0 Members and 1 Guest are viewing this topic.

Programmy

  • Newbie
  • *
  • Posts: 19
    • View Profile
How to make the sprite move when pushed by another sprite
« on: June 16, 2018, 07:45:22 am »
I'm having  a hard time making a sprite move when pushed, basically
it moves left all the time regardless of the code that I put in
basically I want the sprite to move left when pushed left, right when right
up when up and down when down

I'm getting
confused to where the  x an y coordinates are, I think -x is right +x left
and + y is up and -y is down or I may be wrong, need help


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



void main(int argc, char** argv[]) {



        sf::RenderWindow window;
        window.create(sf::VideoMode(800, 600), "test", sf::Style::Default);

        sf::Texture texture;
        texture.loadFromFile("c:/Users/jason/source/repos/SFML2/Eagle.png");
        sf::Sprite sprite(texture);
        sf::Sprite sprite2(texture);

        sf::Vector2u size = texture.getSize();
        sprite.setOrigin(size.x / 2, size.y / 2);


        sf::Vector2f increment(0.4f, 0.4f);


        sprite.setTexture(texture);
        sprite.setPosition(sf::Vector2f(0, 250));

        sprite2.setTexture(texture);
        sprite2.setOrigin(-200, -200);


        while (window.isOpen())
        {

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

                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                        {
                                sprite.move(-5, 0);
                        }
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                        {
                                sprite.move(+5, 0);
                        }
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                        {
                                sprite.move(0, -5);
                        }
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
                        {
                                sprite.move(0, +5);
                        }              
                       
                       
                        if (sprite.getGlobalBounds().intersects(sprite2.getGlobalBounds()))
                        {
                                if (sprite.getPosition().x > sprite2.getPosition().x)
                                        sprite2.move(+10, 0);  
                        }
                       
                }

                window.clear(sf::Color(255, 255, 255));
                window.draw(sprite);
                window.draw(sprite2);
                window.display();
        }


}


 
« Last Edit: June 16, 2018, 07:46:56 am by Programmy »

decoder

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: How to make the sprite move when pushed by another sprite
« Reply #1 on: June 16, 2018, 03:24:03 pm »
First of all, the coordinate system that most graphics libraries like SFML, SDL, etc. had been using is the Cartesian coordinates, where the origin (0, 0) sits at the top left corner of the rendering window. For example, if you were to draw an object and didn't specify its specific location, then its default location will be at the top left corner (unless you've specified its origin), and not at the center of the screen as you would expect. Refer to the attachment.

So here's the code overview
#include <SFML/Graphics.hpp>

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

bool checkCollision(const sf::FloatRect& rectA,
                                        const sf::FloatRect& rectB)
{
        return rectB.intersects(rectA);
}

void shiftSprite(sf::Sprite& sprite,
                                 const sf::Vector2f& speed,
                                 Direction dir,
                                 const sf::Time& deltaTime)
{
        sf::Vector2f offset;

        switch (dir)
        {
                case Direction::Left:
                        offset.x = -speed.x;
                        break;
                case Direction::Right:
                        offset.x = speed.x;
                        break;
                case Direction::Up:
                        offset.y = -speed.y;
                        break;
                case Direction::Down:
                        offset.y = speed.y;
                        break;
        }

        sprite.move(offset.x * deltaTime.asMilliseconds(),
                          offset.y * deltaTime.asMilliseconds());
}

void main()
{
        sf::RenderWindow window;
        window.create(sf::VideoMode(800, 600), "test", sf::Style::Default);
        window.setFramerateLimit(60);

        sf::Texture texture;
        texture.loadFromFile("protagonist.png");

        sf::Sprite sprite(texture);
        sf::Sprite sprite2(texture);

        sprite.setPosition(sf::Vector2f(0, 250));
        sprite.setOrigin(sprite.getLocalBounds().width / 2,
                                         sprite.getLocalBounds().height / 2);
        sprite2.setOrigin(-200, -200);

        sf::Vector2f speed(0.4f, 0.4f);
        sf::Clock timer;

        while (window.isOpen())
        {
                sf::Event event;
                sf::Time deltaTime = timer.restart();

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

                sf::Vector2f offset;
                Direction dir = Direction::Static;

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                {
                        offset.x = -speed.x;
                        dir = Direction::Left;
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                {
                        offset.x = speed.x;
                        dir = Direction::Right;
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                {
                        offset.y = -speed.y;
                        dir = Direction::Up;
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
                {
                        offset.y = speed.y;
                        dir = Direction::Down;
                }

                sprite.move(offset.x * deltaTime.asMilliseconds(),
                                  offset.y * deltaTime.asMilliseconds());

                if (checkCollision(sprite.getGlobalBounds(), sprite2.getGlobalBounds()))
                        shiftSprite(sprite2, speed, dir, deltaTime);
               
                window.clear(sf::Color(255, 255, 255));
                window.draw(sprite);
                window.draw(sprite2);
                window.display();
        }
}
 

Here's the explanation:
enum class Direction
{
        Up, Down, Left, Right, Static
};
 
Basically, this specifies the sprites' directions. The "Static" just says that the object is at rest.

bool checkCollision(const sf::FloatRect& rectA, const sf::FloatRect& rectB);
 
This function checks if any collision between the two rectangles happens, where rectA is the collider, and rectB is the bounding box.

void shiftSprite(sf::Sprite& sprite,
                       const sf::Vector2f& velocity,
                       Direction dir,
                       const sf::Time& deltaTime)
 
This function just basically moves the sprite. It takes the sprite object; the velocity (because it has a corresponding direction - the dir parameter); and the frame time or the delta time. The delta time makes your sprite to move smoothly real time.

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                {
                        offset.x = -speed.x;
                        dir = Direction::Left;
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                {
                        offset.x = speed.x;
                        dir = Direction::Right;
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                {
                        offset.y = -speed.y;
                        dir = Direction::Up;
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
                {
                        offset.y = speed.y;
                        dir = Direction::Down;
                }
 
You can't do this piece of code inside the poll event loop because sf::Keyboard::isKeyPressed checks if any key is being pressed not had been pressed.

Reference: https://en.sfml-dev.org/forums/index.php?topic=14350.0

Typically, there's a big difference
if (sf::Keyboard::isKeyPressed(sf::Keyboard::isKeyPressed(KEY)))
    // Checks if the key is being pressed

while (window.pollEvent(event))
    if (event.type == sf::Event::KeyReleased &&
        event.key.code == sf::Keyboard::KEY)
        // Checks if the key has been pressed
 

sprite.move(offset.x * deltaTime.asMilliseconds(), offset.y * deltaTime.asMilliseconds());

if (checkCollision(sprite.getGlobalBounds(), sprite2.getGlobalBounds()))
    shiftSprite(sprite2, speed, dir, deltaTime);
 
The code should not be interchanged as the checkCollision function checks the updated position of the sprite (collider).

The code above uses independent frame rate
window.setFramerateLimit(60);
.....
sprite.move(offset.x * deltaTime.asMilliseconds(),
                  offset.y * deltaTime.asMilliseconds());
 

Reference: https://maksimdan.gitbooks.io/sfml-and-gamedevelopement/content/frame_rate.html
« Last Edit: June 16, 2018, 03:27:09 pm by decoder »

Programmy

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: How to make the sprite move when pushed by another sprite
« Reply #2 on: June 16, 2018, 03:33:35 pm »
this helps a lot, thanks for the thorough explanation :)

 

anything