Jump to content
  • Advertisement
Sign in to follow this  
Guns Akimbo

Help needed with 2D collision detection bug, please.

This topic is 3963 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, I've got a bug in my 2D collision detection. It uses a black and white image for a collision map and tests the pixels in the player do not overlap collidable parts of the image that are collidable (the black parts) So far its working great with the small problem that if a player collides with the side of an object it "teleports" him downwards to the floor rather than making him fall normaly, so when he jumps and collides with a platforms edge he gets zapped down to the floor again. Collision detection is done by 2 Methods. "private bool Collision(Actor actor)" returns true if any of the players(actors) pixels inside his bounding box area will overlap any black pixels in the collision map image when his velocity is added to his position. And "private bool Fallision(Actor actor)" which is used to check if any of the bottom row of pixels in the players bounding box are currently touching any black pixels. Fallision is needed because the player can fall fast enough that Collision will add his velocity to his position and report a collision when he is far from the ground... Fallision can then be used in a while loop to close the space between the player and the ground before the screen is updated... Which is a bit "hackey" but is releaves a lot of overhead from collision detection when not falling. My problem seems to be that when colliding (i.e the players position + his velocity = a position inside the collidable enviroment) is true and the player is decending (his Y Velocity is posative) then I loop through the falling collision correction with the exact purpose of closing the distance between the player and the floor to zero before a screen update. The problem is then when he hits the side of a platform mid-jump that Collision = True and most of the time he's in the downward arc of his jump so the code will enter the collision correction loop it uses for falling correction and plant the player on the floor in a single frame of animation. Now i'm annoyed because I seem to have designed myself into a corner where the only solution is a complete reworking of the collision detection... so i'm reaching out for some advice working round this "bug"/"design flaw" to save me redesigning my collision. Thanks in advance :) Collision Check Code:
  private bool Collision(Actor actor)
        {
           
            bool Collision = false;
            for (int y = 0; y < actor.BoundingHeight; y++)
            {
                if (Collision) break;
                for (int x = 0; x < actor.BoundingWidth; x++)
                {                  
                   
                        if ((bgCollisionData[(int)((((actor.Position.Y + y + actor.OriginOffset.Y) + actor.Velocity.Y) * BackGroundImage.Width) + (actor.Position.X + x + actor.OriginOffset.X) + actor.Velocity.X)] == Constants.BaseCollideColour && actor.CollisionData[(int)((y * actor.Sprite.Width) + x)] != 0))
                        {
                            Collision = true;
                            break;
                        }
                }
            }
            if (Collision)
                return true;
            else
                return false;
        }
       

Fallision Code:
private bool Fallision(Actor actor)
        {
            List<bool> CanFall = new List<bool>(actor.BoundingWidth);

            for (int x = 0; x < actor.BoundingWidth; x++)
            {
                if ((bgCollisionData[(int)((((actor.Position.Y + actor.BoundingHeight + actor.OriginOffset.Y) + 1) * BackGroundImage.Width) + (actor.Position.X + x + actor.OriginOffset.X))] != Constants.BaseCollideColour))
                {
                    CanFall.Add(true);    //No colliding enviroment beneath actor @ current pixel                

                }
                else
                {
                    CanFall.Add(false);   //Colliding enviroment beneath actor @ current pixel              
                }
            }
            return CanFall.Contains(false);
        }

Background Collision Code:
public void BackGroundCollisionDetection(Actor actor)
        {
            if (actor.Velocity.Y < actor.BoundingHeight && !Fallision(actor))   //Falling mechanism
            {
                actor.Velocity.Y += Constants.Gravity;             
            }

            if (!Collision(actor))     //If actor NOT Colliding
            {
                actor.Colliding = false;
                actor.Position += (actor.Velocity);
            }
            else                        //If actor Colliding
            {            
                if (actor.NormalDirection.Y == 1)   //If Decending
                {
                    while (!Fallision(actor))       //Correction to high velocity fall collision
                    {
                        actor.Position.Y++;
                    }
                                                    //Correction Finished player is touching the floor:
                        actor.Velocity.Y = 0;
                        actor.Grounded = true;
                        actor.Jumping = false;                    
                }
                
                if (actor.NormalDirection.X == 1 || actor.NormalDirection.X == -1)  //If hitting a wall
                {
                    actor.Velocity.X = 0;
                }
                actor.Colliding = true;
            }      
        }   

Share this post


Link to post
Share on other sites
Advertisement
Quote:

Fallision is needed because the player can fall fast enough that Collision will add his velocity to his position and report a collision when he is far from the ground... Fallision can then be used in a while loop to close the space between the player and the ground before the screen is updated... Which is a bit "hackey" but is releaves a lot of overhead from collision detection when not falling.


I don't understand why you would add the players velocity to collision detection. The purpose of collision detection is to detect whether 2 objects are physically colliding and what you're doing is predicting a collision, which is not necessary. What happens if your code detects that you're going to collide with a platform soon (i.e. land on a platform) but before you actually get there the platform (which is in motion) moves out from beneath you?

Anyways, what you want to do is remove this addition of velocity to collision detection. Then, before you move your characters position check to see if it will collide with anything in the direction it is going. If it doesn't collide, perform the move.

Are you trying to simulate your character "falling" rather than have it appear at the ground?

Share this post


Link to post
Share on other sites
First you state that fallison should only be called when collision has been detected at the bottom of the character and yet you call it whenever there is a collison and movement is in the downward direction. You have found a case where collision happens and velocity is downward but the collision didn't happen at the bottom of the object so fallision shouldn't be called and yet it is. you need to calculate on which side of the object the collision occurred so that you can correctly call fallision.

Share this post


Link to post
Share on other sites
@Shake

I use the predictive collision for Player(or enemy, etc) Vs. the enviroment because the enviroment is a static image being used as a collision map... rather than the classic tilemap aproach.

Moving platforms will be treated as collidable animate objects... think of them like enemies you collide with but do no damage.

The predictive aproach means that if a player moves 10 pixels left i need 1 run through a collison check loop rather than 1 run through the loop for each pixel he moves forward.

I found that if i was checking for current collisions then I was checking every time the player moved 1 pixel in any direction... which was horribly slow.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!