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

Author Topic: [Q] Adding Gravity to My Code  (Read 6175 times)

0 Members and 1 Guest are viewing this topic.

UchihaKite

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
[Q] Adding Gravity to My Code
« on: May 16, 2016, 02:20:27 am »
Good Evening!

I'm back with another question that hopefully someone can help me out with. This week I was required to create a ball that would be launched from the bottom left corner of the screen, and continuously bounce off the surfaces of the screen. The longer I hold Spacebar, the faster the ball would get. I managed to complete my assignment a lot quicker than I thought I would, so I thought I would contact my teacher and see if I can't do something extra. He told me to add Gravity to my code. This is all he gave me.

Implement gravity into your ball movement:
- This will apply acceleration to your physics now.
- Remember, Velocity is the change in position per second, while acceleration is the change in Velocity per second.
- Gravity in our "Game" should be between 500 - 1500 Pixels/s^2

I have been trying to do this for a couple of days now, however I have been unable to implement it into my code. I know their are multiple ways of doing everything in coding, but from everything I have seen online and on tutorial videos, none of the methods have been working. So, I was hoping someone here has run into the same problems as me, and will be able to help me out.

Thank you all in advance for taking the time to look at my code, and helping me out!

// Engine.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <SFML/Graphics.hpp>

using namespace std;

void applyGravity(float, float);

float yVelocity;

int main()
{
        float Power = 0.0f;
        bool toMove = false;

        float Time;

        sf::RenderWindow window(sf::VideoMode(1024, 512), "Welcome to SDVA 203!");
        sf::CircleShape shape(25);
        shape.setPosition(0, 486);
        shape.setOrigin(shape.getRadius(), shape.getRadius());
        shape.setFillColor(sf::Color::White);

        sf::Clock clock;
        float angleInDegrees = 225;
        float angleInRadians = angleInDegrees * 2 * 3.1415 / 360;
        float xVelocity = cos(angleInRadians) * 100;
        yVelocity = sin(angleInRadians) * 100;
        while (window.isOpen())
        {
                sf::Time dt = clock.restart();
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                window.close();

                        if (event.type == sf::Event::KeyReleased)
                        {
                                if (event.key.code == sf::Keyboard::Space)
                                {
                                        toMove = true;
                                }
                        }

                        if (event.type == sf::Event::KeyPressed)
                        {
                                if (event.key.code == sf::Keyboard::Num1)
                                {

                                        xVelocity = cos(angleInRadians) * 100;
                                        yVelocity = sin(angleInRadians) * 100;
                                }
                                if (event.key.code == sf::Keyboard::Num2)
                                {

                                        xVelocity = cos(angleInRadians) * 300;
                                        yVelocity = sin(angleInRadians) * 300;
                                }
                                if (event.key.code == sf::Keyboard::Num3)
                                {

                                        xVelocity = cos(angleInRadians) * 600;
                                        yVelocity = sin(angleInRadians) * 600;
                                }
                                if (event.key.code == sf::Keyboard::Num4)
                                {

                                        xVelocity = cos(angleInRadians) * 1200;
                                        yVelocity = sin(angleInRadians) * 1200;
                                }
                                if (event.key.code == sf::Keyboard::Space)
                                {
                                        toMove = false;
                                }
                        }
                }

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
                {
                        Power += dt.asSeconds();

                        if (Power > 2.0f)
                        {
                                xVelocity = cos(angleInRadians) * 100;
                                yVelocity = sin(angleInRadians) * 100;
                                std::cout << "Power Level is at 100!" << std::endl;
                        }
                        if (Power > 4.0f)
                        {
                                xVelocity = cos(angleInRadians) * 300;
                                yVelocity = sin(angleInRadians) * 300;
                                std::cout << "Power Level is at 300!" << std::endl;
                        }
                        if (Power > 6.0f)
                        {
                                xVelocity = cos(angleInRadians) * 600;
                                yVelocity = sin(angleInRadians) * 600;
                                std::cout << "Power Level is at 600!" << std::endl;
                        }
                        if (Power > 8.0f)
                        {
                                xVelocity = cos(angleInRadians) * 1200;
                                yVelocity = sin(angleInRadians) * 1200;
                                std::cout << "Power Level is at 1200!" << std::endl;
                        }
                        if (Power > 10.0f)
                        {
                                xVelocity = cos(angleInRadians) * 9001;
                                yVelocity = sin(angleInRadians) * 9001;
                                std::cout << "Power Level Over 9000!" << std::endl;
                        }
                }

                if (toMove == true)
                {
                        shape.move(xVelocity * dt.asSeconds(), yVelocity * dt.asSeconds());
                        cout << xVelocity << yVelocity << endl;

                        applyGravity(500.0, 500.0);
                }

                sf::Vector2f position = shape.getPosition();
               
                if (position.y <= shape.getRadius())
                {
                        yVelocity *= -1;
                        shape.setPosition(position.x, shape.getRadius());
                }

                if (shape.getRadius() + position.y >= 512)
                {
                        yVelocity *= -1;
                        shape.setPosition(position.x, 512 - shape.getRadius());
                }
                if (position.x <= shape.getRadius())
                {
                        xVelocity *= -1;
                        shape.setPosition(shape.getRadius(), position.y);
                }
                if (shape.getRadius() + position.x >= 1024)
                {
                        xVelocity *= -1;
                        shape.setPosition(1024 - shape.getRadius(), position.y);
                }

                if (shape.getRadius() + position.y >= 512)
                {
                        yVelocity = yVelocity / 2.0f;
                }

                //std::cout << "Ball position is " << position.x <<","<<position.y << std::endl;

                window.clear();
                window.draw(shape);
                window.display();
        }
        return 0;
}

