Search code examples
c++sdlgame-physicssdl-2

Bounding box collision between specific tiles and a sprite using vectors and multimap


I have a set of random x and y co-ordinate values generated and have stored them to a multimap and then have copied the list of x co-ordinate values to a vector x and the list of y co-ordinate values to a vector y and then have passed them in the function iteratively

bool Sprite::collisionExists( int x, int y, SDL_Rect b  )

and I pass it in mycheckCollisions() function in an if statement like this

 collisionExists( x[k],y[l],sprite)

where sprite is the SDL_Rect type I created in that function.

I have a tile map created filled with rocks where I want the sprite to move around in the map but not being able to go forward if a rock is in the next tile.

The problem I am facing is that I can't seem to detect any collision when I created a vector and compared each value whereas before when it tested it with only two images the code worked perfectly.

Here is the code where I randomly insert the x and y co-ordinate values for the tiled map

//randomly set positions of the rocks
void setRandomRockPositions()
{
for(int i=0;i<40;i++)
{
    int x,y;

    int minX=3;
    int maxX=8;
    x=roll(minX,maxX);


    int minY=1;
    int maxY=9;
    y=roll(minY,maxY);

    //if x and y are not the location for the house tile, add a rock
    if((x!=9 && y!=5))
    {
        rocks.insert(std::pair<int, int>(x, y));

    }
 }

}

Some variables and constant declarations

  //Screen attributes
const int SCREEN_WIDTH  = 1024;
const int SCREEN_HEIGHT = 728;

// Scaling the tiles to be 80x80
const int TILE_SIZE = 80;

std::multimap<int, int> rocks;
static const int SPRITE_WIDTH = 104;
static const int SPRITE_HEIGHT = 96;

The code for detecting collision between the sprite and rocks

bool Sprite::checkCollisions()
{
SDL_Rect sprite;
sprite.x= mPosX;
sprite.y=mPosY;
sprite.w=SPRITE_WIDTH;
sprite.h=SPRITE_HEIGHT;

std::vector<int> x(rocks.size());
std::vector<int> y(rocks.size());

std::multimap<int,int>::iterator it=rocks.begin();

while(it!=rocks.end())
{
    for(int i=0;i<rocks.size();i++)
    {
        x[i]= (*it).first;
        ++it;
    }
}

std::multimap<int,int>::iterator it2=rocks.begin();
while(it2!=rocks.end())
{
    for(int j=0;j<rocks.size();j++)
    {
        y[j]=(*it2).second;
        ++it2;
    }
}

for(int k=0;k<rocks.size();k++)
{
    for(int l=0; l<rocks.size();l++)
    {
        if(collisionExists( x[k],y[l],sprite))
        {
            return true;
            std::cout<<"Collision Detected!"<<std::endl;
        }
    }
}

return false;
}

The basic detection collision code

bool Sprite::collisionExists( int x, int y, SDL_Rect b  )
{
//The sides of the rectangles
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;

//Calculate the sides of rect A
leftA = x;
rightA = x + SPRITE_WIDTH;
topA = y;
bottomA = y + SPRITE_HEIGHT;

//Calculate the sides of rect B
leftB = b.x;
rightB = b.x + b.w;
topB = b.y;
bottomB = b.y + b.h;

//If any of the sides from A are outside of B
if( bottomA <= topB)//-50 )
{
    return false;
}

if( topA >= bottomB)//-50 )
{
    return false;
}

if( rightA <= leftB)//+50 )
{
    return false;
}

if( leftA >= rightB)//-50 )
{
    return false;
}

//If none of the sides from A are outside B
return true;
}

I think my problem lies in the checkCollisions() function, because the the ouput "Collision Detected" is never shown on the console. I have tried many variations of looping and storing them from the map to the vector but I still can't figure out why the collision detection stopped working.


Solution

  • The solution I've realised now is actually very simple. I had to multiply each element of x and y with the tile size.

    collisionExists( x[k]*TILE_SIZE,y[l]*TILE_SIZE,sprite)

    I was passing x and y co-ordinates instead to my function and that was a fundamental error on my part.