SFML community forums

Help => General => Topic started by: Jycerian on September 18, 2013, 07:07:13 pm

Title: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 18, 2013, 07:07:13 pm
I started with creating my first real C++ SFML game based on Pong. Right now the paddles move from left to right but I would like to have them move like the picture below. How can I accomplish this?

(http://oi39.tinypic.com/2hnynbc.jpg)

Current Code:
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

int main()
{
        const int gameWidth  = 640;
        const int gameHeight = 480;

        const float paddleSpeed = 400.f;

        sf::VideoMode videoMode(gameWidth, gameHeight);
    sf::RenderWindow window(videoMode, "Pong", sf::Style::Close);

        // Loading textures
        sf::Texture bgTexture;
        sf::Texture p1Texture;
        sf::Texture p2Texture;
        sf::Texture ballTexture;

        if (!bgTexture.loadFromFile("Media/Textures/Background.png"))
                return EXIT_FAILURE;
        if (!p1Texture.loadFromFile("Media/Textures/Player1.png"))
                return EXIT_FAILURE;
        if (!p2Texture.loadFromFile("Media/Textures/Player2.png"))
                return EXIT_FAILURE;
        if (!ballTexture.loadFromFile("Media/Textures/Ball.png"))
                return EXIT_FAILURE;

        // Loading Fonts
        sf::Font font;
        if (!font.loadFromFile("Media/Fonts/Unibody 8.ttf"))
                return EXIT_FAILURE;

        // Initializing sprites
        sf::Sprite background;
        sf::Sprite player1;
        sf::Sprite player2;
        sf::Sprite ball;

        background.setTexture(bgTexture);
        player1.setTexture   (p1Texture);
        player2.setTexture   (p2Texture);
        ball.setTexture      (ballTexture);

        // Sprites origin
        background.setOrigin(0,0);
        player1.setOrigin(player1.getLocalBounds().width / 2, player1.getLocalBounds().height / 2);
        player2.setOrigin(player2.getLocalBounds().width / 2, player2.getLocalBounds().height / 2);
        ball.setOrigin   (ball.getLocalBounds().width    / 2, ball.getLocalBounds().height    / 2);

        // Sprites position
        background.setPosition(0,0);
        player1.setPosition   (gameWidth / 2, gameHeight - 30);
        player2.setPosition   (gameWidth / 2, 30);
        ball.setPosition      (gameWidth / 2, gameHeight / 2);

        sf::Clock clock;
        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                window.close();
                }

                float deltaTime = clock.restart().asSeconds();

                // Move player1 paddle (bottom)
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) &&
                   (player1.getPosition().x - player1.getLocalBounds().width / 2 > 0.f))
                {
                        player1.move(-paddleSpeed * deltaTime, 0.f);
                }

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) &&
                   (player1.getPosition().x + player1.getLocalBounds().width / 2 < gameWidth))
                {
                        player1.move(paddleSpeed * deltaTime, 0.f);
                }


                window.clear(sf::Color::Black);

                // Drawing sprites
                window.draw(background);
                window.draw(player1);
                window.draw(player2);
                window.draw(ball);

                window.display();
        }
        return EXIT_SUCCESS;
}
Title: Re: C++ SFML, Circular Movement - Help!
Post by: zsbzsb on September 18, 2013, 07:24:23 pm
Here is some tips focusing on the player's paddle. (the difference is that the computer's paddle will be flat at 270o)

First calculate the rotation of the paddle. So have a variable (float) for the position of the paddle. 90o will be where your paddle is in the middle (straight down from the center of the origin). 0o will be to the right and 180o will be to the left. Note this rotation is from the center of your playing field.

Next you need to determine which way to angle the paddle. Do something like this

//playerPositionAngle is the float that tracks the position of your paddle - 90 degrees is straight down
playerPaddle.setRotation(playerPositionAngle - 90); // change to 270 for the computer paddle
//Remember to have the player's paddle's origin in the center of the paddle

Now that we have the rotation we need to calculate the actual position of the paddle. Do something like this

//Remember if you use std::sin/cos it takes radians, not degrees
playerPaddle.setPosition(sf::Vector2f(radius * Cos(playerPositionAngle), radius * Sin(playerPositionAngle)));
 

This is the basic algorithm you will need, try to code it along the lines I have given you and then if you need more help feel free to ask  ;)

By the way, if you don't want to worry about the whole cos/sin functions and all that math, Nexus has written a beautiful library named Thor that has a nice thor::PolarVector that can take an angle and radius and calculate the X/Y position for you.

PS I really like the idea of a circular pong  :D
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 19, 2013, 04:45:16 am
you can convert degrees to radians by :

radians = degrees * PI / 180.0

and if i m not wrong, the paddle s absolute position would be, as zsbzsb said, but adding it to the center of the circle:

paddle.Position = new Vector2f( cos(angle) * radius + 320, sin(angle) * radius + 240 );

where 320,240 would be the center of the circle, from where its radius moves the paddle, ... actually, the paddle s angle is taken between the segments from the center of the circle to the center of the paddle, and from the center to the paddle s origin point

another matter:
you would have to get the angle of the ball, including when it touches the paddle, or the circunpherence:
first you should give and initial angle to the ball, por example, 60 degrees
when it bounces with any ot the 2 paddles,

ballAngle = 180 - 2 * paddleAngle - ballAngle;
while (ballAngle < 0) ballAngle += 360; 

when the ball bounces with the circunpherence:
i see the circunpherence as a great polygon, as if it had too many edges, then we would have to get the angle of that edge or segment where the ball hits, and apply the same formula (as if the edges were static paddles):

let s suppose we have the (xHit, yHit) Point of where the ball hit. That point belongs to the circunpherence.
the angle would be:

angleCirc = ASin( (yHit - 240) / radius ) + PI / 2;     // this angle is already in radians

ASin is the function that returns the angle whose sine is x. Here the only way to get the angle is getting the Sine, that is Y / radius. Adding PI /2 (that is 90 degrees) is because the edge is normal to the radius
then when the ball bounces with the circle line, the new ball angle could be:

ballAngle = 180 - 2 * angleCirc - ballAngle;      // remember angleCirc is already in radians

Perhaps you will need to detect in every loop if the ball hits weather the circle wall or a paddle. I suppose you will need the trigonometrical functions again ...
please let us know if you need more help ...
I agree with zsbzsb ... it s very nice your idea, very original ... I won t steal it, cos i m very busy with my poor Sonic ... then, when you finish the game, please post the link to it

the last thing: don t you forget the goal lines?  ;)

I hope it helps   :) ... and also hope i m not wrong, i haven t tested it ... just into my mind  ;D

Pablo
(from Bs As Argentina)

Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 19, 2013, 10:41:45 am
Oke so I got a different problem, I did read "Tigre Pablito" post but I can't get the circular collision to work. I tried mutiple things but I can't make it work, anyone knows how to fix it?

