4
\$\begingroup\$

I am working on a platformer 2D, and i am currently focusing on collision. I have the actual rectangle(class: Rect) and i can detect if the player-model is intersepting it. However, when it comes from the side, that is when the problems appear: i can prevent it from going down after the interseption but i cant prevent it if it intersepts with the edges. how can I make a better collision system?

EDIT:

I have worked a little on a system, but it doesnt work. Help me improve this:

for(Platform p : game.platforms){
            if(Rect.intersects(getBounds(), p.getBounds())){
                coll = true;            
                int px = p.x;
                int py = p.y;
                if((x + 100) >= px  && (x + 100) <= px + 10){
                    x = px - 101;
                    y += 100;
                    Toast.makeText(game.c, "if(x + 100) >= px  && (x + 100) <= px + 10)", Toast.LENGTH_LONG).show();
                } else if(y  <= (py + 1) && y  >= py + p.height + 10){
                    y = 0;
                    Toast.makeText(game.c, "if8y <= (py + 1) && y  >= py + p.height + 10)", Toast.LENGTH_LONG).show();
                } else if(y  >= py ){
                    y = py - 100;
                    Toast.makeText(game.c, "if(y >= py", Toast.LENGTH_LONG).show();
                }
            }
        }
        if(!coll){
            y += 6;

        }else{

            heightJumped = 0;
            canJump = true;
            isInAir = false;
            jumping = false;
        }
        coll = false;
    }
\$\endgroup\$
2
  • \$\begingroup\$ At the first frame where the moving rectangle intersects with a static rectangle, you can move it towards the opposite direction, so that it barely touches the static rectangle and no longer intersects. \$\endgroup\$
    – dimitris93
    Oct 16, 2015 at 17:20
  • \$\begingroup\$ It's about depth resolution. Find the depth intersected on each axis of the rectangle and resolve the smallest depth. There are still problems with that solution. But you should try this first. \$\endgroup\$ Oct 16, 2015 at 19:48

1 Answer 1

1
\$\begingroup\$

This is my perfectly working 2d collision system (C++). Maybe it helps. I have also had the problem with wrong colliding from sides but finally solved it.

So, I have a rectangle of player with 64px width and height.
"posX" and "posY" are its center coordinates.
The parameters of the "colCheck" function are the sides of the rectangle which we want to check if colliding.

float difference = 0; //final difference between player and object (inside)

short Player::colCheck(float left2, float top2, float right2, float bottom2)
{
    short _returnVal = 0;     //Return value
    float left1 = posX-32;    //Player Left
    float right1 = posX+32;   //Player Right
    float top1 = posY-32;     //Player Top
    float bottom1 = posY+32;  //Player Bottom

    if(left1 < right2 && right1 > left2 && top1 < bottom2 && bottom1 > top2)
    {
        if(right1 > left2 && left1 < left2 && right1-left2 < bottom1-top2 && right1-left2 < bottom2-top1)
        {
            difference = right1-left2;
            _returnVal = 1;
            //Player collides from left side of the object
        }
        else if(left1 < right2 && right1 > right2 && right2-left1 < bottom1-top2 && right2-left1 < bottom2-top1)
        {
            difference = right2-left1;
            _returnVal = 2;
           //Player collides from right side of the object
        }
        else if(bottom1 > top2 && top1 < top2)
        {
            difference = bottom1-top2;
            _returnVal = 3;
           //Player collides from top side of the object
        }
        else if(top1 < bottom2 && bottom1 > bottom2)
        {
            difference = bottom2-top1;
            _returnVal = 4;
           //Player collides from bottom side of the object
        }
    }

    return _returnVal;
}

        //Parameter 'cols' (=collisions): cols [index] [side]
        //cols[x][0] -> left side
        //cols[x][1] -> top side
        //cols[x][2] -> right side
        //cols[x][3] -> bottom side
        //Parameter 'size': count of the collisions
        void Player::colReact(std::vector<std::vector<float>> cols, unsigned int size)
        {
            for(unsigned int i = 0; i < size; i++)
            {
                short ret = colCheck(cols[i][0], cols[i][1], cols[i][2], cols[i][3]); //check if collides and get the return value
                if(ret > 0) //if is colliding
                {
                    float changeX; //variable to add to players X coord.
                    float changeY; //variable to add to players Y coord.
                    if(ret == 1) //collides from left
                    {
                        changeX = -difference;
                        changeY = 0;
                    }
                    else if(ret == 2) //collides from right
                    {
                        changeX = difference;
                        changeY = 0;
                    }
                    else if(ret == 3) //collides from top
                    {
                        changeX = 0;
                        changeY = -difference;
                    }
                    else if(ret == 4) //collides from bottom
                    {
                        changeX = 0;
                        changeY = difference;
                    }
                    posX += changeX; //add the -difference value to players x coord.
                    posY += changeY; //add the -difference value to players y coord.
                }
            }
        }

Hope it's a helpful source.

\$\endgroup\$
3
  • \$\begingroup\$ Sorry for a late responce, but could you try to explain the code? I use java so i need to know exactly how it works in order to use it \$\endgroup\$
    – user69046
    Nov 11, 2015 at 20:09
  • \$\begingroup\$ I've commented on their right side. But I repeat it clearly, You have to use the function "colReact(collisions[], collisionCount);" in your update loop. and your player object (as Rectangle) has the position coordinates "posX" and "posY" (They are its center coords.). the function "colCheck(..)" is just the logic side of collision check. It's returns whether it's colliding and at which side of the collision object. And colReact avoids your player to go over of that collision object. If your players (rectangle) width is 64px, then you have to use the same variables like in the func. "colCheck" \$\endgroup\$ Nov 11, 2015 at 21:07
  • \$\begingroup\$ what about colliding with more complex meshes? \$\endgroup\$ Apr 30, 2020 at 7:17

You must log in to answer this question.