SFML community forums

Help => General => Topic started by: lilbigwill99 on November 22, 2016, 12:08:56 am

Title: Ball in Pong only moves in 4 directions
Post by: lilbigwill99 on November 22, 2016, 12:08:56 am
I was wondering how you would go about trying to change the direction of the ball when a collision happens a little relative to the angle that the ball hit at, rather than what I have been doing and just changing the direction of the x or y axis. Could someone show this in code, and why they did what they did and why what I am doing is wrong? Also, if someone wants bonus points, could you tell me why the ball trips out when it hits the top or bottom of a paddle?


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

using std::cout;
using std::endl;

int main()
{

    srand(time(0));

    const int WINDOW_WIDTH = 720;
    const int WINDOW_HEIGHT = 480;

    sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "PONG BOIII");
    window.setFramerateLimit(60);
    sf::Event event;

    ///////paddles///////

    const int PADDLE_WIDTH = 25;
    const int PADDLE_HEIGHT = 100;

    sf::RectangleShape paddle1(sf::Vector2f(PADDLE_WIDTH, PADDLE_HEIGHT));
    paddle1.setOrigin(PADDLE_WIDTH / 2, PADDLE_HEIGHT / 2);
    paddle1.setPosition(50, WINDOW_HEIGHT / 2);

    sf::RectangleShape paddle2(sf::Vector2f(PADDLE_WIDTH, PADDLE_HEIGHT));
    paddle2.setOrigin(PADDLE_WIDTH / 2, PADDLE_HEIGHT / 2);
    paddle2.setPosition(WINDOW_WIDTH - 50, WINDOW_HEIGHT / 2);
    float AIspeedDown = 0.5;
    float AIspeedUP = -0.5;

    /////the ball////////

    const int BALL_RADIUS = 10;
    float bX = 0.5;
    float bY = 0.5;

    sf::CircleShape theBall(BALL_RADIUS);
    theBall.setPointCount(300);
    theBall.setOrigin(BALL_RADIUS / 2, BALL_RADIUS / 2);
    theBall.setPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
    theBall.setFillColor(sf::Color::Cyan);

    sf::Clock clock;
    sf::Time time;

    while (window.isOpen()) {

        while (window.pollEvent(event)) {

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

        } //ends events

        //moves paddle
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
            paddle1.move(0, -0.5 * time.asMilliseconds());
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
            paddle1.move(0, 0.5 * time.asMilliseconds());
        }

        //checking window collision
        if (paddle1.getPosition().y - paddle1.getOrigin().y <= 0) {
            paddle1.move(0, 0.5 * time.asMilliseconds());
        }

        if (paddle1.getPosition().y + paddle1.getOrigin().y >= WINDOW_HEIGHT) {
            paddle1.move(0, -0.5 * time.asMilliseconds());
        }

        //ball stuff
        theBall.move(bX * time.asMilliseconds(), bY * time.asMilliseconds());

        if (theBall.getPosition().y <= 0 || theBall.getPosition().y >= WINDOW_HEIGHT) {
            bY *= -1;
        }

        if (theBall.getPosition().x >= WINDOW_WIDTH) {
            theBall.setPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
            bX = 0.5;
        }

        if (theBall.getPosition().x <= 0) {
            theBall.setPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
            bX = 0.5;
        }

        if (theBall.getGlobalBounds().intersects(paddle1.getGlobalBounds())) {

            bX *= -1;
        }

        if (theBall.getGlobalBounds().intersects(paddle2.getGlobalBounds())) {

            bX *= -1;
        }

        //AI for enemy paddle
        if (paddle2.getPosition().y < theBall.getPosition().y) {

            paddle2.move(0, AIspeedDown * time.asMilliseconds());
        }

        if (paddle2.getPosition().y > theBall.getPosition().y) {

            paddle2.move(0, AIspeedUP * time.asMilliseconds());
        }

        time = clock.restart();

        ////////update positions//////

        //////////////////////////////

        window.clear(sf::Color::Blue);

        //draw here//

        window.draw(paddle1);
        window.draw(paddle2);
        window.draw(theBall);

        /////////////

        window.display();

    } //ends game loop

    return 0;
}




 
Title: Ball in Pong only moves in 4 directions
Post by: eXpl0it3r on November 22, 2016, 01:58:15 am
I can't provide any code, but the basic idea is to have a direction vector and when you collide, you can simply change the x & y direction values. If you want to, yoi can calculate the angle between the direction and the surface and calculate the values so you get the same output angle. For axis aligned lines, you just need to either negate the x or the y value depending how the line is oriented.
Title: Re: Ball in Pong only moves in 4 directions
Post by: lilbigwill99 on November 22, 2016, 02:57:22 am
I can't provide any code, but the basic idea is to have a direction vector and when you collide, you can simply change the x & y direction values. If you want to, yoi can calculate the angle between the direction and the surface and calculate the values so you get the same output angle. For axis aligned lines, you just need to either negate the x or the y value depending how the line is oriented.

