Hello everybody.
I'm trying to learn how to make games with SDL and C++ using mainly LazyFoo's tutorials.
Everything was going relatively well, until I stumbled upon a problem I do not know how to solve.
I have a tile based map, and up until now I was capping the frame rate and the character moved fine around the map. When the player contacted a tile, I was subtraction the velocity from the player's position, and it worked fine.
But after I started using frame independent movement, subtracting the velocity obviously stopped working, and I'm not sure what to do now.
The ideal, I think, would be to set the player's contacting side to not be greater than the tile's (kind of like I handle the player's contact with the level's boundaries), but the way I handle the tile map I don't know how to get the tile's position.
Here is my code. I'm very new at programming, so it might be a bit crude:
Collision detection:
bool collision( SDL_Rect a , SDL_Rect b )
{
int lefta , leftb;
int righta , rightb;
int topa , topb;
int bottoma , bottomb;
lefta = a.x;
righta = a.x + a.w;
topa = a.y;
bottoma = a.y + a.h;
leftb = b.x;
rightb = b.x + b.w;
topb = b.y;
bottomb = b.y + b.h;
if( righta <= leftb || lefta >= rightb || bottoma <= topb || topa >= bottomb ) return false;
return true;
}
Tile setting and tile collision detection:
bool collision( SDL_Rect a , tile * tiles[] )
{
for( int t = 0 ; t < TOTAL_TILES ; t++ )
{
if( tiles[t]->get_type() == PLATFORM )
{
if( collision( a , tiles[t]->get_box() ) ) return true;
}
}
return false;
}
bool set_tiles( tile * tiles[] )
{
int x = 0;
int y = 0;
std::ifstream map( "tilemap.map" );
if( map == NULL ) return false;
for( int t = 0 ; t < TOTAL_TILES ; t++ )
{
int type = 0;
map >> type;
if( map.fail() )
{
map.close();
return false;
}
if( type >= 0 && type < TILE_SPRITES ) tiles[t] = new tile( x , y , type );
else
{
map.close();
return false;
}
x += TILE_WIDTH;
if( x >= LEVEL_WIDTH )
{
x = 0;
y += TILE_HEIGHT;
}
}
map.close();
return true;
}
Player movement:
void player::move( Uint32 delta_ticks , tile * tiles[] )
{
x += xvel * ( delta_ticks / 1000.f );
if( x < 0 ) x = 0;
if( x + PLAYER_WIDTH > LEVEL_WIDTH ) x = LEVEL_WIDTH - PLAYER_WIDTH;
if( collision( box , tiles ) )
{
if( xvel > 0 ) ///WHAT DO I DO HERE?///
else if( xvel < 0 ) ///WHAT DO I DO HERE?///
}
y += yvel * ( delta_ticks / 1000.f );
if( collision( box , tiles ) )
{
if( yvel >= 0 )
{
///WHAT DO I DO HERE?///
jumping = false;
}
else ///WHAT DO I DO HERE?///
}
else yvel += gravity;
if( yvel >= VELOCITY * 8 ) yvel = VELOCITY * 8;
if( y > LEVEL_HEIGHT + 50 )
{
y = 0;
x = 0;
status = FACING_RIGHT;
}
box.x = x;
box.y = y;
}
I have also tried to seperate vertical from horizontal collision detection, but it did not seem to help.
The best I could think of to do it is this:
bool horizontal_collision( SDL_Rect a , SDL_Rect b )
{
int lefta , leftb;
int righta , rightb;
int topa , topb;
int bottoma , bottomb;
lefta = a.x;
righta = a.x + a.w;
topa = a.y;
bottoma = a.y + a.h;
leftb = b.x;
rightb = b.x + b.w;
topb = b.y;
bottomb = b.y + b.h;
if( righta >= leftb && lefta <= rightb && bottoma > topb && topa < bottomb ) return true;
return false;
}
bool vertical_collision( SDL_Rect a , SDL_Rect b )
{
int lefta , leftb;
int righta , rightb;
int topa , topb;
int bottoma , bottomb;
lefta = a.x;
righta = a.x + a.w;
topa = a.y;
bottoma = a.y + a.h;
leftb = b.x;
rightb = b.x + b.w;
topb = b.y;
bottomb = b.y + b.h;
if( bottoma >= topb && topa <= bottomb && righta > leftb && lefta < rightb ) return true;
return false;
}
I've been trying various thing for three days now, but nothing seems to work. So a little help from someone more experienced would be appreciated.
Thank you in advance. :-)