0

I'm making a simple simulation of a ball bouncing. I already implemented gravity, but I don't know how to handle for collisions (make the ball change direction). I tried reverting the velocity, but that didn't work.

// random start velocity
float v = 2.f;

// force
float f = 0.f + (v*t) + (1/2.f)*G*t;

std::cout << f << "\n";

// collision happened
if ((ball.getPosition().y + ball.getRadius()) > 400.f) {
    // revert the velocity
    v = -v;
}

ball.setPosition(sf::Vector2f(ball.getPosition().x, f));

Here is the full code:

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

//calculate the distance between the ball and    the ground
float distance_to_ground(float ball_y, float ground_y){
    return (float)(ball_y - ground_y);
}

int main() {
    // gravity constant
    const float G = 9.807;

    // create the window
    sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
    window.setFramerateLimit(60);

    sf::CircleShape ball(30);
    ball.setPosition(window.getSize().x/2.f, 100);
    ball.setOrigin(ball.getRadius(),ball.getRadius());

    //mass of the ball
    const float m1 = ball.getRadius();

    sf::Clock TimeDelta;
    // run the program as long as the window is open
    while (window.isOpen())
    {
        // check all the window's events that were triggered since the last iteration of the loop
        sf::Event event;
        while (window.pollEvent(event))
        {
            // "close requested" event: we close the window
            if (event.type == sf::Event::Closed)
                window.close();
        }

        sf::Time elapsed = TimeDelta.getElapsedTime();
        float t = elapsed.asSeconds();

        // distance between the ball and the ground
        float R = distance_to_ground(ball.getPosition().y, window.getSize().y);

        // random start velocity
        float v = 2.f;

        // force
        float f = 0.f + (v*t) + (1/2.f)*G*t;

        std::cout << f << "\n";

        // collision happened
        if ((ball.getPosition().y + ball.getRadius()) > 400.f){
            // change the velocity to negative
            v = -v;
        }

        ball.setPosition(sf::Vector2f(ball.getPosition().x, f));

        // clear the window with black color
        window.clear(sf::Color::Black);

        // draw everything here...
        window.draw(ball);

        // end the current frame
        window.display();
    }
    return 0;
}
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 1
    What is your question? I think you only want to change velocity if it's going down. Because then it might be switched back at next iteration. Also why is force equal to position? That does not make sense physically. Have you tried debugging the code to see whether it behaves as expected? – Quimby May 29 '22 at 15:23
  • possibly related https://stackoverflow.com/questions/72027998/ – Jeffrey May 29 '22 at 15:38
  • see https://stackoverflow.com/a/71827702/2521214 and all sublinks in there – Spektre May 30 '22 at 09:00

1 Answers1

1
//collision happened
if ((ball.getPosition().y + ball.getRadius()) > 400.f){
    // revert the velocity 
    v = -v;
}

This can result in the ball bouncing up and down, and falling through. You need:

//collision happened
if ((ball.getPosition().y + ball.getRadius()) > 400.f){
    // make sure the velocity is downwards.
    v = -std::abs(v);
}
Jeffrey
  • 11,063
  • 1
  • 21
  • 42