(http://oi40.tinypic.com/o5b57o.jpg)

#include <SFML/Graphics.hpp>

#define PI 3.14159265359

unsigned const int SCREEN_WIDTH  = 640;
unsigned const int SCREEN_HEIGHT = 480;

int main()
{
        sf::ContextSettings settings;
        settings.antialiasingLevel = 8;

        sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32), "Pong", sf::Style::Close, settings);
        window.setFramerateLimit(60);

        // Loading textures
        sf::Texture bgTexture;
        sf::Texture p1Texture;
        sf::Texture p2Texture;
        sf::Texture ballTexture;

        if (!bgTexture.loadFromFile("Media/Textures/Background.png"))
                return EXIT_FAILURE;
        if (!p1Texture.loadFromFile("Media/Textures/Player1.png"))
                return EXIT_FAILURE;
        if (!p2Texture.loadFromFile("Media/Textures/Player2.png"))
                return EXIT_FAILURE;
        if (!ballTexture.loadFromFile("Media/Textures/Ball.png"))
                return EXIT_FAILURE;

        // Texture smoothing
        p1Texture.setSmooth(true);
        p2Texture.setSmooth(true);
        ballTexture.setSmooth(true);

        // Loading Fonts
        sf::Font font;
        if (!font.loadFromFile("Media/Fonts/Unibody 8.ttf"))
                return EXIT_FAILURE;

        // Initializing sprites
        sf::Sprite background;
        sf::Sprite player1;
        sf::Sprite player2;
        sf::Sprite ball;

        background.setTexture(bgTexture);
        player1.setTexture   (p1Texture);
        player2.setTexture   (p2Texture);
        ball.setTexture      (ballTexture);

        // Sprites origin
        background.setOrigin(0,0);
        player1.setOrigin(player1.getLocalBounds().width / 2, player1.getLocalBounds().height / 2);
        player2.setOrigin(player2.getLocalBounds().width / 2, player2.getLocalBounds().height / 2);
        ball.setOrigin   (ball.getLocalBounds().width    / 2, ball.getLocalBounds().height    / 2);

        // Sprites position
        background.setPosition(0,0);
        player1.setPosition   (SCREEN_WIDTH / 2, SCREEN_HEIGHT - 30);
        player2.setPosition   (SCREEN_WIDTH / 2, 30);
        ball.setPosition      (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);

        // Paddle move and rotate variables
        float moveSpeed = 100.0f;
        float radius = 230.0f;
        float limit = 79.f;
        float p1Angle = 0.f;
        float p2Angle = 0.f;

        radius = radius - (player1.getLocalBounds().height / 2 + 10);

        // Creating the playfield
        sf::CircleShape circle(230);
        circle.setOrigin(circle.getLocalBounds().width / 2, circle.getLocalBounds().height / 2);
        circle.setPosition(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        circle.setFillColor(sf::Color::Red);

        // Ball variables
         float ballSpeed = 100.f;
         float ballRadius = ball.getLocalBounds().width / 2;
         float initBallAngle = 90.f;
         float ballAngle = 0.f;

         ballAngle = initBallAngle * PI / 180.f;

        sf::Clock clock;
        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                window.close();
                }

                float deltaTime = clock.restart().asSeconds();

                // Move player1 paddle (bottom)
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && !sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                        p1Angle -= moveSpeed * deltaTime;
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && !sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                        p1Angle += moveSpeed * deltaTime;

                // Player1 movement limit
                if (p1Angle < -limit) p1Angle = -limit;
                if (p1Angle >  limit) p1Angle =  limit;

                // Move and rotate player1
                player1.setPosition(SCREEN_WIDTH / 2 + sin((float)(p1Angle * PI / 180)) * radius, SCREEN_HEIGHT / 2 + cos((float)(p1Angle * PI / 180)) * radius);
                player1.setRotation(p1Angle * -1.0f);

                // Move the ball
                float factor = ballSpeed * deltaTime;
                ball.move(cos(ballAngle) * factor, sin(ballAngle) * factor);

                // Collision
                //if (not sure what to put in here to get circular collision)
                //{
                //      ballAngle = -ballAngle;
                //}
               

                window.clear(sf::Color::Black);

                // Drawing sprites
                window.draw(background);
                window.draw(circle);
                window.draw(player1);
                window.draw(player2);
                window.draw(ball);
               
                window.display();
        }
        return EXIT_SUCCESS;
}
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Ixrec on September 19, 2013, 11:12:21 am
Well, by a "circular collision" I assume you mean "how do I check if something is inside a given circle?" which is very simple: get its distance from the center of the circle, and if that distance is less than the circle's radius, then it's inside the circle.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 19, 2013, 12:51:30 pm
Yeah I have implemented some sort of collision only it is really bad haha but I am happy something is moving and bouncing and so it starts to look more like a game now. Any tips on how I can improve it?

This is my program: http://filebeam.com/acadd3b5a8b5ba3ad23ce9e7928f4728 ,so you can see how it runs. Also includes the media if you prefer to compile it yourself.

#include <SFML/Graphics.hpp>

#define PI 3.14159265359

unsigned const int SCREEN_WIDTH  = 640;
unsigned const int SCREEN_HEIGHT = 480;

int main()
{
        sf::ContextSettings settings;
        settings.antialiasingLevel = 8;

        sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32), "Pong", sf::Style::Close, settings);
        window.setFramerateLimit(60);

        // Loading textures
        sf::Texture bgTexture;
        sf::Texture p1Texture;
        sf::Texture p2Texture;
        sf::Texture ballTexture;

        if (!bgTexture.loadFromFile("Media/Textures/Background.png"))
                return EXIT_FAILURE;
        if (!p1Texture.loadFromFile("Media/Textures/Player1.png"))
                return EXIT_FAILURE;
        if (!p2Texture.loadFromFile("Media/Textures/Player2.png"))
                return EXIT_FAILURE;
        if (!ballTexture.loadFromFile("Media/Textures/Ball.png"))
                return EXIT_FAILURE;

        // Texture smoothing
        p1Texture.setSmooth(true);
        p2Texture.setSmooth(true);
        ballTexture.setSmooth(true);

        // Loading Fonts
        sf::Font font;
        if (!font.loadFromFile("Media/Fonts/Unibody 8.ttf"))
                return EXIT_FAILURE;

        // Initializing sprites
        sf::Sprite background;
        sf::Sprite player1;
        sf::Sprite player2;
        sf::Sprite ball;

        background.setTexture(bgTexture);
        player1.setTexture   (p1Texture);
        player2.setTexture   (p2Texture);
        ball.setTexture      (ballTexture);

        // Sprites origin
        background.setOrigin(0,0);
        player1.setOrigin(player1.getLocalBounds().width / 2, player1.getLocalBounds().height / 2);
        player2.setOrigin(player2.getLocalBounds().width / 2, player2.getLocalBounds().height / 2);
        ball.setOrigin   (ball.getLocalBounds().width    / 2, ball.getLocalBounds().height    / 2);

        // Sprites position
        background.setPosition(0,0);
        player1.setPosition   (SCREEN_WIDTH / 2, SCREEN_HEIGHT - 30);
        player2.setPosition   (SCREEN_WIDTH / 2, 30);
        ball.setPosition      (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);

        // Paddle move and rotate variables
        float moveSpeed = 100.0f;
        float radius    = 230.0f;
        float limit     = 79.f;
        float p1Angle   = 0.f;
        float p2Angle   = 0.f;

        radius = radius - (player1.getLocalBounds().height / 2 + 10);

        // Creating the playfield
        sf::CircleShape circle(230);
        circle.setOrigin      (circle.getLocalBounds().width / 2, circle.getLocalBounds().height / 2);
        circle.setPosition    (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        circle.setFillColor(sf::Color::Transparent);

        // Ball variables
         float ballSpeed     = 200.f;
         float ballRadius    = ball.getLocalBounds().width / 2;
         float initBallAngle = 90.f;
         float ballAngle     = 0.f;

         ballAngle = initBallAngle * PI / 180.f;

        sf::Clock clock;
        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                window.close();
                }

                float deltaTime = clock.restart().asSeconds();

                // Move player1 paddle (bottom)
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::A) && !sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                        p1Angle -= moveSpeed * deltaTime;
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::D) && !sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                        p1Angle += moveSpeed * deltaTime;

                // Player1 movement limit
                if (p1Angle < -limit) p1Angle = -limit;
                if (p1Angle >  limit) p1Angle =  limit;

                // Move and rotate player1
                player1.setPosition(SCREEN_WIDTH / 2 + sin((float)(p1Angle * PI / 180)) * radius, SCREEN_HEIGHT / 2 + cos((float)(p1Angle * PI / 180)) * radius);
                player1.setRotation(p1Angle * -1.0f);

                // Move the ball
                float factor = ballSpeed * deltaTime;
                ball.move(cos(ballAngle) * factor, sin(ballAngle) * factor);

                // Collision
                if (sqrt(pow(ball.getPosition().x - circle.getPosition().x, 2) +
                                 pow(ball.getPosition().y - circle.getPosition().y, 2)) >=
                                 circle.getRadius() - ballRadius)
                {
                        ballAngle = PI + ballAngle - (rand() % 30) * PI / 90;
                }

                // Collision player1 paddle
                if (ball.getGlobalBounds().intersects(player1.getGlobalBounds()))
                        ballAngle = PI + ballAngle - (rand() % 30) * PI / 90;

                window.clear(sf::Color::Black);

                // Drawing sprites
                window.draw(background);
                window.draw(circle);
                window.draw(player1);
                window.draw(player2);
                window.draw(ball);
               
                window.display();
        }
        return EXIT_SUCCESS;
}
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Clockwork on September 19, 2013, 03:42:52 pm
Hello!

