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

Author Topic: I'm confused about collision detection.  (Read 3674 times)

0 Members and 2 Guests are viewing this topic.

aratnon

  • Newbie
  • *
  • Posts: 24
    • View Profile
I'm confused about collision detection.
« on: April 04, 2013, 02:50:29 pm »
I want to detect collision between player and object in map. I keep all objects in vector.
Here this is the code

bool Collision::IsCollided(Player *player, std::vector<Platform*> platformList)
{
        for(int i = 0; i < platformList.size(); i++)
        {
                if(player->GetPosition().x + player->GetWidth() > platformList[i]->GetPosition().x &&
                        player->GetPosition().x < platformList[i]->GetPosition().x + platformList[i]->GetWidth() &&
                        player->GetPosition().y + player->GetHeight() > platformList[i]->GetPosition().y &&
                        player->GetPosition().y < platformList[i]->GetPosition().y + platformList[i]->GetWidth())
                        return true;
        }
        return false;
}
 

And this is in main program.
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
        player->SetFacing("Right");
        player->SetStand(false);
        player->SetWalk(true);
        player->SetSourceY(1);
        player->Update(clock);
        if(Collision::IsCollided(player, currentLevel->GetAllPlatforms()))
                return;
        player->MoveForward();         
}

if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
        player->SetFacing("Left");
        player->SetStand(false);
        player->SetWalk(true);
        player->SetSourceY(2);
        player->Update(clock);
        if(Collision::IsCollided(player, currentLevel->GetAllPlatforms()))
                return;
        player->MoveBackward();        
}

The problem is when a player walk and collide with an object and then a player can't move because his position is overlapping in object position. As the logic of my code if player position is in object position it must return, so player stuck in that position and can't move.
I can't figure out how to fix this problem ?

Moonkis

  • Jr. Member
  • **
  • Posts: 58
    • View Profile
Re: I'm confused about collision detection.
« Reply #1 on: April 04, 2013, 04:38:53 pm »
bool Collision::IsCollided(Player *player, std::vector<Platform*> platformList)
Instead of passing it by value I suggest you pass it by (const) reference, because copying an entire vector of objects can be quite slow.


There are actually two parts when dealing with collisions, the first one is collision detection and the second one is collision response.

The reason why you can't move the player after it's first collision is because you don't move the player back until it's in a none collision phase, because you don't do that the player will always be in collision and not allowed to move.

This is commonly done by finding the intersection amount and moving the player back by that amount, in XNA you can get that information from the class, in SFML i think you will need to do it yourself, I imagine it to be something along the line of the delta between the player and platform.

if(Collision::IsCollided(player, currentLevel->GetAllPlatforms()))
I don't know what happens behind the scene here but going by the name of the function you should consider doing some culling so that you don't check for EVERY platform in the entire level, just the ones that has can be collided by the player ( i.e what is on screen ).

I'll leave the in depth information to the others!

aratnon

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: I'm confused about collision detection.
« Reply #2 on: April 04, 2013, 05:57:39 pm »
Thank you very much. I can solve the problem by move player back a little from collided position, then player can move again.

About checking collision between player and object I don't know how to manage all of objects that will be checked in efficient way.

Do you have any idea about manage object to check collision ?


Moonkis

  • Jr. Member
  • **
  • Posts: 58
    • View Profile
Re: I'm confused about collision detection.
« Reply #3 on: April 04, 2013, 06:32:33 pm »
There are tons of ways but if you are building a TILEbased game with a 2D array representing the position of the tiles then it's quite simple give that all the tiles are of the same size and shape.


With the camera you kinda calculate the offset and get an beginning position something like:

startX = static_cast<int>(camera.x / TILE_SIZE );

Then you can check between the boundaries of StartX and StartX + ScreenWidth/ TILE_SIZE


aratnon

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: I'm confused about collision detection.
« Reply #4 on: April 04, 2013, 06:44:04 pm »
I don't use tile base my objects have different size. I just put all in vector. I don't know this is gonna be bad method.

If I pick objects that are in current screen from main vector that contains all of objects. Can I do this ?

vivo

  • Jr. Member
  • **
  • Posts: 50
    • View Profile
    • Email
Re: I'm confused about collision detection.
« Reply #5 on: April 05, 2013, 03:53:57 pm »
I want to detect collision between player and object in map. I keep all objects in vector.
Here this is the code

bool Collision::IsCollided(Player *player, std::vector<Platform*> platformList)
{
        for(int i = 0; i < platformList.size(); i++)
        {
                if(player->GetPosition().x + player->GetWidth() > platformList[i]->GetPosition().x &&
                        player->GetPosition().x < platformList[i]->GetPosition().x + platformList[i]->GetWidth() &&
                        player->GetPosition().y + player->GetHeight() > platformList[i]->GetPosition().y &&
                        player->GetPosition().y < platformList[i]->GetPosition().y + platformList[i]->GetWidth())
                        return true;
        }
        return false;
}
 

I don't really understand the problem, but maybe intersects method can help you, would be something like:
bool Collision::IsCollided(Player *player, std::vector<Platform*> platformList)
{
        for(int i = 0; i < platformList.size(); i++)
        {
                if(player->GetSprite().GetGlobalBounds().intersects(platformList[i]->GetSprite().GetGlobalBounds())
                        return true;
        }
        return false;
}
 
« Last Edit: April 05, 2013, 03:57:34 pm by vivo »