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

Author Topic: Moving a ball with FPS  (Read 3241 times)

0 Members and 1 Guest are viewing this topic.

DylanMorgan

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Moving a ball with FPS
« on: February 01, 2017, 05:32:26 pm »
Hey guys, I really don't have a clue how to do this. I have an fps counter in the main loop using Sf::Clock and Sf::Time. But I do not know how to make it so my ball will move at a constant rate no matter the frame rate. Can someone point me in the right direction and give me a bit of advice on how to go about this?

ball.cpp
#include "Stdafx.h"
#include "ball.h"

Ball::Ball(int startPositionY, int startPositionX)
{
        position.x = startPositionX;
        position.y = startPositionY;

        startingPosition = position;

        colour = sf::Color::White;

        ball.setRadius(radius);
        ball.setFillColor(colour);
        ball.setPosition(position);
}

Ball::~Ball()
{
}

sf::CircleShape Ball::getBall()
{
        return ball;
}

void Ball::setVelocity(int tempVelocityX, int tempVelocityY)
{
        xVelocity = tempVelocityX;
        yVelocity = tempVelocityY;
}

float Ball::getVelocityX()
{
        return xVelocity;
}

void Ball::reboundSides()
{
        xVelocity = -xVelocity;
}

void Ball::reboundSurface()
{
        position.y -= (yVelocity * 50);
        yVelocity = -yVelocity;
}

void Ball::update()
{
        // Update the ball position variables
        position.y += yVelocity;
        position.x += xVelocity;

        // Move the ball
        ball.setPosition(position);
}

void Ball::hitBottom()
{
        position.x = startingPosition.x;
        position.y = startingPosition.y;
}

sf::FloatRect Ball::getPosition()
{
        return ball.getGlobalBounds();
}

the part of main.cpp that involves ball

                sf::Time time = clock.getElapsedTime();
                std::cout << 1.0f / time.asSeconds() << std::endl;

                // Handle ball hitting the bottom
                if (ball.getPosition().top > windowHeight)
                {
                        // reverse the ball direction
                        ball.hitBottom();
                }

                // Handle ball hitting top
                if (ball.getPosition().top < 0)
                {
                        ball.reboundSurface();
                }

                // Handle ball hitting sides
                if (ball.getPosition().left < 0 || ball.getPosition().left + 10 > windowWidth)
                {
                        ball.reboundSides();
                }

                // Has the ball hit the bat?
                if (ball.getPosition().intersects(paddle.getPosition()))
                {
                        // Hit detected so reverse the ball
                        ball.reboundSurface();
                }

                // Has the ball hit a block in the 1st row?
                for (unsigned int i = 0; i < blockContainer.getSize(); i++)
                {
                        if (ball.getPosition().intersects(blockContainer.getContainer()[i].getPosition()))
                        {
                                // testing
                                std::cout << "Hit 1st row, block: " << i << std::endl;

                                // Reverse ball
                                ball.reboundSurface();

                                // Delete block
                                blockContainer.deleteObjectFromVector(i);
                                i--;

                                // Play sound effect
                                sound.play();
                                break;
                        }
                }
               
                // Has the ball hit a block in the 2nd row?
                for (unsigned int i = 0; i < blockContainer2.getSize(); i++)
                {
                        if (ball.getPosition().intersects(blockContainer2.getContainer()[i].getPosition()))
                        {
                                // testing
                                std::cout << "Hit 2nd row, block: " << i << std::endl;

                                // Reverse ball
                                ball.reboundSurface();

                                // Delete Block
                                blockContainer2.deleteObjectFromVector(i);
                                i--;

                                // Play sound effect
                                sound.play();
                                break;
                        }
                }

                ball.setVelocity(time.asSeconds(), time.asSeconds());
                ball.update();

                window.clear();

                // draw objects
                window.draw(paddle.getPaddle());
                window.draw(ball.getBall());

                blockContainer.drawContainer(window);
                blockContainer2.drawContainer(window);

                // Reset clock
                clock.restart().asSeconds();

                window.display();
        }

I don't really understand how to do this. I have made a guess but it doesn't seem to work. The ball shows on screen but is still.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11028
    • View Profile
    • development blog
    • Email
Moving a ball with FPS
« Reply #1 on: February 01, 2017, 05:54:26 pm »
The simplest solution is to do:
while(window.isOpen()) {
sf::Time dt = clock.restart();
// ...
pos += velocity * dt.asSeconds();
 
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

DylanMorgan

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Moving a ball with FPS
« Reply #2 on: February 01, 2017, 06:18:26 pm »
Quote
The simplest solution is to do:
while(window.isOpen()) {
sf::Time dt = clock.restart();
// ...
pos += velocity * dt.asSeconds();
 

So would I put that function inside the ball class or? I am not sure how I would put this into the programme itself

DylanMorgan

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Moving a ball with FPS
« Reply #3 on: February 01, 2017, 06:25:00 pm »
#include "Stdafx.h"
#include "ball.h"

Ball::Ball(int startPositionY, int startPositionX)
{
        position.x = startPositionX;
        position.y = startPositionY;

        startingPosition = position;

        colour = sf::Color::White;

        ball.setRadius(radius);
        ball.setFillColor(colour);
        ball.setPosition(position);
}

Ball::~Ball()
{
}

sf::CircleShape Ball::getBall()
{
        return ball;
}

void Ball::setVelocity(int tempFrameRateX, int tempFrameRateY)
{
        frameRateX = tempFrameRateX;
        frameRateY = tempFrameRateY;
}

float Ball::getVelocityX()
{
        return xVelocity;
}

void Ball::reboundSides()
{
        xVelocity = -xVelocity;
}

void Ball::reboundSurface()
{
        position.y -= (yVelocity * frameRateY);
        yVelocity = -yVelocity;
}

void Ball::update()
{
        // Update the ball position variables
        position.y += yVelocity;
        position.x += xVelocity;

        // Move the ball
        ball.setPosition(position);
}

void Ball::hitBottom()
{
        position.x = startingPosition.x;
        position.y = startingPosition.y;
}

sf::FloatRect Ball::getPosition()
{
        return ball.getGlobalBounds();
}

I edited my ball.cpp to include the velocity and it works, however if I take off vertical sync. When the frame-rate is really high, then the ball moves really fast. It is not that constant speed no matter the fps

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Moving a ball with FPS
« Reply #4 on: February 01, 2017, 08:14:04 pm »
The important part to keep it at consistent speed is the time - multiplying any motion by the time passed. Notice in eXpl0it3r's example that the velocity was multiplied by dt (delta time - time taking since the previous frame).
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

DylanMorgan

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Moving a ball with FPS
« Reply #5 on: February 01, 2017, 08:58:41 pm »
Quote
The important part to keep it at consistent speed is the time - multiplying any motion by the time passed. Notice in eXpl0it3r's example that the velocity was multiplied by dt (delta time - time taking since the previous frame).

How do I get this dt variable?

sjaustirni

  • Jr. Member
  • **
  • Posts: 94
    • View Profile
Re: Moving a ball with FPS
« Reply #6 on: February 01, 2017, 09:31:09 pm »
The simplest solution is to do:
while(window.isOpen()) {
sf::Time dt = clock.restart();
// ...
pos += velocity * dt.asSeconds();