Search code examples
c++arrays2dcollision-detectionsfml

How to check collision on 2D map in SFML?


I have one RectangleShape for wall and I draw this one object for every "1" on my 2D map:

int map[5][8] =
{
    { 1, 1, 1, 1, 1, 1, 1, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 1, 0, 1, 1, 0, 1 },
    { 1, 2, 1, 0, 0, 0, 3, 1 },
    { 1, 1, 1, 1, 1, 1, 1, 1 }
};

sf::RectangleShape player;
    player.setSize(sf::Vector2f(32,32));

    sf::RectangleShape wall;
    wall.setSize(sf::Vector2f(32,32));
    wall.setFillColor(sf::Color(40, 199, 40));

for (int mapX= 0; mapX< 8; mapX++)
        {
            for (int mapY= 0; mapY< 5; mapY++)
            {
                if (map[mapY][mapX] == 1)
                {
                    wall.setPosition(mapX * 32, mapY * 32);
                    window.draw(wall);
                }
}
}

And I checking for collision with code listed down, but this works for only last drawn wall. How to fix this? Theres only one object wall and I want to check collision for all drawned walls for my 2D array map.

if (event.type == sf::Event::TextEntered)
            {
                fPlayerY_t = fPlayerY;
                fPlayerX_t = fPlayerX;

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) fPlayerY_t = fPlayerY - 32;
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) fPlayerY_t = fPlayerY + 32;
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) fPlayerX_t = fPlayerX + 32;
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) fPlayerX_t = fPlayerX - 32;

                // temp pos
                player.setPosition(fPlayerX_t, fPlayerY_t);

                // collision with wall
                if (player.getPosition().x == wall.getPosition().x &&
                    player.getPosition().y == wall.getPosition().y)
                {
                    // back to prev position
                    player.setPosition(fPlayerX, fPlayerY);
                }
                else
                {
                    // No collision
                    fPlayerX = fPlayerX_t;
                    fPlayerY = fPlayerY_t;
                }
}

Solution

  • Convert the coordinates of the player in array coordinates then check if map[x][y] == 1. So do not have to loop through your entire map every game loop. To convert into array coordinates, use int conversion :

    int playerTileX = (int)(playerWorldX / 32);
    int playerTileY = (int)(playerWorldY / 32);
    
    if(map[playerTileX ][playerTileY ] == 1)
    {
        // collision.
    }
    else
    {
        // no collision.
    }
    

    What I dislike with this solution : it only checks for tiles collision, you have to be sure every wall is the same size (here 32*32).