I ran you demo and it's pretty nice!  It's a cool concept and I'm glad you were able to implement that circular movement, I did notice a couple problems though.

Firstly, when the paddle isn't at the very bottom of the circle, it's collision box (I mean where the ball can hit it) seems extended, and so even though you aren't directly underneath where the ball SHOULD go, you hit it anyway.  So you may want to look that.

Lastly, the ball bugged out on me and got stuck inside the walls at some point.

(http://i.imgur.com/7iJmTqM.png)
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 19, 2013, 04:01:48 pm
Firstly, when the paddle isn't at the very bottom of the circle, it's collision box (I mean where the ball can hit it) seems extended, and so even though you aren't directly underneath where the ball SHOULD go, you hit it anyway.  So you may want to look that.

Any tips on how I can improve it?

;) I know the bugs and that's why my collision sucks haha but it is all I can do at the moment that why I asked for help here.

It gets stuck in walls sometimes because it uses the rand option and so it sometimes rands into a certain angle that is the wrong way and then again and again and then it is stuck :P
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 19, 2013, 04:33:24 pm
I understand that by "circular collision" you mean that the ball bounces on the circunpherence
try this:  (applying the Pithagoras Theorem)

private bool DetectCircunpherenceCollision(int ballX, int ballY)
{
    int posY, posX;
    posX = ballX - 320;
    posY = Math.Sqrt( radius * radius -  posX * posX );

    if (ballY >= 240 + posY || ballY <= 240 - posY) return true;
    return false;
}

you can use this function on every loop, if it returns true, then you would have to get the new ballAngle ; the circunpherence X, Y to get the new angle will be the same than the ball,

the args to be passed should be the x, y of the ball center or origin, to get more precission
Also the function could be optimized and more exact, using the ball radius to detect when it just touch the circle line with its first point, but it would be too much difficult ... and unnecesary ... at least by now

i was forgetting, ... the ball scroll:  (let s supose it runs 5.0 px every loop)

ball.Position = new Vector2f( ball.Position.X + cos(ballAngle) * 5.0, ball.Postion.Y + sin(ballAngle) * 5.0 );

you don t have to worry for the sign of the ball scroll, depending on the angle it changes automatically

We would need -i think- a lady or a guy from SFML forum, that translates for you the code i wrote here to C++ ... i m sorry, i just use C#

let me know if this works, and if you need anything else
and if you get the game better, please update the link or repost it so we can see

Pablo

Title: Re: C++ SFML, Circular Movement - Help!
Post by: Hiura on September 19, 2013, 04:45:55 pm
Math.Sqrt( radius * radius -  posX * posX ); can crash or result in undefined behaviour (depending on the implementation) when |posX| > |radius|. Square root of negative number doesn't exist [in R].
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 19, 2013, 05:25:31 pm
you are very right, MiLord / MiLady

then we could do something like this:

private bool DetectCircunpherenceCollision(int ballX, int ballY)
{
    int posY, posX;
    posX = ballX - 320;
   
    if (posX > radius) posX = radius;           
    else if (posX < -radius) posX = -radius;
   
    posY = Math.Sqrt( radius * radius - posX * posX );    // now the arg >= 0

    if (ballY <= 240 - posY || bally >= 240 + posY) return true;
    return false;
}

I really thank you for the detail, cos the ball could overpass the circle line, that is, it won t land exactly at the border line ... i supose now it s fixed 

Title: Re: C++ SFML, Circular Movement - Help!
Post by: Hiura on September 19, 2013, 05:33:53 pm
I'm not sure I understood what you're trying to achieve – I haven't read the whole thread.. But one more advice on your code: don't use magic numbers (http://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad).

For example, I've no idea what 320 or 240 mean in this function. And so will you when you read your code in a few weeks / months.  ;)
Title: Re: C++ SFML, Circular Movement - Help!
Post by: FRex on September 19, 2013, 05:37:09 pm
Sqrt of negative number desn't cause undefined/implementation defined behaviour or crash.

Not in C#:
http://msdn.microsoft.com/library/system.math.sqrt.aspx
http://buttle.shangorilla.com/1.1/handlers/monodoc.ashx?link=M%3ASystem.Math.Sqrt%28System.Double%29

Not even in C or c++:
http://www.cplusplus.com/reference/cmath/sqrt/

http://oi40.tinypic.com/6plt1c.jpg

Not that you can do anything useful with +/-NaN except detect it with isnan and throw it away and it'll spread like a virus through any number it touches but calling sqrt with negative doesn't crash by itself.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Hiura on September 19, 2013, 05:41:08 pm
Gosh, I've got a value of only -20! :P

Thank you for the precision.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 19, 2013, 06:06:01 pm
320, 240 are the coordinates of the center of the screen, and of the circle

what i was trying is to give to Jycerian a function to detect when the ball bounces on the circunpherence, he is developing a pong game where the paddles are inside a circle ...  8)

we could write, instead of 320, screenWidth/2, and instead of 240, screenHeight/2 ... technically, you are right, again, but i don t usually do this, cos i m lazy

feel free to read all the thread, it s very interesting ...
i hope the binaries are ready soon, so we can play ...

but .... I ask again, Jycerian, shouldn t there be goal lines?
Title: Re: C++ SFML, Circular Movement - Help!
Post by: zsbzsb on September 19, 2013, 06:12:42 pm
but .... I ask again, Jycerian, shouldn t there be goal lines?

There is no "goal lines" in pong. The way you score points is when the ball gets past the opponent's paddle and there is no way to return the ball. So with a circular pong the score would happen when the ball gets outside the arc that the paddle can move in.
Title: AW: C++ SFML, Circular Movement - Help!
Post by: eXpl0it3r on September 19, 2013, 07:27:58 pm
Which will be rather interesting yo program the AI for, because it should be possible to play the ball towards yourself again, thus you can really make it the way a normal Pong AI works. :D
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 19, 2013, 07:56:52 pm
but .... I ask again, Jycerian, shouldn t there be goal lines?

Oh my idea was to create a BOOL that changes depending on what paddle last touched the ball. like:

Player1     = true;
Computer = false;

And then do like a collision/score if statement so that when the bool is true, player1 can only score points in the enemy's field and if it's true it has no effect if he hits his own field first .. then it would just bounce instead of adding points to the bot. vica versa for the computer paddle.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: zsbzsb on September 19, 2013, 07:59:04 pm
Oh my idea was to create a BOOL that changes depending on what paddle last touched the ball. like:

Player1     = true;
Computer = false;

And then do like a collision/score if statement so that when the bool is true, player1 can only score points in the enemy's field and if it's true it has no effect if he hits his own field first .. then it would just bounce instead of adding points to the bot. vica versa for the computer paddle.

That would be the idea, but instead of a bool why don't you get more expressive and use an enum?
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 19, 2013, 10:10:18 pm
private bool DetectCircunpherenceCollision(int ballX, int ballY)
{
    int posY, posX;
    posX = ballX - 320;
   
    if (posX > radius) posX = radius;           
    else if (posX < -radius) posX = -radius;
   
    posY = Math.Sqrt( radius * radius - posX * posX );    // now the arg >= 0

    if (ballY <= 240 - posY || bally >= 240 + posY) return true;
    return false;
}

Thanks!, But this also gets me stuck in the walls haha. pff so hard, this is like my second game ever haha did not expect it to be this hard :D but yeah I am learning so that is good.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 20, 2013, 03:44:30 am
Hello,
yeah, now i understand why the ball gets stuck ... (the collision test traps it, changing its angle indefinitely)
well, please try this, we ll make a little change
(i m assuming that now the ball, though it gets stuck, at least it does on the circle border line)

private bool DetectCircunpherenceCollision(ref int ballX, ref int ballY)
{
    int posX, posY;
    posX = ballX - 320;    // here 320 is screenWidth/2, or Xcenter

    if (posX > radius) posX = radius;
    else if (posX < -radius) posX = -radius;

    ballX = posX + 320;   // this fixes if the ball overpassed the X limit   
                                    // perhaps in C++ you d have to write *ballX = ... (indirection)
    posY = Math.Sqrt( radius * radius - posX * posX );

    // here 240 is screenHeight/2 or yCenter
    // the assignments prevents the ball to overpass the Y limit at the collision point
    if (ballY <= 240 - posY) { ballY = 240 - posY; return true; }
    else if (bally >= 240 + posY) { ballY = 240 + posY; return true; }
   
    return false;
}

