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

Author Topic: Arkanoid game - move a ball  (Read 4134 times)

0 Members and 2 Guests are viewing this topic.

mar

  • Newbie
  • *
  • Posts: 5
    • View Profile
Arkanoid game - move a ball
« on: June 01, 2017, 06:01:07 am »
Hello,

I tried to write a little program of arkanoid and there is a problem. when  I try to move the ball after it bounce in the left wall or in the right wall the ball got stuck.  I did'nt know what is the problem.

// Move the ball
                        float factor = ballSpeed * deltaTime;
                        ball.move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor);
                        // Check collisions between the ball and the screen
                        if (ball.getPosition().x - ballRadius < 0.f)
                        {
                                ballAngle = -ballAngle;
                                ball.setPosition(ballRadius + 0.1f, ball.getPosition().y);

                        }
                        else if (ball.getPosition().x + ballRadius > gameWidth)
                        {
                                ballAngle = -ballAngle;
                                ball.setPosition(gameWidth - ballRadius - 0.1f, ball.getPosition().y);
                        }

                        // up
                        if (ball.getPosition().y - ballRadius < 0.f)
                        {
                                ballAngle = -ballAngle;
                                ball.setPosition(ball.getPosition().x, ballRadius + 0.1f);
                        }

                        // down
                        else if (ball.getPosition().y + ballRadius > gameHeight)
                        {
                                ballAngle = -ballAngle;
                                ball.setPosition(ball.getPosition().x, gameHeight - ballRadius - 0.1f);
                        }

Thank you

 

Carlos Augusto Br Cpp

  • Newbie
  • *
  • Posts: 40
  • Programming is life
    • View Profile
    • Email
Re: Arkanoid game - move a ball
« Reply #1 on: June 01, 2017, 07:17:02 am »
I recommend to you put the setPosition function on the game loop and when you check the collision you could just play with the values (x, y), so you will not need so many setPosition functions for each collision check...

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11037
    • View Profile
    • development blog
    • Email
Re: Arkanoid game - move a ball
« Reply #2 on: June 01, 2017, 10:55:29 am »
Please post in the correct subforum next time. This has nothing to do with the wiki. ;)

Start your debugger or place some std::cout to trck the values to figure out why it gets stuck.

I can't directly see anything wrong with your code.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Elias Daler

  • Hero Member
  • *****
  • Posts: 599
    • View Profile
    • Blog
    • Email
Re: Arkanoid game - move a ball
« Reply #3 on: June 01, 2017, 02:17:47 pm »
I recommend to you put the setPosition function on the game loop and when you check the collision you could just play with the values (x, y), so you will not need so many setPosition functions for each collision check...
setPosition is very fast, no need to over-optimize it.

As for original problem. Your problem is that you're using the code which will only deflect the ball by X axis, not Y axis. That's because your angle is stored in radians and formulas for inverting the angle along the Y axis are different and can be seen here.

But, I think that it's much easier to just store velocity as Vector2f and invert needed axis to be explicit... For example:
if(/*collided with left or right wall*/) {
    v.x = -v.x;
}

if(/*collided with up or down wall*/) {
    v.y = -v.y;
}

ball.move(v * dt.asSeconds());
Tomb Painter, Re:creation dev (abandoned, doing other things) | edw.is | @EliasDaler

Carlos Augusto Br Cpp

  • Newbie
  • *
  • Posts: 40
  • Programming is life
    • View Profile
    • Email
Re: Arkanoid game - move a ball
« Reply #4 on: June 01, 2017, 05:04:14 pm »
@EliasDaler you are right... and that is was exactly what I was trying to say it... putting one setPosition fuction in every collision check is no necessary... and move fuction work as well, since its code behind is a setPosition fuction getting the actual position of each axis and adding with a offset of our choice, doing the move... have a nice day  :)

mar

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Arkanoid game - move a ball
« Reply #5 on: June 01, 2017, 08:31:54 pm »
Thank you very much,
I am new in SFML, I tried to do the ideas you suggested and I was not so successful. My program is based on the pong program that comes with the installation of SFML.
I would be very happy if you could direct me how to combine the ideas you have suggested in my program.
Thank you :)

The program:
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <cmath>
#include <ctime>
#include <cstdlib>