void applyGravity(float gravity, float time)
{
        yVelocity = yVelocity + (gravity * time);
        if (yVelocity < .01)
        {
                yVelocity = 0;
        }
}
 

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: [Q] Adding Gravity to My Code
« Reply #1 on: May 16, 2016, 02:29:31 am »
What doesn't work?

Why are you passing a fixed value to "applyGravity" for the time parameter?
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

UchihaKite

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
Re: [Q] Adding Gravity to My Code
« Reply #2 on: May 16, 2016, 02:37:22 am »
I was passing fixed values into the applyGravity to just play around with the numbers to see if it was my values that were messing everything up or my function. I'm still new, so, I have to play around sometimes to figure out what I did wrong.

I believe it is the code in the function that isn't working. When I run it, nothing changes at all. The ball is supposed to slow down every time it hits the bottom of the window, and adding gravity should produce a different affect, but when I run the code nothing different happens.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: [Q] Adding Gravity to My Code
« Reply #3 on: May 16, 2016, 04:44:10 am »
I don't think you should be adding 250,000 to the y velocity.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

UchihaKite

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
Re: [Q] Adding Gravity to My Code
« Reply #4 on: May 16, 2016, 05:26:37 am »
O_o

Is that what my applyGravity is doing?! I'm only supposed to add 500 pixels per second squared.....What would be the correct input for that?

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: [Q] Adding Gravity to My Code
« Reply #5 on: May 16, 2016, 06:52:44 am »
O_o

Is that what my applyGravity is doing?! I'm only supposed to add 500 pixels per second squared.....What would be the correct input for that?
yes, as Hapax said you passed 500 as gravity and 500 as time that means you adding  500 * 500 = 250,000 to y velocity which is huge number.
 
in your applyGravity() should not take time, time will be evaluated later with move() function. also, you need to  apply the gravity  before call move(). like so,
if (toMove)
{
    applyGravity(gravity);
    shape.move(xVelocity * dt.asSeconds(), yVelocity * dt.asSeconds());
}

UchihaKite

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
Re: [Q] Adding Gravity to My Code
« Reply #6 on: May 16, 2016, 07:13:12 am »
I apologize in advance for my confusion, but I cannot begin to express how much I appreciate the both of you taking the time to help me.

I guess the reason I am confused is because of the "500 Pixels/s^2" aspect of his instructions. So, I think the appropriate question from me should've been, what is the correct formula (Code) that should be in my function? Originally I thought it'd be squaring 500 and adding it to yVelocity twice a second? Or am I just confusing myself by my teachers choice of words? >.<

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: [Q] Adding Gravity to My Code
« Reply #7 on: May 16, 2016, 02:40:12 pm »
Mortal's way is probably the most common way to apply gravity in a game: apply it a fixed amount for a small period of time and work in steps. If you're adding gravity to a game, this is the way to go.