now the function prevents the ball overpasses the border line, then i supose it shouldn t get stuck any more
Note you must pass to the function the X and Y values of the ball BY REFERENCE (or the address), in order it can change their values in the very probable case that they overpass the circle line (it occurs because the pixels you add to the ball trajectory may not match just on the circle line, but a little before or after)

then, your main loop could include:

.........
// here increase the ball x, y ... that is, it moves
for example:
ballX += cos (ballAngle) * 5.0;
ballY += sin (ballAngle) * 5.0;    suposing it runs 5 px per frame

if (DetectCircunpherenceCollision(ref ballX, ref ballY) == true)     // don t know if in C++ you use & not ref
{                                                                                             // and *var = ... to access the value
    ballAngle = AngleCirc();      // the new ball angle when it bounces on the circle line
}                                           // i wrote this function before, i don t remember how i called it
........

Let me know if it works now

And, i tried to run this program, and i couldn t, appears a letter that says the file MSVCP110.DLL is not in my system ... i downloaded the DLL file, copied it to C:\Windows\System32, reboot my PC, and it still says the DLL is not in my system, so i cant run the Pong.exe ...

Can someone help me with this?


Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 20, 2013, 01:36:05 pm
Hey guys, I am now making a couple of small programs to help me understand things better. Like one program rotates balls (like the paddle) the other program detects collision between 2 circles etc. But now I want to make a Collision/Angle program to help me understand the bouncing of walls etc. (in my original program I tried some stuff from the pong example without completely understanding it)

So how would I go about calculating the ball angle with the following picture.

