Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED]Collision detection and sliding alongside walls.  (Read 6304 times)

0 Members and 1 Guest are viewing this topic.

Moonkis

  • Jr. Member
  • **
  • Posts: 58
    • View Profile
[SOLVED]Collision detection and sliding alongside walls.
« on: April 12, 2013, 10:44:12 pm »
I'v been trying to get collision detection between the tiled world and my free moving objects to work, I'v been through MANY hiccups but I finally found a way to do the collision detection right, the only problem is I don't know how to make the player slide alongside a wall if he is moving in more than one direction and the other one is collision free.

This is what I have so far...it's working on the top and bottom walls but not the right and left:
void Player::update(float dt, const Tiles& tiles)
{
        float x = m_x;
        float y = m_y;
       
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) )
        {
                y -= m_speed;
        }
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) )
        {
                y += m_speed;
        }
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::Left ) )
        {
                x -= m_speed;
        }
        if( sf::Keyboard::isKeyPressed( sf::Keyboard::Right ) )
        {
                x += m_speed;
        }
       
        /* Calculate the nerest tiles around the player. */
        int startY = ( m_y - 32 ) / 32;
        int startX = ( m_x - 32 ) / 32;
        int endY = ( m_y + 64 ) / 32;
        int endX = ( m_x + 64) / 32;
       
        for( int sy = startY; sy < endY; sy++ )
        {
                for( int sx = startX; sx < endX; sx++ )
                {
                        if( tiles[sx][sy] != 1 && tiles[sx][sy] != 5 )
                        {
                                sf::IntRect wall;
                                wall.top = sy * 32;
                                wall.left = sx * 32;
                                wall.width = 32;
                                wall.height = 32;
                                m_boundingbox.top = y+20;
                                m_boundingbox.left = x+8;
                                if(m_boundingbox.intersects(wall))
                                {
                                        sf::IntRect xaxis(x+8,m_y+20,16,8);
                                        sf::IntRect yaxis(m_x+8,y+20,16,8);
                                       
                                        if( !xaxis.intersects(wall) )
                                        {
                                                m_x = x;
                                        }
                                        else if( !yaxis.intersects(wall) )
                                        {
                                                m_y = y;
                                        }

                                        return;
                                }
                               
                        }
                }
        }
        m_x = x;
        m_y = y;
}
 



I'v been trying all day and I have no idea how to achieve this.
« Last Edit: April 13, 2013, 12:26:36 pm by Moonkis »

santiaboy

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Re: Collision detection and sliding alongside walls.
« Reply #1 on: April 12, 2013, 11:22:46 pm »
I'm guessing is a 2D platformer, as you never said if it's a top down camera or what..

just when the character is falling and next to a wall? if you already have the collision, you are halfway there! you need to think how to SLOW THE DESCENT OF CHARACTER DOWN ;)

Aaaalso, I think you look into using gravity

Moonkis

  • Jr. Member
  • **
  • Posts: 58
    • View Profile
Re: Collision detection and sliding alongside walls.
« Reply #2 on: April 13, 2013, 12:56:23 am »
I'm guessing is a 2D platformer, as you never said if it's a top down camera or what..

just when the character is falling and next to a wall? if you already have the collision, you are halfway there! you need to think how to SLOW THE DESCENT OF CHARACTER DOWN ;)

Aaaalso, I think you look into using gravity

I should have been a bit clearer about that, it's not a 2D platformer but a birdview(?) rougelike with free movement as opposed to a grid based one.

And I turned towards the forum because I have no idea how to implement it, I'v sketched with pen and papper, tried different approaches, this is where I came closes to a working collision detection between tiles and the player.


EDIT:
I manage to solve it by revamping the code  a bit, checking each axis seperatly:
Code: [Select]
void Player::update(float dt, const Tiles& tiles)
{
float x = m_x;
float y = m_y;

if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) )
{
y -= m_speed;
}
if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) )
{
y += m_speed;
}
if( sf::Keyboard::isKeyPressed( sf::Keyboard::Left ) )
{
x -= m_speed;
}
if( sf::Keyboard::isKeyPressed( sf::Keyboard::Right ) )
{
x += m_speed;
}

// Find the nerest tiles around the player.
int startY = ( m_y - 32 ) / 32;
int startX = ( m_x - 32 ) / 32;
// We add 64 because we need to compensate the sprites width as well.
int endY = ( m_y + 64 ) / 32;
int endX = ( m_x + 64) / 32;

// Set up the movement variables.
bool moveX = true;
bool moveY = true;

// Iterate through the nerest tiles.
for( int sy = startY; sy < endY; sy++ )
{
for( int sx = startX; sx < endX; sx++ )
{
if( tiles[sx][sy] != 1 && tiles[sx][sy] != 5 )
{
// For each tile make a boundingbox.
sf::IntRect wall;
wall.top = sy * 32;
wall.left = sx * 32;
wall.width = 32;
wall.height = 32;

// Create two boundingboxes for the player, one for X-axis and one for Y-axis.
sf::IntRect xaxis(x+8,m_y+20,16,8);
sf::IntRect yaxis(m_x+8,y+20,16,8);

// If we intersect on the x-axis, prevent moving through the x-axis.
if( xaxis.intersects(wall) )
{
moveX = false;
}
// If we intersect on the y-axis, prevent moving through the y-axis.
if( yaxis.intersects(wall) )
{
moveY = false;
}
}
}
}
// If movement is true, then move accordingly.
if( moveX ) m_x = x;
if( moveY ) m_y = y;
}

« Last Edit: April 13, 2013, 12:27:46 pm by Moonkis »