SFML community forums

Help => Graphics => Topic started by: JulianOri on June 24, 2014, 05:17:46 pm

Title: Change movement direction?
Post by: JulianOri on June 24, 2014, 05:17:46 pm
Hi! =)

I´m programming a little game where a ball flies through the window and when it hits the end of the window it shall change its direction. Here´s the code I´m using for this:

void Ball::update(float frametime)
{
        if (pSpriteB->getPosition().y >= 9)
        {
                pSpriteB->move(-400 * frametime, -400 * frametime);
        }
        else if (pSpriteB->getPosition().y <= 9)
        {
                pSpriteB->move(400 * frametime, 400 * frametime);
        }
}

But when the ball hits the window´s end, it just stops and vibrates a bit. What I thought was that the previous movement is still active and I have to end up this previous movement so that the new movement direction can be done without errors, but I didn´t find anything to end up a movement.

What shall I do? Why isn´t it moving correctly? Please help!  :D

Title: Re: Change movement direction?
Post by: Jesper Juhl on June 24, 2014, 05:38:03 pm
Simplest way to make something bounce off a wall is to just invert the x and y parts of the velocity/direction vector.
Title: Re: Change movement direction?
Post by: JulianOri on June 24, 2014, 05:44:40 pm
Hi!  :)

This sounds logic, but unfortunately I don´t have any knowledge on vectors. In school we will have this topic  in about 1 year and on top of that I don´t really understand how SFML handles vectors.

Do you think it will help when I deal with vector mathematics? :)

Julian
Title: Re: Change movement direction?
Post by: Nexus on June 24, 2014, 05:52:25 pm
In game development, vector algebra is absolutely crucial. It's not a very difficult topic, yet it comes in extremely handy because you can essentially get rid of low-level math like component-wise operations or trigonometry. And for more complex operations like the cross-product, there is not even a straightforward way without knowing vector algebra.

If you're interested, I suggest you already have a look at vectors, it will certainly be of advantage in school :)

Having said that, you want to make the ball movement dependent on the velocity, not the position. Velocity is simply the change in position per time, or velocity = distance/time. On the other hand, this lets you infer the travelled distance as distance = velocity*time. With vectors, this extends to every component.
Title: Re: Change movement direction?
Post by: Jesper Juhl on June 24, 2014, 05:54:08 pm
A basic knowledge of vector math makes many things like this a lot simpler, yes. Reading up on basic vector math would definitely be something I'd recommend.
If you want some easy to use classes to help you, take a look at the vector stuff in the Thor library: http://www.bromeon.ch/libraries/thor/index.html .

I don't have time today, but unless someone beats me to it I could make a simple bouncing ball example for you tomorrow evening.
Title: Re: Change movement direction?
Post by: JulianOri on June 24, 2014, 06:08:45 pm
Hey guys!  :)

Thanks for all your expenditure! =)

I know that vectors are extremely important for game programming, so I think I´m going to deal with them. I hope I find a better way than this I used in my code example.

Making a little example a ball bouncing around would be really nice, but when there´s too much expenditure then of course you haven´t to do it for me.

Julian :D
Title: Re: Change movement direction?
Post by: Jesper Juhl on June 24, 2014, 06:14:33 pm
It won't take long to do. I'll try to find the time tomorrow - no problem.

In the mean time you could start reading here: http://mathinsight.org/vector_introduction and there are many other good introduction resources to be found online.
Title: Re: Change movement direction?
Post by: Jesper Juhl on June 25, 2014, 10:59:40 pm
Ok, as promised, here's a simple example of a bouncing ball.

Stick it in a file called bounce.cc and then you can build it (on Linux) like this:
$ clang++ -std=c++11 -lsfml-window -lsfml-graphics -lsfml-system -o bounce bounce.cc
and then run it like so:
$ ./bounce

Each time you run the program the ball will get a random direction and speed, so run it a few times to see different bounces.

#include <SFML/Graphics.hpp>
#include <random>
#include <functional>
#include <cstdlib>
#include <cmath>

int main()
{
    const int window_width = 400;
    const int window_height = 300;
    const float ball_radius = 16.f;
    const int bpp = 32;

    sf::RenderWindow window(sf::VideoMode(window_width, window_height, bpp), "Bouncing ball");
    window.setVerticalSyncEnabled(true);

    std::random_device seed_device;
    std::default_random_engine engine(seed_device());
    std::uniform_int_distribution<int> distribution(-16, 16);
    auto random = std::bind(distribution, std::ref(engine));

    sf::Vector2f direction(random(), random());
    const float velocity = std::sqrt(direction.x * direction.x + direction.y * direction.y);

    sf::CircleShape ball(ball_radius - 4);
    ball.setOutlineThickness(4);
    ball.setOutlineColor(sf::Color::Black);
    ball.setFillColor(sf::Color::Yellow);
    ball.setOrigin(ball_radius / 2, ball_radius / 2);
    ball.setPosition(window_width / 2, window_height / 2);

    sf::Clock clock;
    sf::Time elapsed = clock.restart();
    const sf::Time update_ms = sf::seconds(1.f / 30.f);
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if ((event.type == sf::Event::Closed) ||
                ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) {
                window.close();
                break;
            }
        }

        elapsed += clock.restart();
        while (elapsed >= update_ms) {
            const auto pos = ball.getPosition();
            const auto delta = update_ms.asSeconds() * velocity;
            sf::Vector2f new_pos(pos.x + direction.x * delta, pos.y + direction.y * delta);

            if (new_pos.x - ball_radius < 0) { // left window edge
                direction.x *= -1;
                new_pos.x = 0 + ball_radius;
            } else if (new_pos.x + ball_radius >= window_width) { // right window edge
                direction.x *= -1;
                new_pos.x = window_width - ball_radius;
            } else if (new_pos.y - ball_radius < 0) { // top of window
                direction.y *= -1;
                new_pos.y = 0 + ball_radius;
            } else if (new_pos.y + ball_radius >= window_height) { // bottom of window
                direction.y *= -1;
                new_pos.y = window_height - ball_radius;
            }
            ball.setPosition(new_pos);

            elapsed -= update_ms;
        }

        window.clear(sf::Color(30, 30, 120));
        window.draw(ball);
        window.display();
    }

    return EXIT_SUCCESS;
}
 
Title: Re: Change movement direction?
Post by: JulianOri on June 28, 2014, 02:14:27 pm
Thank you very much!

 ;D
Title: Re: Change movement direction?
Post by: Hapax on June 28, 2014, 02:45:09 pm
Just as an aside, I noticed that in your logic, you are testing to see if the values are equal (>=) in the first if, then - once you are certain that it is not (else) - testing to see if it is equal again (<=). This means that the only time that it runs the second part is when it is less than. As soon as it becomes equal again, it switches back to the first code.