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

Author Topic: C++ SFML, Circular Movement - Help!  (Read 43216 times)

0 Members and 1 Guest are viewing this topic.

Jycerian

  • Newbie
  • *
  • Posts: 49
  • Weakness of attitude becomes weakness of character
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #30 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;
}
 
« Last Edit: September 23, 2013, 12:15:54 pm by Jycerian »

Tigre Pablito

  • Full Member
  • ***
  • Posts: 226
    • View Profile
    • Email
Re: C++ SFML, Circular Movement - Help!
« Reply #31 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

Jycerian

  • Newbie
  • *
  • Posts: 49
  • Weakness of attitude becomes weakness of character
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #32 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....
« Last Edit: September 23, 2013, 01:16:00 pm by Jycerian »

Jycerian

  • Newbie
  • *
  • Posts: 49
  • Weakness of attitude becomes weakness of character
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #33 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

Tigre Pablito

  • Full Member
  • ***
  • Posts: 226
    • View Profile
    • Email
Re: C++ SFML, Circular Movement - Help!
« Reply #34 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)

Jycerian

  • Newbie
  • *
  • Posts: 49
  • Weakness of attitude becomes weakness of character
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #35 on: September 23, 2013, 05:50:27 pm »
Pff still getting stuck sometimes... WHY DID MAN CREATED THESE EVIL CIRCLES! so hard XD

Tigre Pablito

  • Full Member
  • ***
  • Posts: 226
    • View Profile
    • Email
Re: C++ SFML, Circular Movement - Help!
« Reply #36 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

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: C++ SFML, Circular Movement - Help!
« Reply #37 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.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

danijmn

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #38 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

Jycerian

  • Newbie
  • *
  • Posts: 49
  • Weakness of attitude becomes weakness of character
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #39 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.



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.

Jycerian

  • Newbie
  • *
  • Posts: 49
  • Weakness of attitude becomes weakness of character
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #40 on: October 01, 2013, 11:51:03 am »


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.


Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: C++ SFML, Circular Movement - Help!
« Reply #41 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.
Laurent Gomila - SFML developer

Jycerian

  • Newbie
  • *
  • Posts: 49
  • Weakness of attitude becomes weakness of character
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #42 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?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: C++ SFML, Circular Movement - Help!
« Reply #43 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.
Laurent Gomila - SFML developer

Jycerian

  • Newbie
  • *
  • Posts: 49
  • Weakness of attitude becomes weakness of character
    • View Profile
Re: C++ SFML, Circular Movement - Help!
« Reply #44 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




#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;
}
« Last Edit: October 07, 2013, 12:04:12 pm by Jycerian »

 

anything