(http://puu.sh/4vSOs.png)
Title: Re: C++ SFML, Circular Movement - Help!
Post by: danijmn on September 20, 2013, 02:11:30 pm
I saw this post and I immediately recalled one of my academic projects not so long ago in which I had to develop a pinball game in Java for Android.
Circular physics are a pain in the a**.

Fortunately, I managed to find a fantastic reference which explained how to handle collisions betweens different types of objects (but I still had to figure out how to make the flippers work ;D). It includes an explanation of the physics in collisions of balls within circular containers, which is precisely what you want. A fully working example is also provided as well as the source code (in Java, though).

Here is the link (scroll down to example 6a):
http://www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BouncingBalls.html (http://www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BouncingBalls.html)
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 20, 2013, 05:34:43 pm
I saw this post and I immediately recalled one of my academic projects not so long ago in which I had to develop a pinball game in Java for Android.
Circular physics are a pain in the a**.

Fortunately, I managed to find a fantastic reference which explained how to handle collisions betweens different types of objects (but I still had to figure out how to make the flippers work ;D). It includes an explanation of the physics in collisions of balls within circular containers, which is precisely what you want. A fully working example is also provided as well as the source code (in Java, though).

Here is the link (scroll down to example 6a):
http://www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BouncingBalls.html (http://www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BouncingBalls.html)

Thanks!, looks cool but there is so much code haha and I don't know any java either pff.

If anyone is bored I created this simple program that I just wanna use to get the collision and ball bounce correct. but that is the problem :p a lot of you people gave me tips and code snippets but I do not really know how to implement those so that is why I post this simple program now so instead of giving random snippets maby tell me what I need to change / add to this code:

(http://puu.sh/4vR8V.jpg)

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

const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;

int main()
{
    sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "SFML works!", sf::Style::Close);

        // Big circle
        float bigCircleRadius  = 200.f;
        float bigCircleCorners = 32.f;
        sf::CircleShape bigCircle    (bigCircleRadius, bigCircleCorners);
        bigCircle.setOrigin          (bigCircle.getLocalBounds().width / 2, bigCircle.getLocalBounds().height / 2);
        bigCircle.setPosition        (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        bigCircle.setOutlineThickness(2);
        bigCircle.setOutlineColor    (sf::Color::White);
        bigCircle.setFillColor       (sf::Color::Transparent);

        // Small circle
        float smallCircleAngle   = 0.f;
        float smallCircleRadius  = 20.f;
        float smallCircleCorners = 16.f;
        sf::CircleShape smallCircle    (smallCircleRadius, smallCircleCorners);
        smallCircle.setOrigin          (smallCircle.getLocalBounds().width / 2, smallCircle.getLocalBounds().height / 2);
        smallCircle.setPosition        (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        smallCircle.setOutlineThickness(2);
        smallCircle.setOutlineColor    (sf::Color::White);
        smallCircle.setFillColor       (sf::Color::Transparent);

        // Line representing smallCircle angle
        float lineAngle = 0.f;
        sf::RectangleShape line(sf::Vector2f(80, 1));
        line.setPosition(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
       
        // Testing variables
        float moveSpeed = 100.f;

        sf::Clock clock;
    while (window.isOpen())
    {
                float deltaTime = clock.restart().asSeconds();

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

                // Set lineAngle to smallCircleAngle
                lineAngle = smallCircleAngle;

                // Set line position to smallCircle position
                line.setPosition(smallCircle.getPosition().x, smallCircle.getPosition().y);

                // Move the smallCircle
                smallCircle.move(moveSpeed * deltaTime, 0.f);

                // Collision
                if (sqrt(pow(smallCircle.getPosition().x - bigCircle.getPosition().x, 2) +
                             pow(smallCircle.getPosition().y - bigCircle.getPosition().y, 2)) >
                                 bigCircle.getRadius() - smallCircle.getRadius())
                {
                        moveSpeed = -moveSpeed;
                        smallCircle.rotate(180);
                        line.rotate(180);
                        std::cout << "Collision!\n";
                }

        window.clear(sf::Color::Black);
                window.draw(bigCircle);
                window.draw(smallCircle);
                window.draw(line);
        window.display();
    }

    return 0;
}

The rotation of smallCircle and line is just a placeholder to test, at the moment smallCircleAngle is not used yet.

And thank guys for all the help so far. I am learning a lot!
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Ixrec on September 20, 2013, 08:50:18 pm
Quote
The rotation of smallCircle and line is just a placeholder to test, at the moment smallCircleAngle is not used yet.

Unfortunately I think that's where all the interesting parts of the collision algorithm would be, so I'm not sure I can really suggest what to add or improve to this tech demo other than the obvious: fill those parts in.

Though I guess I can point out that doing so will involve making your speed variable 2D instead of 1D, and when a collision occurs instead of simply speed = -speed you'd have to take into account the angle of impact and figure out what direction it should bounce away toward.  There's probably more steps but maybe that'll help.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 20, 2013, 08:58:20 pm
Hello, Jycerian, zsbzsb, and all Ladies and Guys from SFML

let s see, first i ll try to draw the main loop and then to detail the heavy functions, that i already wrote before
if needed, please someone translate from my code to C++, thank you (i don t know why don t you all use C# ... it s easier and more legible)
i saw you were asking in the last reply for the ball s angle when it hits the border line, here it is all

while (true)
{
    PlayerInput();     // however it is, events, etc
   
    ComputerPaddleControl()    // has it been thought or programmed?
 
    DrawGraphics();    // however it is

    BallMove();          // i ll give an idea, but perhaps it s already done

    if (DetectCircunpherenceCollision( ref ballX, ref ballY ) == true)
    {
        ballAngle = AngleCircle();
    }
    else if (DetectPaddleCollision( ballX, ballY ) == true)
    {
        ballAngle = AnglePaddle()
    }

    // it would be missing the score issue, i m sorry but i insist with the goal lines, cos the ball will never be 
    // impeded to return, as you said, zsbzsb, it will bounce once and again on different points on the circle
    // lines, even if it never hits the paddles, it can t escape from the circle

    // anyway, Jycerian, you could try first if the schema and functions i wrote make the program works fine,
    // weather there are or not goal lines
}

// returns true if the ball bounces on the circunpherence
private bool DetectCircunpherenceCollision( ref int ballX, ref int ballY )
{
// already written and optimized, see last version
}

// returns true if the ball bounces on the paddle
// convert paddleAngle to radians before passing it to the Sin or Cos
private bool DetectPaddleCollision( int ballX, int ballY )
{
    int a, SideX;
   
    Paddle.Radius = paddleTexture.Width / 2;   // however it is   
    Paddle.Height = paddleTexture.Height;       // however it is

    SideX = Math.Cos (paddleAngle) * Paddle.Radius;
    for (a = Paddle.Origin.X - SideX; a<= Paddle.Origin.X + SideX; a++)
    {
        if (Distance( Ball.Origin.X, Ball.Origin.Y, a, Math.Sin(paddleAngle) * a / Math.Cos(paddleAngle) )
            < ball.Radius + Math.Cos(paddleAngle) * Paddle.Height / 2)
            return true;
    }
    return false;
}

// returns the ball s angle (in degrees) when it bounces on the circle line
private int AngleCircle()
{
    int angle, tangentAngle;
   
    // the circunpherence s tangent line at the collision point behaves as a paddle, then we get its angle and
    // then we get the new ball s angle; we add PI/2 (90 degrees) cos the tangent is normal to the radius 
    tangentAngle = (Math.Asin( (ballY - 240) / radius ) + PI / 2) * 180 / PI;   // converted to degrees

    angle = 180 - 2 * tangentAngle - ballAngle;   // here we use the same formula than when the ball
                                                                      // bounces with the paddle
    return angle;
}

// returns the ball s angle (in degrees) when it bounces on the paddle
private int AnglePaddle()
{
    int angle;
    angle = 180 - 2 * paddleAngle - ballAngle;
    return angle;
}

// makes the ball move - i don t know if already implemented
private void BallMove()
{
    Ball.Position.X += Math.Cos(ballAngle) * 5.0;   
    Ball.Position.Y -= Math.Sin(ballAngle) * 5.0;
}

I will repeat, i couldn t run this program Jycerian that sent the link, because of the MSVCP110.DLL file ... now, could any member tell me how to fix that, so i can see the game?
i don t know about DLL s nor OS s very much ... just programming
thank you

please let us know if now, the Pong works fine now
and be carefull with the variable names, if you have any doubt tell me

Pablo
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Ixrec on September 20, 2013, 09:10:12 pm
That's a Microsoft-specific Visual Studio-related DLL.  Offhand I have no idea what visual studio settings make it a dependency, but I personally haven't had problems with my programs needing it on other people's computers (and I can run his program just fine).  Since you forgot to mention what your OS is we don't know if Jycerian introduced a strange dependency somehow or if you're simply not running Windows (in which case of course it wouldn't work).

Still, you should be able to copy and paste his code and compile it yourself.  That worked for me with his collision test just now.

@Jycerian: It's not hugely relevant to the current collision discussion, but I noticed with your original pong program that dragging the window around for several seconds causes the ball to escape the playing field and never come back (I assume it's oscillating indefinitely since it's always outside the circle).  Something to tackle once you've gotten basic bouncing that looks right.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 20, 2013, 10:02:07 pm
Thank you, MiLord!
I m using Windows 7 Ultimate 32 bit ... and i have installed Visual C# 2008 Express Edition, NOT C++
i downloaded the DLL file, tried copying it to the game s folder, to C:\Windows\System32, also i ran regsvr32 at the command shell, and it says it couldn t load the MSVCP110.DLL file ...
when i tried to run the Pong, a messagebox said the DLL wasn t installed on my system, ... but it really is!

about Jycerian s pong game, i really hope that now it will work, with the circular collision and so ... actually, i am looking for solving this DLL problem, and then waiting for the binaries to see this sophisticated game
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 21, 2013, 01:12:16 am
@Jycerian: It's not hugely relevant to the current collision discussion, but I noticed with your original pong program that dragging the window around for several seconds causes the ball to escape the playing field and never come back (I assume it's oscillating indefinitely since it's always outside the circle).  Something to tackle once you've gotten basic bouncing that looks right.

Thank you, I noticed this also I will take small steps forward so this would probably be the last issue to fix :)
 
My current goals are: Paddle Rotation (I know how to do this now) Ball Collision and Bounce (Working on this now) Enemy AI (Not yet done) Score (Not yet done) Menu (Not yet done) Fixing bugs (Not yet done)

about Jycerian s pong game, i really hope that now it will work, with the circular collision and so

I hope so too, tomorrow I will continue to play around with the collision and ball bounce. BTW: I use windows 7 64x and use visual studio 2012. with C++ and SFML 2.1

please let us know if now, the Pong works fine now
and be carefull with the variable names, if you have any doubt tell me

Pablo

I will look into your post tomorrow and play around with it, I did some C# myself with XNA but now I am learning C++ and SFML, because I want to get into the Game Industrie and C++ is standard there. But I agree that C# is easier for sure.

Again, thank you all guys for helping and I am sure this topic will be helpful to others too :D I never realized that a round game would be so much trouble haha but yeah it's my first C++ SFML game so after I get all this finished I am sure I could create more games with ease.

Also I google'd your DLL problem and found some useful stuff:

Quote
You will need to install the correct Redistributable Package (http://www.microsoft.com/en-us/download/details.aspx?id=30679) from Microsoft. Please note that you cannot just take any of those, you need to pick the one that goes with your very specific version of Visual Studio. The link for example is for VS 2012 SP1. If you have another version, you need another vcredist package.

Quote
Answer of user nvoigt seems to be correct (+1 for that). As an alternative to install Redist Package you can deploy "manually" MSVCP110.dll with your application. Easiest way is to put the dll where your exe is. But as the other people say: you need the correct version of redist pack which fits your system configuration.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 21, 2013, 03:01:21 am
I forgot to write the Distance function, i don t know why i have realized right now

// returns the distance between points P(x1, y1) and Q(x2, y2)
private int Distance(int x1, int y1, int x2, int y2)
{
    return Math.Sqrt( (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) );
}

this function is used by the one that tests the ball s bounce on the paddle

Now i ll check out about the problem with the microsoft package and the dll

if you are using VS 2012, then it s .NET 4.0 or 4.5, do i have to update that? and i guess the dll is not the same from one to another?
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 23, 2013, 11:08:49 am
Oke, so I have implemented the code that is posted here for the collision in my simplified program but it is not working correct, the ball bounce of the top part of the circle but not the bottom part. What did I do wrong? it is not working as it should haha.

EDIT: Oke I forgot some code, but the collision is really weird and for some reason if I put 0 degrees as the initial angle it has no collision, also I rotate the objects equal to their angle, for some reason when I run my program the angle indicator (line) is way off. It still gets stuck in walls sometimes.

HELP?!

DOWNLOAD: http://fbe.am/nDl

Code:

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

#define PI 3.14159265359

const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;

bool DetectCircumferenceCollision (float ballX, float ballY, float radius)
{
        float posX, posY;
        posX = ballX - SCREEN_WIDTH / 2;

        if (posX > radius)
        {
                posX = radius;
        }
        else if (posX < -radius)
        {
                posX = -radius;
        }

        ballX = posX + SCREEN_WIDTH / 2;

        posY = sqrt(radius * radius - posX * posX);

        if (ballY <= SCREEN_HEIGHT / 2 - posY)
        {
                ballY = SCREEN_HEIGHT / 2 - posY;
                return true;
        }
        else if (ballY >= SCREEN_HEIGHT / 2 + posY)
        {
                ballY = SCREEN_HEIGHT / 2 + posY;
                return true;
        }

        return false;
}

int angleCircle(float ballX, float ballY, float ballAngle, float radius)
{
        int angle, tangentAngle;

        tangentAngle = (asin((ballY - SCREEN_HEIGHT / 2) / radius) + PI / 2) / PI * 180;

        angle = 180 - 2 * tangentAngle - ballAngle;

        return angle;
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "SFML works!", sf::Style::Close);

        // Big circle
        float bigCircleRadius  = 200.f;
        float bigCircleCorners = 32.f;
        sf::CircleShape bigCircle    (bigCircleRadius, bigCircleCorners);
        bigCircle.setOrigin          (bigCircle.getLocalBounds().width / 2, bigCircle.getLocalBounds().height / 2);
        bigCircle.setPosition        (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        bigCircle.setOutlineThickness(2);
        bigCircle.setOutlineColor    (sf::Color::White);
        bigCircle.setFillColor       (sf::Color::Transparent);

        // Ball
        float ballAngle = 0.1f;
        float ballRadius  = 20.f;
        float ballCorners = 16.f;

        sf::CircleShape ball    (ballRadius, ballCorners);
        ball.setOrigin          (ball.getLocalBounds().width / 2, ball.getLocalBounds().height / 2);
        ball.setPosition        (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        ball.setOutlineThickness(2);
        ball.setOutlineColor    (sf::Color::White);
        ball.setFillColor       (sf::Color::Transparent);

        // Line representing smallCircle angle
        float lineAngle = 0.f;
        sf::RectangleShape line(sf::Vector2f(80, 1));
        line.setPosition(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);

        /*---------------------------------------------------*/

        // Ball variables
        float ballSpeed = 100.f;
        float ballX = ball.getPosition().x;
        float ballY = ball.getPosition().y;

        sf::Clock clock;
    while (window.isOpen())
    {
                float deltaTime = clock.restart().asSeconds();

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

                // Set lineAngle to BallAngle
                lineAngle = ballAngle;

                // Set line position to ball position
                line.setPosition(ballX, ballY);

                ball.setRotation(ballAngle);
                line.setRotation(lineAngle);

                // Move the ball
                ball.setPosition(ballX, ballY);
                ballX += cos(ballAngle) * (ballSpeed * deltaTime);
                ballY += sin(ballAngle) * (ballSpeed * deltaTime);

                // Collision
                if (DetectCircumferenceCollision(ballX, ballY, bigCircleRadius) == true)
                {
                        ballAngle = angleCircle(ballX, ballY, ballAngle, bigCircleRadius);
                }


                // Collision
                //if (sqrt(pow(smallCircle.getPosition().x - bigCircle.getPosition().x, 2) +
                //           pow(smallCircle.getPosition().y - bigCircle.getPosition().y, 2)) >
                //               bigCircle.getRadius() - smallCircle.getRadius())
                //{
                //      moveSpeed = -moveSpeed;
                //      smallCircle.rotate(180);
                //      line.rotate(180);
                //      std::cout << "Collision!\n";
                //}

        window.clear(sf::Color::Black);
                window.draw(bigCircle);
                window.draw(ball);
                window.draw(line);
        window.display();
    }

    return 0;
}
 
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 23, 2013, 12:32:10 pm
Good morning!

I got scared, for a few moments, but, finally I found the problem

the function angleCircle() returns its value in degrees, I recommend also you assign the initial ballAngle in degrees, let s say, 60;

then, when you pass the argument to cos() and sin() functions, you should first convert the ballAngle degrees to radians,

please write this new function

double Radians(double degrees)
{
    return (degrees * PI / 180.0);
}

and now you can correct the lines

ballX += cos(ballAngle) * ..................

by

ballX += cos(Radians(ballAngle)) * ...................

Remember that always all the trigonometrical functions return their values and take their arguments that are angles, in radians; you can use degrees so that is easier for you to read and understand your program, but need to convert when calling these functions

Good luck, I m waiting for the fixed version!

Pablo

PS: I was able to run this and the previous you sent, thank to your help with the MS package
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 23, 2013, 01:05:35 pm
Ah yeah I forgot about that, thought it was already in radians haha. Oke now I have another problem; It detects the collision but it does not bounce back (something with the angle function). I "fixed" this by putting:

ballAngle = -ballAngle;

under

ballAngle = angleCircle(ballX, ballY, ballAngle, ballRadius);
(EDIT: is the ballRadius correct or should I use the bigCircleRadius here? You just said "radius" so that is why I ask)

in the collision code in the main loop. Is this correct? I thought the angle function did that automatically?

DOWNLOAD

The one without the ballAngle = -ballAngle: http://fbe.am/nDv
The one with  ballAngle = -ballAngle          : http://fbe.am/nDw

PS: Another question is my reference way correct? see:

bool DetectCircumferenceCollision (float ballX, float ballY, float radius)
(EDIT: of it removes the & sign, float & ballX etc)

And in the main loop I call the function with:

if (DetectCircumferenceCollision(ballX, ballY, bigCircleRadius))
(EDIT: No & signs used here)
Is that correct? does it now refer to the adress of ballX and ballY or does it simple copy it?



My current code (remove the ballAngle = -ballAngle; to see what I am talking about)

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

#define PI 3.14159265359

const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;

bool DetectCircumferenceCollision ([b]float ballX, float ballY, float radius[/b])
{
        float posX, posY;
        posX = ballX - SCREEN_WIDTH / 2;

        if (posX > radius)
        {
                posX = radius;
        }
        else if (posX < -radius)
        {
                posX = -radius;
        }

        ballX = posX + SCREEN_WIDTH / 2;

        posY = sqrt(radius * radius - posX * posX);

        if (ballY <= SCREEN_HEIGHT / 2 - posY)
        {
                ballY = SCREEN_HEIGHT / 2 - posY;
                return true;
        }
        else if (ballY >= SCREEN_HEIGHT / 2 + posY)
        {
                ballY = SCREEN_HEIGHT / 2 + posY;
                return true;
        }

        return false;
}

int angleCircle(float ballX, float ballY, float ballAngle, float radius)
{
        int angle, tangentAngle;

        tangentAngle = (asin((ballY - SCREEN_HEIGHT / 2) / radius) + PI / 2) / PI * 180;

        angle = 180 - 2 * tangentAngle - ballAngle;

        return angle;
}

double radians(double degrees)
{
        return (degrees * PI / 180.0);
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "SFML works!", sf::Style::Close);

        // Big circle
        float bigCircleRadius  = 200.f;
        float bigCircleCorners = 32.f;
        sf::CircleShape bigCircle    (bigCircleRadius, bigCircleCorners);
        bigCircle.setOrigin          (bigCircle.getLocalBounds().width / 2, bigCircle.getLocalBounds().height / 2);
        bigCircle.setPosition        (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        bigCircle.setOutlineThickness(2);
        bigCircle.setOutlineColor    (sf::Color::White);
        bigCircle.setFillColor       (sf::Color::Transparent);

        // Ball
        float ballAngle = 90.f;
        float ballRadius  = 20.f;
        float ballCorners = 16.f;

        sf::CircleShape ball    (ballRadius, ballCorners);
        ball.setOrigin          (ball.getLocalBounds().width / 2, ball.getLocalBounds().height / 2);
        ball.setPosition        (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        ball.setOutlineThickness(2);
        ball.setOutlineColor    (sf::Color::White);
        ball.setFillColor       (sf::Color::Transparent);

        // Line representing smallCircle angle
        float lineAngle = 0.f;
        sf::RectangleShape line(sf::Vector2f(80, 1));
        line.setPosition(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);

        /*---------------------------------------------------*/

        // Ball variables
        float ballSpeed = 100.f;
        float ballX = ball.getPosition().x;
        float ballY = ball.getPosition().y;



        sf::Clock clock;
    while (window.isOpen())
    {
                float deltaTime = clock.restart().asSeconds();

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

                // Set lineAngle to BallAngle
                lineAngle = ballAngle;

                // Set line position to ball position
                line.setPosition(ballX, ballY);

                ball.setRotation(ballAngle);
                line.setRotation(lineAngle);

                // Move the ball
                ball.setPosition(ballX, ballY);
                ballX += cos(radians(ballAngle)) * (ballSpeed * deltaTime);
                ballY += sin(radians(ballAngle)) * (ballSpeed * deltaTime);

                // Collision
                if (DetectCircumferenceCollision([b]ballX, ballY, bigCircleRadius[/b]))
                {
                        std::cout << "Collision!\n";
                        [b]ballAngle = angleCircle(ballX, ballY, ballAngle, [u]ballRadius[/u]);
                        ballAngle = -ballAngle;[/b]
                }


                // Collision
                //if (sqrt(pow(smallCircle.getPosition().x - bigCircle.getPosition().x, 2) +
                //           pow(smallCircle.getPosition().y - bigCircle.getPosition().y, 2)) >
                //               bigCircle.getRadius() - smallCircle.getRadius())
                //{
                //      moveSpeed = -moveSpeed;
                //      smallCircle.rotate(180);
                //      line.rotate(180);
                //      std::cout << "Collision!\n";
                //}

        window.clear(sf::Color::Black);
                window.draw(bigCircle);
                window.draw(ball);
                window.draw(line);
        window.display();
    }

    return 0;
}


EDIT: oh and it still gets stuck sometimes: http://puu.sh/4yefZ.png
Is this due to my deltaTime? I heard something about fixed timestep but could not find anything for sfml and how to implement it. uhm....
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 23, 2013, 02:33:15 pm
Just tried the paddle collision code u did send me, did have no effect :) But I will go home now from school. I will check some more at home, my friend said that I should just use intersect and use paddle.GetGlobalBounds() to the intersect rotates with the object, haven't tried this yet will do this when I am at home.

Thanks again :o Looking forward to your next post.

YOLO
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 23, 2013, 03:10:02 pm
If I m not wrong, "fixed time step" means, that instead of the ball goes forward speed px and then test the circle line collision, you do something like this

for (a = 0; a < n; a++)
{
    ballX += cos(radians(ballAngle)) * speed / n;
    ballY -= sin(radians(ballAngle)) * speed / n;
   
    if (DetectCircumpherenceCollision(ballX, ballY, bigCircleRadius) == true)
    {
        ballAngle = angleCircle();
    }
}
n should be lower or equal than and an exact divisor of speed

this is, you part the number of px the ball scrolls per frame, in order that the collision detection is more exact, cos if not, supose the ball is 4 px from the border line, and you increase its trayectory in 8 px, what happens? the ball overpasses the circle line, and there are problems ...
with this trick, that aparently they called "fixed time step", it is like if the ball gave shorter steps, and it can bounce before ending the last of those shorter steps, in which case it scrolls the pending steps after having bounced and changed its angle, but in opposite way
that is, the collision will be tested n times instead o 1, along the distance the ball scrolls per frame, that will avoid that it overpasses the circle border line
(greater n, greater precission, in the most exact case, the shorter step's module is 1, that is n = speed)

what I called Radius, is the big circle radius, then I call ballRadius to the ball radius, but in the paddle collision function ...

About the reference signus, I'm not sure how it is in VS C++.NET, but in the ancient C/C++ it was:
(for example)
void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;       // indirection operator *, access the value
    *b = temp;
}

and you called the function

swap(&a, &b);   // passing the address with the reference operator &

But I think now, using the fixed timestep, it won't be necesary to use pointers in the fuction's args (that is used to modify the values referred by them)

Keep us alert of your game's progress, and tell me if you need something else
 :) ;) :D ;D 8)
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 23, 2013, 05:50:27 pm
Pff still getting stuck sometimes... WHY DID MAN CREATED THESE EVIL CIRCLES! so hard XD
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tigre Pablito on September 23, 2013, 07:20:20 pm
Did you do what I suggested? Please send the new fixed code, so I can see
It shouldn't fail ...

I'll try here again the main loop

let s supose speed = 40;

while (window.IsOpen())
{
    // FRAME THE GRAPHICS
    DrawGraphics();   // whatever it is

    // THE BALL MOVES AND BOUNCES
    for (int a = 0; a < 20; a++)
    {
        ballX += cos(radians(ballAngle)) * 2;
        ballY -= sin(radians(ballAngle)) * 2;

        if (DetectCircumpherenceCollision(ballX, ballY, bigCircleRadius))
            ballAngle = angleCirc(ballX, ballY, ballAngle, bigCircleRadius);
    }   

    // HERE speed = 40, n = 20, THEN speed / n = 2, as seen in the for() LOOP
    // THE GREATER n, BETTER, BUT NOT > speed

    // TIME RETARD
    //
}

Try this, and post the code so I can see
And don't worry, the program will work
Meanwhile I'll check out the paddle collision issue
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Nexus on September 23, 2013, 07:30:28 pm
Please use the [code=cpp] [/code] tags to format your code. It's the drop-down field on the very right.

Use the "modify" function to edit your post.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: danijmn on September 23, 2013, 09:58:35 pm
Balls getting stuck is a typical problem in this kind of game. Basically you have to make sure that the ball is headed towards a certain object before trying to calculate a collision against it. If the ball is not even headed against the object you can simply ignore the rest of the computation.

So, if the ball's velocity vector and the normal of the surface are less than 90 degress apart, there can be no collision (beware, there are two normals for a line segment in 2D, you need the one pointing "inside" the circular world, but I suppose you already figured that out). This is a fairly simple check.

To do it, you need to find the cosine of the angle between the two vectors (ball velocity and surface normal) and if it is equal to or more than zero (angle is between -90 and 90 deg) there can be no collision. You can compute this using the dot product. Here's an explanation for 3D vectors: http://www.wikihow.com/Find-the-Angle-Between-Two-Vectors (http://www.wikihow.com/Find-the-Angle-Between-Two-Vectors)
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on September 23, 2013, 10:17:30 pm
COLLISION FIXED

Oke so a couple of days a go I met a guy on this forum (PM) and we have been talking on Skype about this all the time, he could't really figure it out either. That's when I posted back here. He had a billiard test application (bouncing balls) he managed to adjust that code and implement it for my needs =D (Circle Container with a Circle inside) and it works really good :o He did not use angles etc.

(http://puu.sh/4yygc.png)

DOWNLOAD: http://fbe.am/nE9

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

unsigned int SCREEN_WIDTH = 640;
unsigned int SCREEN_HEIGHT = 480;

void collision(sf::CircleShape& ball, sf::CircleShape& circle, sf::Vector2f& direction);

int main()
{
        sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32), "Circles :S", sf::Style::Close);
        window.setFramerateLimit(60);

        sf::Clock clock;
        sf::Event windowEvent;
        float elapsedTime = 0.0f;

        sf::CircleShape circle(200.0f);
        circle.setOutlineThickness(2.0f);
        circle.setOutlineColor(sf::Color::White);
        circle.setFillColor(sf::Color::Transparent);
        circle.setPosition(SCREEN_WIDTH/2.0f, SCREEN_HEIGHT/2.0f);
        circle.setOrigin(circle.getGlobalBounds().width/2, circle.getGlobalBounds().height/2);

        sf::CircleShape ball = circle;
        ball.setRadius(20.0f);
        ball.setPosition(SCREEN_WIDTH/2.0f, SCREEN_HEIGHT/2.0f + 20.0f);
        ball.setOrigin(ball.getGlobalBounds().width/2, ball.getGlobalBounds().height/2);

        sf::Vector2f direction(1.0f, 0.0f);
        float ballSpeed = 200.0f;

        while(window.isOpen())
        {
                while(window.pollEvent(windowEvent))
                {
                        if(windowEvent.type == sf::Event::Closed)
                                window.close();
                }

                window.clear(sf::Color());

                ball.move(direction * ballSpeed * elapsedTime);

                if((ball.getRadius() + sqrt(pow(circle.getPosition().x - ball.getPosition().x, 2.0f) + pow(circle.getPosition().y - ball.getPosition().y, 2.0f)) > circle.getRadius()))
                {
                        ball.move(-direction * ballSpeed * elapsedTime);
                        collision(ball, circle, direction);
                }

                window.draw(circle);
                window.draw(ball);

                elapsedTime = clock.restart().asSeconds();
                window.display();
        }

        return EXIT_SUCCESS;
}

void collision(sf::CircleShape& ball, sf::CircleShape& circle, sf::Vector2f& direction)
{
        float sz, st, sv1, xt1, yt1, xz1, yz1;
        sz = st = sv1 = xt1  = yt1 = xz1 = yz1 = 0.0f;

        sv1 = direction.y / direction.x;
        sz = ((circle.getPosition().y - ball.getPosition().y) / (circle.getPosition().x - ball.getPosition().x));

        if(sz != 0)
        {
                st = -1.0f / sz;

                xt1 = direction.x * (sz - sv1) / (sz - st);
                xz1 = direction.x * (st - sv1) / (st - sz);
                yt1 = xt1 * st;
                yz1 = xz1 * sz;

                sf::Vector2f t1(xt1, yt1);
                sf::Vector2f z1(xz1, yz1);

                direction = (t1 - z1);
        }
        else
        {
                direction.x *= -1.0f;
                direction.y *= -1.0f;
        }
}

Do not hesitate to drop your thoughts down here and let me know what you think about this piece of code. It does not get stuck in walls etc.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on October 01, 2013, 11:51:03 am
(http://puu.sh/4ENmd.png)

How do I fix the rectangular collision when it rotates? above I display the collision box. or should I use pixel-collision?  The rectangle represents the paddle and the ball obviously the ball.

Title: Re: C++ SFML, Circular Movement - Help!
Post by: Laurent on October 01, 2013, 12:03:36 pm
You must use an oriented bounding rectangle. SFML only provides support for axis-aligned rectangles, so you'll have to create your own data structure and find the corresponding collision algorithms.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on October 01, 2013, 01:16:50 pm
You must use an oriented bounding rectangle. SFML only provides support for axis-aligned rectangles, so you'll have to create your own data structure and find the corresponding collision algorithms.

https://github.com/SFML/SFML/wiki/Source%3A-Simple-Collision-Detection

I guess that is what I should be looking at to accomplish this?
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Laurent on October 01, 2013, 01:26:08 pm
Yes, OBB collision is what you need. Maybe it could be simpler, since the second shape to test is a circle.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on October 07, 2013, 11:07:25 am
I got rectangle to rectangle /w rotation working. But how do I make it work with circle to rectangle /w rotation collision? Any idea's?

DOWNLOAD: http://fbe.am/nVZ

(http://puu.sh/4JRtd.png)
(http://puu.sh/4JRsA.png)

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

#ifndef PI
    #define PI (3.14159265358979323846)
#endif
#define RADIANS_PER_DEGREE (PI/180.0)

const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;

sf::Vector2f RotatePoint(const sf::Vector2f& Point, float Angle);
bool BoundingBoxTest(const sf::Sprite& Object1, const sf::Sprite& Object2);
int main()
{
    sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "Rectangle to Rectangle Collision", sf::Style::Close);

        int screenCenterX = SCREEN_WIDTH  / 2;
        int screenCenterY = SCREEN_HEIGHT / 2;

        sf::Sprite rect1;
        rect1.setOrigin(rect1.getGlobalBounds().width / 2, rect1.getGlobalBounds().height / 2);
        rect1.setPosition(screenCenterX, screenCenterY);
        rect1.setRotation(0);

        sf::Sprite rect2;
        rect2.setOrigin(rect2.getGlobalBounds().width / 2, rect2.getGlobalBounds().height / 2);
        rect2.setPosition(screenCenterX, screenCenterY + 100);
        rect2.setRotation(45);

        sf::Texture texture1;
        sf::Texture texture2;
        sf::Texture texture3;

        if (!texture1.loadFromFile("Media/Textures/Red.jpg", sf::IntRect(0, 0, 80, 25)))
        {
                return EXIT_FAILURE;
        }

        if (!texture2.loadFromFile("Media/Textures/Blue.jpg", sf::IntRect(0, 0, 80, 25)))
        {
                return EXIT_FAILURE;
        }

        if (!texture3.loadFromFile("Media/Textures/Green.jpg", sf::IntRect(0, 0, 80, 25)))
        {
                return EXIT_FAILURE;
        }

        rect1.setTexture(texture1);
        rect2.setTexture(texture2);

        float moveSpeed = 100.f;

        sf::Clock clock;
    while (window.isOpen())
    {
                float deltaTime = clock.restart().asSeconds();

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::A) && !sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                        rect1.move(-moveSpeed * deltaTime, 0);
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::D) && !sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                        rect1.move(moveSpeed * deltaTime, 0);
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::W) && !sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                        rect1.move(0, -moveSpeed * deltaTime);
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::S) && !sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                        rect1.move(0, moveSpeed * deltaTime);

                if (BoundingBoxTest(rect1, rect2))
                {
                        std::cout << "Collision.\n";
                        rect1.setTexture(texture3);
                }
                else
                        rect1.setTexture(texture1);

        window.clear(sf::Color::Black);
                window.draw(rect1);
                window.draw(rect2);
        window.display();
    }

    return 0;
}

