Question

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.

Was it helpful?

Solution 2

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.

OTHER TIPS

I think my problem lies in the checkCollisions() function, because the the ouput "Collision Detected" is never shown on the console.

That might be due to the fact that checkCollisions() returns before displaying the "Collision Detected!" message. Move the return one line lower, and it might work as expected:

if(collisionExists( x[k],y[l],sprite))
{
    std::cout << "Collision Detected!" << std::endl;
    return true;
}

Try it.


By the way, you might want to

  • switch from global variables to (const) reference parameters
  • simply step through your rocks container instead of using two loops to fill separate x and y vectors, where you then test every x coordinate against every y coordinate.

    for( const auto & coords : rocks ) {
        if( collisionExists( coords.first, coords.seconds, sprite) ) {
            std::cout << "Collision Detected!" << std::endl;
            return true;
        }
    }
    
  • if you really want to use each x with each y, you could at least fill the separate vectors in a single loop:

    for( const auto & coords : rocks ) {
        x.push_back( coords.first );
        y.push_back( corrds.second );
    }
    

(Warning: all code written in browser only -- uncompiled and untested!)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top