int main()
{
        std::srand(static_cast<unsigned int>(std::time(NULL)));

        // Define some constants
        const float pi = 3.14159f;
        const int gameWidth = 800;
        const int gameHeight = 600;
        sf::Vector2f paddleSize(100, 25);
        float ballRadius = 10.f;

        // Create the window of the application
        sf::RenderWindow window(sf::VideoMode(gameWidth, gameHeight, 32), "SFML Pong",
                sf::Style::Titlebar | sf::Style::Close);
        window.setVerticalSyncEnabled(true);

        // Create the left paddle
        sf::RectangleShape paddle;
        paddle.setSize(paddleSize);
        paddle.setOutlineThickness(3);
        paddle.setOutlineColor(sf::Color::Black);
        paddle.setFillColor(sf::Color(100, 100, 200));
        paddle.setOrigin(paddleSize / 2.f);

        // Create the ball
        sf::CircleShape ball;
        ball.setRadius(ballRadius);
        ball.setOutlineThickness(3);
        ball.setOutlineColor(sf::Color::Black);
        ball.setFillColor(sf::Color::White);
        ball.setOrigin(ballRadius / 2, ballRadius / 2);

        // Define the paddles properties
        sf::Clock AITimer;
        const sf::Time AITime = sf::seconds(0.1f);
        const float paddleSpeed = 400.f;
        const float ballSpeed = 400.f;
        float ballAngle = 0.f; // to be changed later

        sf::Clock clock;
        bool isPlaying = false;
        while (window.isOpen())
        {
                // Handle events
                sf::Event event;
                while (window.pollEvent(event))
                {
                        // Window closed or escape key pressed: exit
                        if ((event.type == sf::Event::Closed) ||
                                ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
                        {
                                window.close();
                                break;
                        }

                        // Space key pressed: play
                        if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space))
                        {
                                if (!isPlaying)
                                {
                                        // (re)start the game
                                        isPlaying = true;
                                        clock.restart();

                                        // Reset the position of the paddles and ball
                                        paddle.setPosition(gameWidth / 2, gameHeight - paddleSize.y / 2 - 10);
                                        ball.setPosition(gameWidth / 2, gameHeight - paddleSize.y / 2 - 40);

                                        // Reset the ball angle
                                        do
                                        {
                                                // Make sure the ball initial angle is not too much vertical
                                                ballAngle = (std::rand() % 360) * 2 * pi / 360;
                                        } while (std::abs(std::cos(ballAngle)) < 0.7f);
                                }
                        }
                }
                if (isPlaying)
                {
                        float deltaTime = clock.restart().asSeconds();

                        // Move the player's paddle
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) &&
                                (paddle.getPosition().x - paddleSize.x / 2 > 15.f))
                        {
                                paddle.move(-paddleSpeed * deltaTime, 0.f);
                        }
                        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) &&
                                (paddle.getPosition().x + paddleSize.x / 2 < gameWidth - 15.f))
                        {
                                paddle.move(paddleSpeed * deltaTime, 0.f);
                        }

                        // Move the ball
                        float factor = ballSpeed * deltaTime;
                        ball.move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor);
                        // Check collisions between the ball and the screen
                        if (ball.getPosition().x - ballRadius < 0.f)
                        {
                                ballAngle = -ballAngle;
                                ball.setPosition(ballRadius + 0.1f, ball.getPosition().y);

                        }
                        else if (ball.getPosition().x + ballRadius > gameWidth)
                        {
                                ballAngle = -ballAngle;
                                ball.setPosition(gameWidth - ballRadius - 0.1f, ball.getPosition().y);
                        }

                        // up
                        if (ball.getPosition().y - ballRadius < 0.f)
                        {
                                ballAngle = -ballAngle;
                                ball.setPosition(ball.getPosition().x, ballRadius + 0.1f);
                        }

                        // down
                        else if (ball.getPosition().y + ballRadius > gameHeight)
                        {
                                ballAngle = -ballAngle;
                                ball.setPosition(ball.getPosition().x, gameHeight - ballRadius - 0.1f);
                        }


                        // Check the collisions between the ball and the paddles
                        // Left Paddle
                        if (ball.getPosition().x - ballRadius < paddle.getPosition().x + paddleSize.x / 2 &&
                                ball.getPosition().x - ballRadius > paddle.getPosition().x &&
                                ball.getPosition().y + ballRadius >= paddle.getPosition().y - paddleSize.y / 2 &&
                                ball.getPosition().y - ballRadius <= paddle.getPosition().y + paddleSize.y / 2)
                        {
                                if (ball.getPosition().y > paddle.getPosition().y)
                                        ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180;
                                else
                                        ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180;

                                ball.setPosition(paddle.getPosition().x + ballRadius + paddleSize.x / 2 + 0.1f, ball.getPosition().y);
                        }
                }

                // Clear the window
                window.clear(sf::Color(50, 200, 50));

                if (isPlaying)
                {
                        // Draw the paddles and the ball
                        window.draw(paddle);
                        window.draw(ball);
                }

                // Display things on screen
                window.display();
        }

        return EXIT_SUCCESS;
}

 
« Last Edit: June 01, 2017, 08:34:00 pm by mar »

