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

Author Topic: Accelerating object doesn't "hit" the ground correctly after falling  (Read 1859 times)

0 Members and 1 Guest are viewing this topic.

Ganado

  • Newbie
  • *
  • Posts: 34
  • Moo, I say.
    • View Profile
    • FOnline Engine, check it out.
Using SFML 2.1, Code::Blocks 12.11

So far SFML seems really nice. However, I have an issue in this little practice code, it's probably something obvious that I'm not seeing... anyway, here's the code, I'll explain it after:

int main()
{
    const int WINDOW_WIDTH = 960;
    const int WINDOW_HEIGHT = 540;

    // Removed code, Renders "Window", with WIDTH/HEIGHT
    Window.setVerticalSyncEnabled(true); // 60 fps

    sf::Texture brickTexture;
    sf::Sprite brickImage;
    // Removed code, just loads the brick.png, a 60x40 image
    brickImage.setTexture(brickTexture);
    brickImage.setOrigin(brickImage.getLocalBounds().width/2.0, brickImage.getLocalBounds().height/2.0); // Sets sprite origin at (30, 20)
    brickImage.setPosition(WINDOW_WIDTH/2, WINDOW_HEIGHT/2);


        // Important code
    bool freefall = true;
    int i = 1;
    while (Window.isOpen())
    {
        sf::Event event;
        while(Window.pollEvent(event))
        {
            switch(event.type)
            {
            case sf::Event::MouseButtonPressed:
                if (event.mouseButton.button == sf::Mouse::Left)
                {
                    brickImage.setPosition(event.mouseButton.x, event.mouseButton.y);
                    freefall = true;
                    i = 1;
                }
                break;
            }
        }
        if (brickImage.getPosition().y >= (WINDOW_HEIGHT - WINDOW_HEIGHT/10.0))
            freefall = false;   // The position at which it stops falling is not constant...
        else if (freefall == true)
        {
            brickImage.move(0, i);
            i++;
        }

        Window.clear(); // Removed for the screenshot
        Window.draw(brickImage);

        Window.display();
    }

}
If you want compilable code, see: http://pastebin.com/cjhYfAne
Note that you'll need an image named brick.png to go with it (dimensions don't matter)

Problem:
Basically, this code is making a rectangle brick accelerate as it falls. I want the brick to stop falling at the same height on the screen each time (in this case, 9/10-ths of the screen height with respect to the center point of the brick), but the problem is that the end position is slightly different depending on how high you drop the brick from.
Here's an example, with Window.clear(); off:


See how the end position at the bottom of the screen of each brick dropped is different? Why does it not stop falling immediately after it reaches the cut-off point? I ask for some help please.

Also, if I'm placing certain parts of code in the wrong part of the loop in general, please tell me.

Unrelated questions:
In my while (Window.isOpen()) loop, if I have brickImage.move(0, 1), does that make it move 60 pixels per second? (60 if my Vsync/FPS is set to 60)

Also had a question of how things like the standard rand() function work without including <cstdlib> or how using time as a seed in srand can work without <ctime>.

Thank you for reading!
« Last Edit: August 10, 2013, 03:39:31 am by Ganado »

Jebbs

  • Sr. Member
  • ****
  • Posts: 358
  • DSFML Developer
    • View Profile
    • Email
Re: Accelerating object doesn't "hit" the ground correctly after falling
« Reply #1 on: August 10, 2013, 03:49:46 am »
They start at different locations, so their velocity is going to be different at the point when they get to/past the y value you want them to stop at. Unless you are tracking the movement per pixel they move, you will get some that have moved passed the point at which you want them to stop.

What I would do is inside this piece of code:

 if (brickImage.getPosition().y >= (WINDOW_HEIGHT - WINDOW_HEIGHT/10.0))
            freefall = false;   // The position at which it stops falling is not constant...

