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

Author Topic: Can this collision code be simplified?  (Read 1348 times)

0 Members and 1 Guest are viewing this topic.

ChayHawk

  • Newbie
  • *
  • Posts: 10
    • View Profile
    • Email
Can this collision code be simplified?
« on: May 27, 2022, 01:20:15 pm »
So i have been watching tutorials on SFML and this guy made these tutorials for collision, so I followed along and he said there could be better alternatives out there so im wondering, is there better cleaner/easier to read collision code for everything under the General Collision section or is this pretty much it?

Heres the tutorials i was following:

Part 1: https://www.youtube.com/watch?v=onRDXY6WoVk
Part 2: https://www.youtube.com/watch?v=QM92txFYjLI
Part 3: https://www.youtube.com/watch?v=A04MPkBL5H4
Part 5: https://www.youtube.com/watch?v=bNXgu9_JmE4&t=653s



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

using std::cout;
using std::vector;

int main()
{
    const unsigned WINDOW_WIDTH{ 800 };
    const unsigned WINDOW_HEIGHT{ 600 };

    sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "SFML works!");
    window.setFramerateLimit(60);

    float dt;
    sf::Clock dtClock;

    const float gridSize = 50.0f;

    //Player
    const float movementSpeed = 100.f;
    sf::Vector2f velocity;
    sf::RectangleShape player;
    player.setFillColor(sf::Color::Green);
    player.setSize(sf::Vector2f(gridSize, gridSize));
    player.setPosition(sf::Vector2f(0, 0));

    //Walls
    std::vector<sf::RectangleShape> walls;

    sf::RectangleShape wall;
    wall.setFillColor(sf::Color::Red);
    wall.setSize(sf::Vector2f(gridSize, gridSize));
    wall.setPosition(gridSize * 5, gridSize * 2);

    walls.push_back(wall);

    //Collision
    sf::FloatRect nextPos;

    while (window.isOpen())
    {
        dt = dtClock.restart().asSeconds();

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

            //Prevents contents of window from being stretched
            if (event.type == sf::Event::Resized)
            {
                // update the view to the new size of the window
                sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
                window.setView(sf::View(visibleArea));
            }
        }

        //Player Movement

        velocity.x = 0.f;
        velocity.y = 0.f;

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
        {
            velocity.y += -movementSpeed * dt;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
        {
            velocity.x += -movementSpeed * dt;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
        {
            velocity.y += movementSpeed * dt;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
        {
            velocity.x += movementSpeed * dt;
        }

        //General Collision
        for (auto& wall : walls)
        {
            sf::FloatRect playerBounds = player.getGlobalBounds();
            sf::FloatRect wallBounds = wall.getGlobalBounds();

            nextPos = playerBounds;
            nextPos.left += velocity.x;
            nextPos.top += velocity.y;

            if (wallBounds.intersects(nextPos))
            {
                //Bottom Collision
                if (playerBounds.top < wallBounds.top
                    && playerBounds.top + playerBounds.height < wallBounds.top + wallBounds.height
                    && playerBounds.left < wallBounds.left + wallBounds.width
                    && playerBounds.left + playerBounds.width > wallBounds.left)
                {
                    velocity.y = 0;
                    player.setPosition(playerBounds.left, wallBounds.top - playerBounds.height);
                }

                //Top Collision
                if (playerBounds.top > wallBounds.top
                    && playerBounds.top + playerBounds.height > wallBounds.top + wallBounds.height
                    && playerBounds.left < wallBounds.left + wallBounds.width
                    && playerBounds.left + playerBounds.width > wallBounds.left)
                {
                    velocity.y = 0;
                    player.setPosition(playerBounds.left, wallBounds.top + wallBounds.height);
                }

                //Right Collision
                if (playerBounds.left < wallBounds.left
                    && playerBounds.left + playerBounds.width < wallBounds.left + wallBounds.width
                    && playerBounds.top < wallBounds.top + wallBounds.height
                    && playerBounds.top + playerBounds.height > wallBounds.top)
                {
                    velocity.x = 0;
                    player.setPosition(wallBounds.left - playerBounds.width, playerBounds.top);
                }

                //Left Collision
                if (playerBounds.left > wallBounds.left
                    && playerBounds.left + playerBounds.width > wallBounds.left + wallBounds.width
                    && playerBounds.top < wallBounds.top + wallBounds.height
                    && playerBounds.top + playerBounds.height > wallBounds.top)
                {
                    velocity.x = 0;
                    player.setPosition(wallBounds.left + wallBounds.width, playerBounds.top);
                }
            }
        }

        player.move(velocity);

        //Screen Collision

        //Left Collision
        if (player.getPosition().x < 0.0)
        {
            player.setPosition(0, player.getPosition().y);
        }

        //Top Collision
        if (player.getPosition().y < 0)
        {
            player.setPosition(player.getPosition().x, 0);
        }

        //Right Collision
        if (player.getPosition().x + player.getGlobalBounds().width > window.getSize().x)
        {
            player.setPosition(window.getSize().x - player.getGlobalBounds().width, player.getPosition().y);
        }

        //Bottom Collision
        //Right Collision
        if (player.getPosition().y + player.getGlobalBounds().height > window.getSize().y)
        {
            player.setPosition(player.getPosition().x, window.getSize().y - player.getGlobalBounds().height);
        }

        window.clear();
        window.draw(player);

        for (auto& i : walls)
        {
            window.draw(i);
        }

        window.display();

    }

    return 0;
}

kojack

  • Sr. Member
  • ****
  • Posts: 300
  • C++/C# game dev teacher.
    • View Profile
Re: Can this collision code be simplified?
« Reply #1 on: May 27, 2022, 01:47:40 pm »
One way to go would be to use an existing solution like Box2D. It will handle all of that for you. It works extremely well with SFML.
It takes a little bit more code to set up, but the entire general collision section would turn into 1 line (calling the box2d world's step function).

ChayHawk

  • Newbie
  • *
  • Posts: 10
    • View Profile
    • Email
Re: Can this collision code be simplified?
« Reply #2 on: May 27, 2022, 04:37:11 pm »
I was thinking of that, but it looks like i have to build it with cmake and thats always a pain for me. Maybe i'll get the ambition to do it one of these days as it seems like a really cool physics engine and would make my life simpler, but for right now i'll just stick to the sfml/C++ approach.

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: Can this collision code be simplified?
« Reply #3 on: May 29, 2022, 04:56:43 pm »
you may try manifold for detecting the collision, here an excellent tutorial in this topic with examples:

http://trederia.blogspot.com/2016/02/2d-physics-101-pong.html