Carlos Augusto Br Cpp

  • Newbie
  • *
  • Posts: 40
  • Programming is life
    • View Profile
    • Email
Re: Arkanoid game - move a ball
« Reply #6 on: June 03, 2017, 09:22:06 pm »
Sorry for dont reply quickly... btw... I have removed the paddle to focus on ball movement... so now its working... so you can check and study the code and put the paddle...

there goes:
#include <SFML/Graphics.hpp>
#include <random>
#include <functional>
#include <cstdlib>
#include <cmath>

int main(int argc, char* argv[])
{
    const int window_width = 800;
    const int window_height = 600;
    const float ball_radius = 16.f;

    sf::RenderWindow window(sf::VideoMode(window_width, window_height), "SFML Pong");
    window.setVerticalSyncEnabled(true);

    std::random_device seed_device;
    std::default_random_engine engine(seed_device());
    std::uniform_int_distribution<int> distribution(-16, 16);
    auto random = std::bind(distribution, std::ref(engine));

    sf::Vector2f direction(random(), random());
    const float velocity = 15;

    sf::CircleShape ball(ball_radius - 4);
    ball.setOutlineThickness(4);
    ball.setOutlineColor(sf::Color::Black);
    ball.setFillColor(sf::Color::White);
    ball.setOrigin(ball.getRadius(), ball.getRadius());
    ball.setPosition(window_width / 2, window_height / 2);

    sf::Clock clock;
    sf::Time elapsed = clock.restart();
    const sf::Time update_ms = sf::seconds(1.f / 30.f);
   
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if ((event.type == sf::Event::Closed) || ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
           {
                window.close();
                break;
            }
        }

        elapsed += clock.restart();

        while (elapsed >= update_ms)
        {
            const auto pos = ball.getPosition();
            const auto delta = update_ms.asSeconds() * velocity;
            sf::Vector2f ball_pos(pos.x + direction.x * delta * 2, pos.y + direction.y * delta * 2);

            if (new_pos.x - ball_radius < 0)
            { // left window edge
                direction.x *= -1;
                ball_pos.x = 0 + ball_radius;
            }
            else if (new_pos.x + ball_radius >= window_width)
            { // right window edge
                direction.x *= -1;
                ball_pos.x = window_width - ball_radius;
            }
           
            else if (new_pos.y - ball_radius < 0)
            { // top of window
                direction.y *= -1;
                ball_pos.y = 0 + ball_radius;
            }
   
            else if (new_pos.y + ball_radius >= window_height)
            { // bottom of window
                direction.y *= -1;
                ball_pos.y = window_height - ball_radius;
            }
           
            ball.setPosition(ball_pos);

            elapsed -= update_ms;
        }

        window.clear(sf::Color(50, 200, 50));
        window.draw(ball);
        window.display();
    }

    return EXIT_SUCCESS;
}
 

mar

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Arkanoid game - move a ball
« Reply #7 on: June 04, 2017, 10:33:22 pm »
Thank you,
You are very help me and I put also the paddle.

Carlos Augusto Br Cpp

  • Newbie
  • *
  • Posts: 40
  • Programming is life
    • View Profile
    • Email
Re: Arkanoid game - move a ball
« Reply #8 on: June 05, 2017, 09:33:10 am »
You are welcome... good to know that it helps  :)

 

anything