I have managed to create a collision detection system for my tile-based jump'n'run game (written in C++/SFML), where I check on each update what values the surrounding tiles of the player contain and then I let the player move accordingly (i. e. move left when there is an obstacle on the right side).
This works fine when the player sprite is not too big: Given a tile size of 5x5 pixels, my solution worked quite fine with a spritesize of 3x4 and 5x5 pixels.
My problem is that I actually need the player to be quite gigantic (34x70 pixels given the same tilesize). When I try this, there seems to be an invisible, notably smaller boundingbox where the player collides with obstacles, the player also seems to shake strongly. Here some images to explain what I mean:
Works: http://tinypic.com/r/207lvfr/8
Doesn't work: http://tinypic.com/r/2yuk02q/8
Another example of non-functioning: http://tinypic.com/r/kexbwl/8 (the player isn't falling, he stays there in the corner)
My code for getting the surrounding tiles looks like this (I removed some parts to make it better readable):
std::vector<std::map<std::string, int> > Game::getSurroundingTiles(sf::Vector2f position)
{
// converting the pixel coordinates to tilemap coordinates
sf::Vector2u pPos(static_cast<int>(position.x/tileSize.x), static_cast<int>(position.y/tileSize.y));
std::vector<std::map<std::string, int> > surroundingTiles;
for(int i = 0; i < 9; ++i)
{
// calculating the relative position of the surrounding tile(s)
int c = i % 3;
int r = static_cast<int>(i/3);
// we subtract 1 to place the player in the middle of the 3x3 grid
sf::Vector2u tilePos(pPos.x + (c - 1), pPos.y + (r - 1));
// this tells us what kind of block this tile is
int tGid = levelMap[tilePos.y][tilePos.x];
// converts the coords from tile to world coords
sf::Vector2u tileRect(tilePos.x*5, tilePos.y*5);
// storing all the information
std::map<std::string, int> tileDict;
tileDict.insert(std::make_pair("gid", tGid));
tileDict.insert(std::make_pair("x", tileRect.x));
tileDict.insert(std::make_pair("y", tileRect.y));
// adding the stored information to our vector
surroundingTiles.push_back(tileDict);
}
// I organise the map so that it is arranged like the following:
/*
* 4 | 1 | 5
* -- -- --
* 2 | / | 3
* -- -- --
* 6 | 0 | 7
*
*/
return surroundingTiles;
}
I then check in a loop through the surrounding tiles, if there is a 1 as gid (indicates obstacle) and then check for intersections with that adjacent tile.
The problem I just can't overcome is that I think that I need to store the values of all the adjacent tiles and then check for them. How? And may there be a better solution?
Any help is appreciated.
P.S.: My implementation derives from this blog entry, I mostly just translated it from Objective-C/Cocos2d.