class OrientedBoundingBox // Used in the BoundingBoxTest
        {
        public:
                OrientedBoundingBox (const sf::Sprite& Object) // Calculate the four points of the OBB from a transformed (scaled, rotated...) sprite
                {
                        sf::Transform trans = Object.getTransform();
                        sf::IntRect local = Object.getTextureRect();
                        Points[0] = trans.transformPoint(0.f, 0.f);
                        Points[1] = trans.transformPoint(local.width, 0.f);
                        Points[2] = trans.transformPoint(local.width, local.height);
                        Points[3] = trans.transformPoint(0.f, local.height);
                }

                sf::Vector2f Points[4];

                void ProjectOntoAxis (const sf::Vector2f& Axis, float& Min, float& Max) // Project all four points of the OBB onto the given axis and return the dotproducts of the two outermost points
                {
                        Min = (Points[0].x*Axis.x+Points[0].y*Axis.y);
                        Max = Min;
                        for (int j = 1; j<4; j++)
                        {
                                float Projection = (Points[j].x*Axis.x+Points[j].y*Axis.y);

                                if (Projection<Min)
                                        Min=Projection;
                                if (Projection>Max)
                                        Max=Projection;
                        }
                }
        };

bool BoundingBoxTest(const sf::Sprite& Object1, const sf::Sprite& Object2) {
        OrientedBoundingBox OBB1 (Object1);
        OrientedBoundingBox OBB2 (Object2);

        // Create the four distinct axes that are perpendicular to the edges of the two rectangles
        sf::Vector2f Axes[4] = {
                sf::Vector2f (OBB1.Points[1].x-OBB1.Points[0].x,
                OBB1.Points[1].y-OBB1.Points[0].y),
                sf::Vector2f (OBB1.Points[1].x-OBB1.Points[2].x,
                OBB1.Points[1].y-OBB1.Points[2].y),
                sf::Vector2f (OBB2.Points[0].x-OBB2.Points[3].x,
                OBB2.Points[0].y-OBB2.Points[3].y),
                sf::Vector2f (OBB2.Points[0].x-OBB2.Points[1].x,
                OBB2.Points[0].y-OBB2.Points[1].y)
        };

        for (int i = 0; i<4; i++) // For each axis...
        {
                float MinOBB1, MaxOBB1, MinOBB2, MaxOBB2;

                // ... project the points of both OBBs onto the axis ...
                OBB1.ProjectOntoAxis(Axes[i], MinOBB1, MaxOBB1);
                OBB2.ProjectOntoAxis(Axes[i], MinOBB2, MaxOBB2);

                // ... and check whether the outermost projected points of both OBBs overlap.
                // If this is not the case, the Seperating Axis Theorem states that there can be no collision between the rectangles
                if (!((MinOBB2<=MaxOBB1)&&(MaxOBB2>=MinOBB1)))
                        return false;
        }
        return true;
}
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on October 08, 2013, 11:41:33 am
Anyone?
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Ixrec on October 08, 2013, 12:34:17 pm
Maybe get the bounding box of the circle and set it to the same rotation as the rectangle? Then the side of the circle bounding box would be parallel with the nearest rectangle side, and regular rectangle to rectangle algorithms can then be used...I think.

Never done circle to rectangle myself so that's just a guess.  Obviously this won't extend to ellipses.
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Tobberoth on October 08, 2013, 06:52:24 pm
SAT can handle circles, though it's a bit harder than rectangles. It's covered here, though there are unfortunately no implementation details included:

http://www.metanetsoftware.com/technique/tutorialA.html#section3
Title: Re: C++ SFML, Circular Movement - Help!
Post by: Jycerian on October 08, 2013, 07:06:33 pm
SAT can handle circles, though it's a bit harder than rectangles. It's covered here, though there are unfortunately no implementation details included:

http://www.metanetsoftware.com/technique/tutorialA.html#section3

Yeah I have seen that already, found some stuff about OBB and AABB etc. I shall  read up upon it soon.
http://gamedev.tutsplus.com/tutorials/implementation/create-custom-2d-physics-engine-aabb-circle-impulse-resolution/
Title: Re: C++ SFML, Circular Movement - Help!
Post by: zsbzsb on November 01, 2013, 08:57:42 pm
I know you are having trouble your collision (and I really like the idea of circular pong). Anyways I wrote a simple version of pong that does what you are trying to achieve. If you want, you can see my version of it [full source code] here (http://en.sfml-dev.org/forums/index.php?topic=13435).