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

Author Topic: Ball in Pong only moves in 4 directions  (Read 5004 times)

0 Members and 1 Guest are viewing this topic.

lilbigwill99

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Ball in Pong only moves in 4 directions
« 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;
}




 

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Ball in Pong only moves in 4 directions
« Reply #1 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.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

lilbigwill99

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: Ball in Pong only moves in 4 directions
« Reply #2 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++)

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Ball in Pong only moves in 4 directions
« Reply #3 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. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Ball in Pong only moves in 4 directions
« Reply #4 on: November 22, 2016, 10:49:37 am »
I actually did a blog post on this a little while back.

grumpaladin

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Ball in Pong only moves in 4 directions
« Reply #5 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:

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:
  • Calculate the distance between the Ball's center and the center of the Paddle.
  • Compute the angle using cmath's sin() function, passing in the distance divided by the maximum desired angle. In my case, I used 50 as my maximum desired angle.

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.

lilbigwill99

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: Ball in Pong only moves in 4 directions
« Reply #6 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)

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Ball in Pong only moves in 4 directions
« Reply #7 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?

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.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

lilbigwill99

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: Ball in Pong only moves in 4 directions
« Reply #8 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

 

anything