Q.Reilly
Q.Reilly

Reputation: 33

Problems with interaction between player movement and collisions

I have been trying to create a top-down game, similar to that of 'realm of the mad gods'. I am having some issues with getting my player movement to behave properly with my player movement.

Some things to keep in mind. There are 4 buffers located on each side of my player which is 1 pixel thick. When the player collides with a wall at a speed of 1 pixel, the player will stop and behaves as expected.

Here is the issue. I want my player to move faster than 1 pixel, but when I increase the player speed to 4 pixels, the player will move into the wall. this makes sense, but I have taken measures to avoid this, but have been unsuccessful so far.

Code sample 1 shows the movement code.

Code sample 2 shows the movement trigger code.

I have put the rest of the code on GitHub, which can be found through the following link: https://github.com/Quinn-R/top-down-tech-demo

Thanks for any help I receive.

EDIT: My player does not completely surpass the wall. Both the player and the wall are 32 pixel boxes.

EDIT2: Code sample 3 is the code that shows the game loop.

Code sample 1

void player::move(std::string direction, std::vector<wall> walls)
{
    if(direction == "left")
    {
        for(int i = 0; i < walls.size(); i++)
        {
            if(leftBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || leftBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
            {
                //collideTop = 0;
                //collideBottom = 0;
                collideLeft = 1;
                //collideRight = 0;
            }
        }
        if(collideLeft != 1)
        {
            character.move(-1, 0);
            collideTop = 0;
            collideBottom = 0;
            collideLeft = 0;
            collideRight = 0;
        }
    }

    if(direction == "right")
    {
        for(int i = 0; i < walls.size(); i++)
        {
            if(rightBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || rightBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
            {
                //collideTop = 0;
                //collideBottom = 0;
                //collideLeft = 0;
                collideRight = 1;
            }
        }
        if(collideRight != 1)
        {
            character.move(1, 0);
            collideTop = 0;
            collideBottom = 0;
            collideLeft = 0;
            collideRight = 0;
        }
    }

    if(direction == "up")
    {
        for(int i = 0; i < walls.size(); i++)
        {
            if(topBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || topBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
            {
                collideTop = 1;
                //collideBottom = 0;
                //collideLeft = 0;
                //collideRight = 0;
            }
        }
        if(collideTop != 1)
        {
            character.move(0, -1);
            collideTop = 0;
            collideBottom = 0;
            collideLeft = 0;
            collideRight = 0;
        }
    }

    if(direction == "down")
    {
        for(int i = 0; i < walls.size(); i++)
        {
            if(bottomBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || bottomBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds()*/)
            {
                //collideTop = 0;
                collideBottom = 1;
                //collideLeft = 0;
                //collideRight = 0;
            }
        }
        if(collideBottom != 1)
        {
            character.move(0, 1);
            collideTop = 0;
            collideBottom = 0;
            collideLeft = 0;
            collideRight = 0;
        }
    }
}

Code sample 2

void sfml1::buttonPressed()
{

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
        for(int i = 0; i < speed; i++)
        {
            players[0].move("left", walls);
        }
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
        for(int i = 0; i < speed; i++)
        {
            players[0].move("right", walls);
        }
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
        for(int i = 0; i < speed; i++)
        {
            players[0].move("up", walls);
        }
    }

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    {
        for(int i = 0; i < speed; i++)
        {
            players[0].move("down", walls);
        }
    }
}    

Code sample 3

void sfml1::sfmlLoop()
{
    setWalls();
    while(window.isOpen())
    {

        update();
        buttonPressed();
        update();

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

                /*if (event.type == sf::Event::Resized)
                {
                    // update the view to the new size of the window
                    //event.size.width, event.size.height);
                    //view1.setWidth();
                    //view1.setViewport(sf::FloatRect(0, 0, 1, 1.5f));
                    view1.scale(1, 1);
                    window.setView(view1);
                }*/
        }

        draw();

    }
}

Upvotes: 2

Views: 84

Answers (1)

Ori Almog
Ori Almog

Reputation: 59

While inside the buttonPressed() function, your character's state is defined by its collision buffers. When you make this call:

for(int i = 0; i < speed; i++)
{
    players[0].move("right", walls);
}

The move() function has the potential of changing the player's state, but this is not reflected in the player's collision buffer. You move speed times to the right while making the collision check from your initial position speed times.

All you need to do is call bufUpdate() at the end of your move() function. This will ensure that after the movement has been resolved, your collision buffer is updated.

Upvotes: 1

Related Questions