Thank you for your time and answer, but I don't think I quite understand lol. How exactly would I go about getting the angle at which I can use for an output angle? I'm pretty sure you said I should store my x and y directions in a vector right? I'm not sure how that helps me at the moment seeing as how I am not keeping track of the balls location (the only time I've used vectors was for keeping track of previous events, im only a month into c++)
Title: Ball in Pong only moves in 4 directions
Post by: eXpl0it3r on November 22, 2016, 08:54:45 am
This has little to do with C++ and more to do with math, especially vector math. If you have no idea about vector math, I suggest you go read up on it. ;)
Title: Re: Ball in Pong only moves in 4 directions
Post by: fallahn on November 22, 2016, 10:49:37 am
I actually did a blog post (http://trederia.blogspot.co.uk/2016/02/2d-physics-101-pong.html) on this a little while back.
Title: Re: Ball in Pong only moves in 4 directions
Post by: grumpaladin on November 22, 2016, 07:53:58 pm
I'm not incredibly mathematically inclined, so this is something that I kind of struggled with too.

The solution that I came up with is to compute an angle based on where the Ball strikes the paddle. The "angle of reflection" becomes much more severe as the Ball hits closer to one of the extreme ends (top or bottle of the Paddle). Similarly, the angle is less severe the closer to the center the ball strikes. This way, the player can bounce the Ball upwards if they position the paddle in a way that it hits towards the top; likewise for bouncing the Ball downwards.

It looks a little something like this:
(https://s12.postimg.org/jc2rll4rh/pong_angle.png)
The closer to the center/green the Ball hits, then a smaller angle is computed and the Ball's reflection angle isn't changed drastically.
The closer to the edges/orange-red the Ball hits, then a larger angle is computed and the reflection angle is much more extreme.

Mathematically, this is my approach:

Hint: just following the math won't replicate the way I did it entirely. In order to do that, remember that SFML's Y axis is reversed from normal 2D coordinates that we do in math.

Hope this helps.
Title: Re: Ball in Pong only moves in 4 directions
Post by: lilbigwill99 on November 23, 2016, 01:29:01 am
Thank you everyone for your replies, I'm glad you guys are cool on this website haha. 8)
Title: Re: Ball in Pong only moves in 4 directions
Post by: Hapax on November 23, 2016, 09:26:10 pm
Also, if someone wants bonus points, could you tell me why the ball trips out when it hits the top or bottom of a paddle?
Bonus points? (http://i.imgur.com/9TOXxWu.png)

It's likely that you're assuming that whenever the ball hits the paddle, you should flip the x velocity as if it hit the front (side) of the paddle. However, when it hits the top (or bottom), it's already passed the point it would have "reflected" on the front. Therefore, after flipping the x, it will still be travelling with the same y velocity (down, if hitting the top). During the next test, the ball will still be inside the paddle, travelling constantly downwards. Since it's still colliding, you flip the x again. This repeats until it exits the bottom of the paddle.

Does this describe what you meant by "trip out"?

Remember to test each collision that may occur (test front, top and bottom explicitly) and, not mentioned above, move the ball to a position where it is no longer in contact with the paddle immediately after collision is detected.
Title: Re: Ball in Pong only moves in 4 directions
Post by: lilbigwill99 on November 24, 2016, 08:33:48 am

Does this describe what you meant by "trip out"?



Haha thank you I don't know why I didn't figure that one out on my own