Welcome to Code Forum!

Join a community that supports you and your coding journey from day one. We strive to be a friendly, supportive community that empowers everyone to be better developers. By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
  • Tutorials listed in this section have not been reviewed nor are affliated by Code Forum. It is the sole responsbility of the authour to properly maintain and ensure information is accurate.

Unmaintained Introduction to coding - 7. Handling the collisions

Handling the collisions​

Currently, collisions are not tested. The player can walk over the trees and stones. Let us resolve that.

Testing the collision between two sprites​

The class sf::FloatRect is almost the same as sf::IntRect. The only difference is that its members (Representing its position and size) are of type 'float' rather than 'int'.

The method 'getGlobalBounds' of the class sf::Sprite returns an object of type sf::FloatRect representing its boundaries.

The class sf::FloatRect has a method called 'intersects' that returns 'true' if it is in collision with the sf::FloatRect object it received in argument and 'false' otherwise.

Let us define two sprites:
C++:
sf::Sprite s1, s2;
The following code tests if the two sprites are in collision:
C++:
if(s1.getGlobalBounds().intersects(s2.getGlobalBounds()))
{
    // The instructions here are executed if the two sprites are in collision.
}

The strategy​

There are many ways to handle collisions. Here, we will employ a simple technique. It comes as follow: After each translation of the character, we test if it is in collision with any of the objects inside the game (Trees, stones...). If it is, we cancel the previous movement (We subtract the translation vector that we added to the position of the character). Otherwise, we do nothing. Basically, if a translation causes the player 'merge' with an object, we cancel it. Because the movement of the player is updated very frequently (Many very small movements), the character will stop right before he comes to collision with an object.

The code​

Here is the code handling the collisions between the player and the trees:
C++:
// For each tree.
for(int c=0; c < 8; c++)
{
    // If the player is in collision with the tree.
    if(player.getGlobalBounds().intersects(trees[c].getGlobalBounds()))
    {
        // We cancel the movement.
        player.setPosition(player.getPosition().x-trans.x, player.getPosition().y-trans.y);
    }
}
The same, but for the stones:
C++:
for(int c=0; c < 3; c++)
{
    if(player.getGlobalBounds().intersects(stones[c].getGlobalBounds()))
        player.setPosition(player.getPosition().x-trans.x, player.getPosition().y-trans.y);
}
The 2 sections of code from above must be placed after the player has been translated.

The code of the game so far​

C++:
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow win(sf::VideoMode(800, 600), "Introduction to coding", sf::Style::Close);

    // Grass

    sf::Texture grassTex;
    grassTex.loadFromFile("resources/grass.png");
    grassTex.setRepeated(true);

    sf::Sprite grass;
    grass.setTexture(grassTex);
    grass.setScale(5, 5);
    grass.setTextureRect(sf::IntRect(0,0,160,120));

    // Dirt tiles

    sf::Texture dirtTex;
    dirtTex.loadFromFile("resources/dirt.png");

    sf::Sprite dirtTiles[10];

    dirtTiles[0].setPosition(300, 60);
    dirtTiles[1].setPosition(660, 300);
    dirtTiles[2].setPosition(390, 480);
    dirtTiles[3].setPosition(660, 60);
    dirtTiles[4].setPosition(720, 420);
    dirtTiles[5].setPosition(180, 300);
    dirtTiles[6].setPosition(60, 180);
    dirtTiles[7].setPosition(60, 420);
    dirtTiles[8].setPosition(240, 420);
    dirtTiles[9].setPosition(480, 120);

    for(int c = 0; c < 10; c++)
    {
        dirtTiles[c].setTexture(dirtTex);
        dirtTiles[c].setScale(5, 5);
    }

    // Trees

    sf::Texture treeTex;
    treeTex.loadFromFile("resources/tree.png");

    sf::Sprite trees[8];
    trees[0].setPosition(50, 60);
    trees[1].setPosition(600, 150);
    trees[2].setPosition(630, 456);
    trees[3].setPosition(300, 600);
    trees[4].setPosition(720, 40);
    trees[5].setPosition(460, 500);
    trees[6].setPosition(20, 370);
    trees[7].setPosition(340, 240);

    for(int c = 0; c < 8; c++)
    {
        trees[c].setTexture(treeTex);
        trees[c].setScale(3, 3);
    }

    // Stones

    sf::Texture stoneTex;
    stoneTex.loadFromFile("resources/stone.png");

    sf::Sprite stones[3];
    stones[0].setPosition(304, 64);
    stones[1].setPosition(664, 304);
    stones[2].setPosition(180, 300);

    for(int c = 0; c < 3; c++)
    {
        stones[c].setTexture(stoneTex);
        stones[c].setScale(3, 3);
    }

    // Player

    sf::Texture playerTex;
    playerTex.loadFromFile("resources/player.png");

    sf::Sprite player;
    player.setTexture(playerTex);
    player.setPosition(400, 300);
    player.setScale(3, 3);

    float playerMovementSpeed = 200.0;
    sf::Clock playerMovementClock;

    // Game loop

    sf::Event event;

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

        // Player movements

        sf::Vector2f trans;
        float mouv =
        playerMovementClock.getElapsedTime().asSeconds() *
        playerMovementSpeed;

        if(sf:⌨️:isKeyPressed(sf:⌨️:W))
            trans.y -= mouv;
        if(sf:⌨️:isKeyPressed(sf:⌨️:S))
            trans.y += mouv;
        if(sf:⌨️:isKeyPressed(sf:⌨️:A))
            trans.x -= mouv;
        if(sf:⌨️:isKeyPressed(sf:⌨️:D))
            trans.x += mouv;

        player.setPosition(player.getPosition().x+trans.x, player.getPosition().y+trans.y);
        playerMovementClock.restart();

        // Collision testing

        for(int c=0; c < 8; c++)
        {
            if(player.getGlobalBounds().intersects(trees[c].getGlobalBounds()))
                player.setPosition(player.getPosition().x-trans.x, player.getPosition().y-trans.y);
        }
        for(int c=0; c < 3; c++)
        {
            if(player.getGlobalBounds().intersects(stones[c].getGlobalBounds()))
                player.setPosition(player.getPosition().x-trans.x, player.getPosition().y-trans.y);
        }

        // Rendering

        win.clear();

        win.draw(grass);

        for(int c = 0; c < 10; c++)
            win.draw(dirtTiles[c]);

        for(int c = 0; c < 8; c++)
            win.draw(trees[c]);

        for(int c = 0; c < 3; c++)
            win.draw(stones[c]);

        win.draw(player);

        win.display();
    }

    return 0;
}
 
Last edited by a moderator:

Buy us a coffee!

Buy me a coffee.
Back
Top Bottom