However, be aware that, mathematically, this might not be very accurate (it's a close approximation). Velocity isn't technically affected every small step but constantly. Gravity in this way would require time to be used in its calculations. Since your velocity would be later multiplied by the time passed, gravity could be stored as a separate velocity and just added on without multiplying by time (if it has already been multiplied by it).

That said, your 500 pixels per second squared would be 500 * (time * time). Note that if time should be less than a second (one) as that would move it 500 pixels in one frame (frames are most often much smaller than a second).
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

UchihaKite

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
Re: [Q] Adding Gravity to My Code
« Reply #8 on: May 16, 2016, 05:39:48 pm »
Thank you both for the replies! This is helping me out a lot!

So, at this point, when I launch the ball it shoots up properly, and then the gravity shoots it back down quickly. So, it is kind of working. It's like it is bouncing but just shooting back down about a second into it being in the air. I feel like I am getting close, but I am either missing something or my formula is incorrect. Here is what I added/edited

void applyGravity(float Gravity);

float yVelocity;

// The function and yVelocity are outside of my main loop
// yVelocity is fully declared inside of the main loop

        yVelocity = sin(angleInRadians) * 100;

// I made an if statement to help keep elapsedTime to just about a second

                if (elapsedTime > 2.0)
                {
                        elapsedTime = 0.0;
                }

// I put the function in an if statement so it only fires about every second, otherwise it caused my ball to just zoom back and forth on the ground.

                if (toMove == true)
                {
                        if (elapsedTime < 2.0 && elapsedTime >= 1.0)
                        {
                                applyGravity(Gravity);
                        }
                        shape.move(xVelocity * dt.asSeconds(), yVelocity * dt.asSeconds());
                        cout << xVelocity << yVelocity << endl;
                }

// And this is my function. I have a set amount for the time because the "per second" part of his instructions, I was assuming that meant Time should only be about 1 second?

void applyGravity(float Gravity)
{
        yVelocity = (Gravity * (1.0 * 1.0)) + yVelocity;
}
 

Edit:
P.S. Should anything be done to xVelocity during all of this? I noticed that when I bumped up the power of launching the ball up to make it bounce around more, all that ends up happening is it starts bouncing off the sides of the window and barely skimming the "ground"
« Last Edit: May 16, 2016, 05:44:16 pm by UchihaKite »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: [Q] Adding Gravity to My Code
« Reply #9 on: May 16, 2016, 05:49:12 pm »
What is "elapsedTime" and why are you resetting it every two seconds?

If you are setting elapsedTime to zero whenever it passes two, why are you then testing to see if it's under two?
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

UchihaKite

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
Re: [Q] Adding Gravity to My Code
« Reply #10 on: May 16, 2016, 06:06:26 pm »
I was using elapsedTime to keep track of One Second, that way the function only fires every seconds, rather than through every pass. When I tried firing the function without the little "timer" all that would happen is the ball would just move back and forth without launching. When I set the function in the if statement to have it fire about every second, the ball produced more of a "bounce" effect.

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: [Q] Adding Gravity to My Code
« Reply #11 on: May 16, 2016, 11:39:57 pm »
@Hapax, you are correct. my attempt solution was came from frustration when i was calculating the math in piece of paper i always end up with undesired results doe to time in velocity formula. so, i just treated the gravity as velocity instead of acceleration which is wrong mathematically but it some how works for me by making the initial velocity much higher with negative value as direction to up and then for every frame i added initial velocity to "gravity velocity" before call move() function. this works fine in my game be cause i have free choices to determine the values of gravity and initial velocity. here the game that i was working on: https://github.com/MORTAL2000/Simple-Super-Mario-

here a few suggestions:
1) it's always recommended to use fixed timestep when the game applies physic.
2) remove the "timer", i don't think this is a proper way to handle the physic in your game. better to let physic flow regularly, this is what should be the game or real world physic behaved.
3) the possible implementation will be
if (toMove)
{
    yVelocity += gravity * dt.asSeconds(); // gravity could be negative value here: -500
    shape.move(xVelocity * dt.asSeconds(), yVelocity * dt.asSeconds());
}
NOTE: i haven't tested it but you may try it.
« Last Edit: May 17, 2016, 12:18:13 am by MORTAL »

UchihaKite

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
Re: [Q] Adding Gravity to My Code
« Reply #12 on: May 17, 2016, 10:24:35 pm »
Ah man! I don't know why I didn't think of just using delta time >.< I guess I was just confused by his instructions. Perhaps he has a different way of doing it, but your method worked perfectly for what I was trying to accomplish, so, Thank You Mortal! You're a life saver man!

I do need to ask though, so I full understand your method. What exactly do you mean by a "fixed timestamp"?

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: [Q] Adding Gravity to My Code
« Reply #13 on: May 17, 2016, 10:36:59 pm »
I'm sorry if I confused you; I was just trying to cover the fact that if you used fixed timestep rather than more accurate mathematical gravity calculations, it'll be slightly less physically accurate. The key-word there is "slightly". I wasn't sure if you needed accurate calculations so I was trying to explain how it wasn't perfect to use delta-time. However, for a game, it's almost always perfect! :)

"Fixed timestep" means a set amount of time that is processed. Never anything more or less. That was, the logic/physics etc. can be more reliable and you can predict more of what can happen.
For more information on this subject, a very good article on this subject can be found here:
http://gafferongames.com/game-physics/fix-your-timestep/

If you have trouble understanding it (most people do, at least the first read through), you may want to consider using my timing library, Kairos, to simplify the procedure using its Timestep or Timestep Lite class.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

UchihaKite

  • Newbie
  • *
  • Posts: 33
    • View Profile
    • Email
Re: [Q] Adding Gravity to My Code
« Reply #14 on: May 29, 2016, 11:03:32 pm »
Don't worry! I am only about as confused as anyone would be their first time doing something like this :D You made everything very clear and helped me out a lot! Thank you again!

How would I go about including your library in the SFML stuff? :O