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

Author Topic: Shapes are moving simultaneously instead of separately  (Read 1653 times)

0 Members and 2 Guests are viewing this topic.

nktsrbrkv

  • Newbie
  • *
  • Posts: 5
    • View Profile
Shapes are moving simultaneously instead of separately
« on: May 10, 2024, 03:16:44 pm »
Hello everyone!

I need my shapes to move completely independently and include collision detection. When I had only one shape, everything was okay, but when I added one more, it began behaving strangely. For some unknown reason to me, my shapes move together; it seems like they are sharing some data. I was trying to figure out what is wrong on my own, but it seems like I am stuck. If it is possible, try to give me a hint instead of a solution. Many thanks in advance.

main.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include <cmath> // fabs
#include <vector>

int main()
{
        sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Works!");

        sf::CircleShape* circle = new sf::CircleShape(100.f);
        circle->setFillColor(sf::Color::Green);
        circle->move(400.f, 0.f);

        sf::RectangleShape* rect = new sf::RectangleShape(sf::Vector2f(100, 200));
        rect->setFillColor(sf::Color::Yellow);
        rect->move(200.f, 150.f);

        std::vector<sf::Shape*> shapes;
        shapes.push_back(circle);
        shapes.push_back(rect);

        float xOffset = 0.5f;
        float yOffset = 0.5f;

        float topRightX = 0.f;
        float bottomRightY = 0.f;
        float topLeftX = 0.f;
        float topLeftY = 0.f;

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

                window.clear();

                for (auto& shape : shapes)
                {
                        if (shape)
                        {
                                if (dynamic_cast<sf::CircleShape*>(shape))
                                {
                                        sf::FloatRect boundRect = shape->getGlobalBounds();

                                        topLeftX = boundRect.getPosition().x;
                                        topLeftY = boundRect.getPosition().y;

                                        auto circle = dynamic_cast<sf::CircleShape*>(shape);
                                        topRightX = boundRect.getPosition().x + circle->getRadius() * 2.f;
                                        bottomRightY = boundRect.getPosition().y + circle->getRadius() * 2.f;
                                }
                                else if (dynamic_cast<sf::RectangleShape*>(shape))
                                {
                                        sf::FloatRect boundRect = shape->getGlobalBounds();

                                        topLeftX = boundRect.getPosition().x;
                                        topLeftY = boundRect.getPosition().y;

                                        auto rectangle = dynamic_cast<sf::RectangleShape*>(shape);
                                        topRightX = boundRect.getPosition().x + rect->getSize().x;
                                        bottomRightY = boundRect.getPosition().y + rect->getSize().y;
                                }

                                if (topRightX >= window.getSize().x - 1.f)
                                        xOffset *= -1.f;
                                else if (bottomRightY >= window.getSize().y - 1.f)
                                        yOffset *= -1.f;
                                else if (topLeftX <= 0.f)
                                        xOffset = fabs(xOffset);
                                else if (topLeftY <= 0.f)
                                        yOffset = fabs(yOffset);

                                sf::Vector2f curPos = shape->getPosition();
                                shape->setPosition(curPos.x + xOffset, curPos.y + yOffset);

                                window.draw(*shape);
                        }
                }

                window.display();
        }

        return 0;
}

Please find in attachments how it works now.
« Last Edit: May 10, 2024, 03:19:47 pm by nktsrbrkv »

kojack

  • Sr. Member
  • ****
  • Posts: 343
  • C++/C# game dev teacher.
    • View Profile
Re: Shapes are moving simultaneously instead of separately
« Reply #1 on: May 10, 2024, 08:01:31 pm »
The same xOffset and yOffset are used by all shapes to move. When one shape reaches the edge it changes the direction, so all shapes change direction since they share the offsets.

You'll need to keep separate xOffset and yOffset for each shape, such as with an std::vector<sf::Vector2f>

nktsrbrkv

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Shapes are moving simultaneously instead of separately
« Reply #2 on: May 10, 2024, 08:46:46 pm »
Many thanks! I adjusted my code according to your advice, and it works as I want: