Message Board


Message Board > C/C++ > Help with some collisions

October 19, 2013, 05:59
DoctorN
Whiskered
91 posts
Hello,

I have been working on an Allegro 4.2.3 tutorial, and I am having some problems with collision. I will supply all that I think is needed. First, there is a hitbox class.
Code:
class hitbox
{
public:
    int x;
    int y;
    int w;
    int h;
}; 

And there is a collision process used for colliding with the world
Code:
bool check_collision( hitbox A, hitbox 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 = A.x;
    rightA = A.x + A.w;
    topA = A.y;
    bottomA = A.y + A.h;

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

    //If no sides from A are outside of B
    if( ( ( bottomA <= topB ) || ( topA >= bottomB ) || ( rightA <= leftB ) || ( leftA >= rightB ) ) == false )
        //A collision is detected
        return true;

    //If neither set of collision boxes touched
    return false;
}

bool world_collsion( hitbox A ) {
   
    for( int t = 0; t < TILE.size(); t++ )
        if( check_collision( A, TILE[ t ].get_box() ) )
            return true;
   
    return false;

In my player process, I have this for horizontal movement
Code:
//moving
    if( key[KEY_RIGHT] && !key[KEY_LEFT] ) {
        dir = 1;
        xspeed = 1;
    }
    if( key[KEY_LEFT] && !key[KEY_RIGHT] ) {
        dir = -1;
        xspeed = -1;
    }
    if( key[KEY_RIGHT] || key[KEY_LEFT] )
        walking = true;
    if( ( !key[KEY_RIGHT] && !key[KEY_LEFT] ) || ( key[KEY_RIGHT] && key[KEY_LEFT] ) ) {
        xspeed = 0;
        walking = false;
        i = 3;
    }
   
    //horizontal offset
    x += xspeed;
    set_hitbox();
   
    //collision with the walls
    if( world_collsion( player_hitbox ) ) {
        x -= xspeed;
        set_hitbox();
    } 

For a long time, the player would get stuck in walls and then moonwalk when I went the other way, so I changed the order and that helped (I hope so). Now here is the vertical movement.
Code:
//jumping
    if( key[KEY_LCONTROL] || key[KEY_RCONTROL] ) {
        if( !key_control )
            if( !falling ) {
                onground = false;
                jumping = true;
            }
        key_control = true;
    }
    if( !key[KEY_LCONTROL] && !key[KEY_RCONTROL] )
        key_control = false;
    if( !key_control )
        if( jumping ) 
            if( yVel <= -1.5 )
                jump_time = 20;
   
    if( jumping && jump_time < 20 ) {
        jump_time++;
        if( yVel > -3 )
            yVel-=0.15;
    }
    if( jump_time >= 20 ) {
        if( yVel < 0 )
            yVel+=0.15;
        else {
            jumping = false;
            falling = true;
        }
    }
   
    //vertical offset
    y+=yVel;
   
    float yNew = y + yVel;
   
    //collision with the floor/cieling
    while( y != yNew && yVel != 0 ) {
        set_hitbox();
        if( world_collsion( player_hitbox ) ) {
            if( falling && !jumping && !onground ) {
                jump_time = 0;
                onground = true;
                falling = false;
            }
            if( jumping && !falling && !onground ) {
                yVel = 0.15;
                y += 3;
                jump_time = 20;
                falling = true;
                jumping = false;
                break;
            }
            if( onground && !falling && !jumping ) {
                yVel = 0.15;
                y--; break;
            }
            set_hitbox();
        }
        break;
    }

    //falling
    if( falling )
        if( yVel < 3 )
            yVel += 0.15; 

This is where I have had a real hard time. Allegro is different from SDL even though my collision process was translated to suit my hitbox instead of SDL_Rect, but the game moves alot faster even when I set my framerate; it also calculates different on the backend I suppose. Anyways, I have a hard time getting the player to firmly collide the floor or the cieling and fall when there is nothing underneath, it has left me exhausted. I hope someone will be able to help me optimize the way I do my horizontal and vertical collisions. Thanks
____________
#
October 20, 2013, 17:12
DTM
Earthling!
823 posts

I can't really get my head around the code so can't really help there.

But I think you need to isolate all aspects of the game and get each working perfectly one by one.

So don't implement jumping or even left/right wall collisions until you have first gotten ground/falling collisions to work perfectly.

Just start with some test cases; have the character fall from a height onto a surface. With no interaction, nothing else at all happening. And get it so the character can fall from any height and lands perfectly and does not penetrate the ground etc.

Then make it so you can move him on the surface, he moves left/right and can drop off the edge and land correctly on another surface.

etc etc

...

also, maybe try to implement subsequent actions without them interacting at all with existing ones.

Your code is tricky to understand because all the different actions are mixed up together, and has all these flags which are set in one place, tested and modified in other places... it's a recipe for bugs.

e.g.

- Rather than having an "onground" flag that is set by some interaction with the ground, you could have an "IsOnGround()" method which *each time it is called* actually collision checks if a platform is underneath the player. (And doesn't modify any other flags or other nasty confusing things like that which could cause rippling effects and break something elsewhere).

- Rather than having a "falling" flag it makes more sense to determine if the player's Y velocity is such that he is travelling downwards... That's what "falling" is, right? So once again, have a "IsFalling()" method which only checks the Y velocity, and doesn't modify any other flags.

- Try to implement everything using more "physics-ish" approaches so it all happens naturally, rather than having to have special cases and flag checking that get all tangled up.

The point is make it so all these behaviours work entirely independently, and then when you have one working you won't accidentally break the other when adding a new action. And it makes it far easier for others to read and understand the code too.

https://en.wikipedia.org/wiki/ … _programming%29
https://en.wikipedia.org/wiki/ … ion_of_concerns
http://programmers.stackexchan … cerns-to-others

...

then again doing all this may just confuse you even further. But at least the approach of getting it all working bit by bit is good.
____________
:o
#

Message Board > C/C++ > Help with some collisions

Quick reply


You must log in or register to post.
Copyright © 2005 Booleansoup.com
Questions? Comments? Bug reports? Contact us!