0
votes

I'm creating a game in C++ using SFML library, and during implementation tile map collision(i'm loading map from txt file - 1's stand for platforms, 0's for free space). https://imgur.com/a/tQZc6

I came across a problem with handling all four type of collisions at the same time(from bottom, top, left and right).What I mean: when there is no collision, the player can normally move, but if we hit the wall, collision appears only for FIRST written if() statement(in our example only right collision occurs, rest are being omitted). Here's my code (i'll paste only necessary things)

class Player
{
public:
    Player();
    Player(sf::Texture* texture, sf::Vector2u imageCount, sf::Vector2f position, float switchTime, float speed, float jumpSpeed);
    ~Player();

    void UpdatePlayer(float deltaTime);

    float top, right, left, bottom;

private:
    sf::Vector2f _position;
    float groundHeight = 40; //i've added gravity and hardcoded the ground height to create jumping 
    float _jumpSpeed; // later on, it will be replaced with bottom collision
    const float gravity = 981.0f;
    sf::RectangleShape body;
    float _speed;

};

//Player.cpp
void Player::UpdatePlayer(float deltaTime)
{
    sf::Vector2f movement(0.0f, 0.0f);

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
    {
        movement.x -= _speed * deltaTime; //we are using delta time in order to move the object in according to time
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
    {
        movement.x += _speed * deltaTime;
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
    {
        movement.y = -sqrt(5.0f * gravity * _jumpSpeed) * deltaTime;
    }
    if (body.getPosition().y + body.getSize().y < groundHeight || movement.y < 0)
    {
        movement.y += gravity * deltaTime;
    }
    else
    {
        body.setPosition(body.getPosition().x, groundHeight - body.getSize().y);
        movement.y = 0;
    }



    bottom = body.getPosition().y + body.getSize().y;
    left = body.getPosition().x;
    right = body.getPosition().x + body.getSize().x;
    top = body.getPosition().y;


    body.move(movement);

}

//Source.cpp

 void LoadCollisionMap(const char*filename)
{
    std::ifstream openfile(filename);
    std::vector<int> tempMap;
    CollMap.clear();

    if (openfile.is_open())
    {
        while (!openfile.eof())
        {
            std::string str, value;
            std::getline(openfile, str);
            std::stringstream stream(str);

            while (std::getline(stream, value, ' '))
            {
                if (value.length() > 0)
                {
                    int a = atoi(value.c_str());
                    tempMap.push_back(a);
                }
            }
            CollMap.push_back(tempMap);
            tempMap.clear();
        }
    }
}
int main()
{
    LoadCollisionMap("Map2.txt"); //Collision map

Player player(&playerTexture, sf::Vector2u(3, 9),sf::Vector2f(100.0f, 150.0f) ,0.3f, 400.0f, 555.0f);

    for (int i = 0; i < CollMap.size(); i++)
    {
        for (int j = 0; j < CollMap[i].size(); j++)
        {
            if (CollMap[i][j] == 1)
            {

                int CollBottom, CollRight, CollLeft, CollTop;
                CollBottom = i * 32 + 32;
                CollTop = i * 32;
                CollLeft = j * 32;
                CollRight = j * 32 + 32;

                if (player.right < CollLeft || player.left > CollRight || player.top > CollBottom || player.bottom < CollTop)
                {
                    //no collision
                }
                else
                {


                    if (player.right > CollLeft)
                    {
                        std::cout << "collision" << std::endl;
                        player.body.setPosition(player.body.getPosition().x - 1, player.body.getPosition().y);
                        break;

                    }


                    if (player.left < CollRight)
                    {
                        std::cout << "collision 2" << std::endl;
                        player.body.setPosition(player.body.getPosition().x + 1, player.body.getPosition().y);
                        break;
                    }


                    if (player.top < CollBottom)
                    {
                        std::cout << "collision 3" << std::endl;

                        player.body.setPosition(player.body.getPosition().x, player.body.getPosition().y + 1);


                        break;


                    }

                    if (player.bottom > CollTop)
                    {
                        std::cout << "collision 4" << std::endl;

                        player.body.setPosition(player.body.getPosition().x, player.body.getPosition().y - 1);
                        break;
                    }


                }

            }

        }
    }
1

1 Answers

0
votes

Operator break return you immediately from the most nested loop. If you want to check all collisions, you should remove break from collision checking, and replace it for example with bool variable.

bool collisionDetected = false;

if (player.right > CollLeft)
{
    std::cout << "collision" << std::endl;
    player.body.setPosition(player.body.getPosition().x - 1, player.body.getPosition().y);

    collisionDetected = true;
}

...

if( collisionDetected ) 
    break;