1
\$\begingroup\$

I am working on a grid based game in c++. I am using this project to learn c++ syntax and get stronger with some programming concepts in general so fairly beginner level programmer here. The problem I am having is with player movement and detection of the walls. Its probably something pretty obvious that I am missing but I have been staring at the code for hours so probably overlooking something. The map is built using an array by dividing the pixels on the screen into 8x8 squares. each one of those elements in the array are given a value based on what tile should be built in that part of the map. Currently the player cant move therefor the collision is being detected even though the player is not hitting a wall.

*** edited the code again - the player can now move. but then eventually there is a collision no where near the wall and then it crashes

void Game::playerMove()
{

    //set the hspd and vspd based on the keys being pressed
    hspd = ((wnd.kbd.KeyIsPressed(VK_RIGHT)) - (wnd.kbd.KeyIsPressed(VK_LEFT)));
    vspd = ((wnd.kbd.KeyIsPressed(VK_DOWN)) - (wnd.kbd.KeyIsPressed(VK_UP)));

    //check for collision horizontally
    if (gridCollision(pX + hspd, pY))
    {
        hspd = 0;
    }

    //move horizontally
    pX += hspd;
    //check for collision vertically
    if (gridCollision(pX, pY + vspd))
    {
        vspd = 0;
    }

    //move vertically
    pY += vspd;

}

bool Game::gridCollision(int x, int y)
{
    int xx = x;
    int yy = y;

    //remember the position
    int curX = x;
    int curY = y;

    pX = xx;
    pY = yy;

    //Collisions within the grid.
    //The players 'map' position/bounding box tile position
    int rgtBbox = mapXpos(pX + 8);
    int leftBbox = mapXpos(pX);
    int botBbox = mapYpos(pY + 8);
    int topBbox = mapYpos(pY);

    //Check for collision in the map tiles.
    bool x_collision = ((map[rgtBbox][topBbox] != floor) || (map[leftBbox][topBbox]) != floor);
    pX = curX;

    bool y_collision = ((map[rgtBbox][botBbox] != floor) || (map[rgtBbox][topBbox]) != floor);
    pY = curY;

    return x_collision || y_collision;

}

int Game::mapXpos(int x)
{
    int mapXval = 0;
    for (int i = x; i < 8; i -= 8)
    {
        mapXval += 1;
    }

    return mapXval;
}

int Game::mapYpos(int y)
{
    int mapYval = 0;
    for (int i = y; i < 8; i -= 8)
    {
        mapYval += 1;
    }

    return mapYval;
}

there is only something off with the collision detection when moving the player.

fyi the map builder is working great so far. It builds a room where the player starts and generates more rooms off of that room if there is enough space to build it.

IT DOES THE THING.

there is a small off by one pixel error right now but that's okay. Here is the solution:

void Game::playerMove()
{

    getInput();

    //set the hspd and vspd based on the keys being pressed
    hspd = rightKey - leftKey;
    vspd = downKey - upKey;

    //check for collision horizontally
    if (gridCollision(pX + hspd, pY))
    {
        while (!gridCollision(pX + signFunc(hspd), pY))
        {
            pX += signFunc(hspd);
        }

        hspd = 0;
    }

    //move horizontally
    pX += hspd;
    //check for collision vertically
    if (gridCollision(pX, pY + vspd))
    {
        while (!gridCollision(pX, pY + signFunc(vspd)))
        {
            pY += signFunc(vspd);
        }

        vspd = 0;
    }

    //move vertically
    pY += vspd;

    //Catch OutofBounds
    if (pX < 0)
    {
        pX = 1;
    }
    else if (pX > ((mapWidth * tileWidth) - 8))
    {
        pX = (mapWidth * tileWidth) - 8;
    }

    if (pY < 0)
    {
        pY = 1;
    }
    else if (pY > ((mapHeight * tileHeight) - 8))
    {
        pY = (mapHeight * tileHeight) - 8;
    }

}

bool Game::gridCollision(int x, int y)
{
    //Collisions within the grid.
    //The players 'map' position/bounding box tile position
    int rgtBbox = mapXpos(x + 8);
    int leftBbox = mapXpos(x);
    int botBbox = mapYpos(y + 8);
    int topBbox = mapYpos(y);

    //Check for collision in the map tiles.
    bool x_collision = ((map[rgtBbox][topBbox] != floor) || (map[leftBbox][topBbox]) != floor);
    bool y_collision = ((map[rgtBbox][botBbox] != floor) || (map[rgtBbox][topBbox]) != floor);

    return x_collision || y_collision;

}

int Game::mapXpos(int x)
{
    int mapXval = 0;
    for (int i = x; i > 8; i -= 8)
    {
        mapXval += 1;
    }

    return mapXval;
}

int Game::mapYpos(int y)
{
    int mapYval = 0;
    for (int i = y; i > 8; i -= 8)
    {
        mapYval += 1;
    }

    return mapYval;
}

int Game::signFunc(int a)
{
    if (a > 0)
    {
        return 1;
    }
    else if (a < 0)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}

void Game::getInput()
{
    if (wnd.kbd.KeyIsPressed(VK_RIGHT))
    {
        rightKey = 1;
    }
    else
    {
        rightKey = 0;
    }
    if (wnd.kbd.KeyIsPressed(VK_LEFT))
    {
        leftKey = 1;
    }
    else
    {
        leftKey = 0;
    }
    if (wnd.kbd.KeyIsPressed(VK_UP))
    {
        upKey = 1;
    }
    else
    {
        upKey = 0;
    }
    if (wnd.kbd.KeyIsPressed(VK_DOWN))
    {
        downKey = 1;
    }
    else
    {
        downKey = 0;
    }
}
\$\endgroup\$
4
  • \$\begingroup\$ I don't know c++ so I may not fully understand your code, but I think you just need to add a Boolean value to your tiles and if true, don't allow movement into that tile. \$\endgroup\$ Commented Oct 6, 2016 at 15:39
  • \$\begingroup\$ oh yupp. that is what i meant gonna edit that. \$\endgroup\$ Commented Oct 6, 2016 at 15:44
  • \$\begingroup\$ @NealDavis I have it just set the movespd to 0 if it is detecting the collision. which makes me think this is kind of where the problem is. I need to move the player. Do the check and if it is a collision move the player back to the original position before the collision(before rendering the frame). \$\endgroup\$ Commented Oct 6, 2016 at 15:48
  • \$\begingroup\$ That sounds like a fine method. Any luck yet? \$\endgroup\$ Commented Oct 7, 2016 at 16:48

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.