You add a little thing that changes the y value to where you want it to stop at. You can't go through the ground, right? This is like saying "The brink stopped falling and it now currently on top of the ground. BECAUSE I SAY SO."

 if (brickImage.getPosition().y >= (WINDOW_HEIGHT - WINDOW_HEIGHT/10.0))
{
     freefall = false;   // The position at which it stops falling is not constant...
     brickImage.setPosition(brickImage.getPosition().x,WINDOW_HEIGHT - WINDOW_HEIGHT/10.0);//so we make it constant!
}

That's the idea anyways!


Edit: Realized I forgot my curly braces in the second if statement I posted. Shame on me!
« Last Edit: August 10, 2013, 04:27:32 am by Jebbs »
DSFML - SFML for the D Programming Language.

Ganado

  • Newbie
  • *
  • Posts: 34
  • Moo, I say.
    • View Profile
    • FOnline Engine, check it out.
Re: Accelerating object doesn't "hit" the ground correctly after falling
« Reply #2 on: August 10, 2013, 04:18:35 am »
Thanks for the quick reply, I tested the code you gave me. That does work to get the correct end result, but the problem is that the brick noticeably "jumps" back up to the "ground" position if the previous position was below it.

The problem with my code seems to be with this part
        else if (freefall == true)
        {
            brickImage.move(0, i);
            i++;
        }
The brickImage.move(0, i); allows it to go past the ground line without first testing it... currently I'm trying to do something with a for loop to immediately test each pixel movement, but so far it's not working correctly and still jumps back up.

Jebbs

  • Sr. Member
  • ****
  • Posts: 358
  • DSFML Developer
    • View Profile
    • Email
Re: Accelerating object doesn't "hit" the ground correctly after falling
« Reply #3 on: August 10, 2013, 04:25:37 am »
Whoops!

Sorry about that. You should always look for a collision before you draw as stuff that happens during your "collision phase" could change the position something get's drawn at. This is a prime example.

Try this:

 
        if (freefall == true)
        {
            brickImage.move(0, i);
            i++;
        }
        if (brickImage.getPosition().y >= (WINDOW_HEIGHT - WINDOW_HEIGHT/10.0))
        {
            freefall = false;   // The position at which it stops falling is not constant...
            brickImage.setPosition(brickImage.getPosition().x,WINDOW_HEIGHT - WINDOW_HEIGHT/10.0);//so we make it constant!
        }

 


Edit:

Alternatively, since this example is very basic you can put the second if statement inside the first if you want:

 
        if (freefall == true)
        {
            brickImage.move(0, i);
            i++;
            if (brickImage.getPosition().y >= (WINDOW_HEIGHT - WINDOW_HEIGHT/10.0))
            {
                   freefall = false;   // The position at which it stops falling is not constant...
                    brickImage.setPosition(brickImage.getPosition().x,WINDOW_HEIGHT - WINDOW_HEIGHT/10.0);//so we make it constant!
            }
        }
       

 
« Last Edit: August 10, 2013, 04:30:36 am by Jebbs »
DSFML - SFML for the D Programming Language.

Ganado

  • Newbie
  • *
  • Posts: 34
  • Moo, I say.
    • View Profile
    • FOnline Engine, check it out.
Re: Accelerating object doesn't "hit" the ground correctly after falling
« Reply #4 on: August 10, 2013, 04:51:03 am »
That seems to work fine, thanks a lot for the help.

Before I looked at your latest reply, I was trying to figure it out myself and came up with this, which seems to do the same thing, but your code makes more sense.  :D
            if (freefall == true)
            {
                for (int j = 0; j < i; j++)
                {
                    if (brickImage.getPosition().y >= (WINDOW_HEIGHT - WINDOW_HEIGHT/10.0))
                    {
                        freefall = false;
                        break;
                    }
                    brickImage.move(0, 1);
                }
                i++;
            }

Anyway, it fixed the problem with jumping. The acceleration of the block seems to be the same as original post, so no problem with that either. Thanks again.
« Last Edit: August 10, 2013, 04:53:23 am by Ganado »