Sign in to follow this  

Stuck on collision detection/resolution

This topic is 672 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

I hate to ask for help on something so simple, but I've been trying to make my collision resolution code work for two days, and everything I try breaks it. I'm using SFML.NET, and I've been searching for code and resources on how to handle this without any real luck. From what I have so far, it seems if I'm colliding with one thing, it ignores every other entity and just passes right through them until it's not colliding with that first entity, after which it gets stuck in that second entity.

 

The code I have so far is below. The BoundingBoxTest and PixelPerfectTest functions are from a third-party library, I tested them and they work fine, they just return a boolean if it detects a collision. I hope I have provided enough information. Sorry if this is in the wrong section, I didn't see any pinned rules about what topics go where.

        public virtual List<Entity> UpdateCollisionList() {
            List<Entity> lst = new List<Entity>();
            foreach (var elm in Globals.GlobalObjects.ObjectsList) {
                //make sure we're not detecting ourselves, and then do a general
                //bounding box detection before doing the more complex pixel perfect detection.
                if (this.UUID != elm.UUID && Collision.CollisionTester.BoundingBoxTest(this.BoundingBox, elm.BoundingBox)) {
                    lst.Add(elm);
                }
            }
            this.CollidingWith = lst;
            return lst;
        }
        
        public virtual void Move(Direction dir) {
            this.UpdateCollisionList();
            float speed = this.Speed * this.DT;
            //FIXME: this can't handle corners.
            //it seems once we collide with something, we don't collide with
            //anything else, even though the foreach loop should ensure that.
            if (this.CollidingWith.Count > 0) {
                //check if we moved so we can still do collision detection
                bool moved = false;
                foreach (var elm in this.CollidingWith) {
                    if (dir == Direction.LEFT ) { if (moved == false) moved = this.CorrectCollision(elm, -speed, 0); }
                    if (dir == Direction.RIGHT) { if (moved == false) moved = this.CorrectCollision(elm,  speed, 0); }
                    if (dir == Direction.UP   ) { if (moved == false) moved = this.CorrectCollision(elm, 0, -speed); }
                    if (dir == Direction.DOWN ) { if (moved == false) moved = this.CorrectCollision(elm, 0,  speed); }
                }
            } else { //if we're not colliding with anything, don't bother checking collision before walking.
                if (dir == Direction.LEFT ) { this.HorizontalPosition -= speed; }
                if (dir == Direction.RIGHT) { this.HorizontalPosition += speed; }
                if (dir == Direction.UP   ) { this.VerticlePosition   -= speed; }
                if (dir == Direction.DOWN ) { this.VerticlePosition   += speed; }
            }
        }
        
        public virtual bool CorrectCollision(Entity elm, float x, float y) {
            //temporary sprite to see if where we want to go isn't occupied.
            Sprite future = this.BoundingBox;
            float Xpos = this.HorizontalPosition + x;
            float Ypos = this.VerticlePosition + y;
            future.Position = new Vector2f(Xpos, Ypos);
            if (!Collision.CollisionTester.PixelPerfectTest(future, elm.BoundingBox, 0)) {
                this.HorizontalPosition = Xpos;
                this.VerticlePosition = Ypos;
                return true;
            }
            return false;
        }

Share this post


Link to post
Share on other sites

Your direction can only be left, right, up, down, so you won't ever be checking 2 direction, so I guess you can't move diagonally?  That doesn't sound right.  So, it looks like it's only possible you'll can collide with 2 objects next to each other (ie, 2 creates on top of each other while moving right).  

 

This solution looks very incomplete.  Can you describe how you are moving, and the exact situations you have problems?  Also, it'll be helpful to post more code around how you create the BoundingBox that is being compared, and any other supporting code.

 

Finally, you can probably figure this out yourself.  You should have many debug statements in there to help you understand what's going on, or just set a break point on a case where your collision list is 2 or more.  that can help paint a picture of what's really going on.  You should learn to do this so you solve these bugs yourself, and, I promise, you'll have TONS of them as you continue to program, no matter how good you get.

Edited by BeerNutts

Share this post


Link to post
Share on other sites

Hi!

 


Your direction can only be left, right, up, down, so you won't ever be checking 2 direction, so I guess you can't move diagonally?  That doesn't sound right.  So, it looks like it's only possible you'll can collide with 2 objects next to each other (ie, 2 creates on top of each other while moving right).  
 
This solution looks very incomplete.  Can you describe how you are moving, and the exact situations you have problems?  Also, it'll be helpful to post more code around how you create the BoundingBox that is being compared, and any other supporting code.

 

Diagonal movement is possible. If two non-conflicting keys are pressed, then the character walks both those ways, e.g. they go one direction and then another, giving the illusion of diagonal movement. The BoundingBox is just an SFML sprite, so it has it's own X and Y value stored in it (A vector of floats with an X and Y value, stored in a Position member). Right now the BoundingBox is just the player sprite, but I separated that so in the future I can have a collision box different from the visible sprite.

Speaking of the BoundingBox, I'll be honest, I have no idea how my code let me get away with it, but I don't see it being set anywhere. Though, adding code to set it didn't fix the problem. I just added "this.BoundingBox.Position = new Vector2f(this.HorizontalPosition, this.VerticlePosition);" to the very top of the Move function, still nothing.

 

My problem is, if I have an entity below me, and one to the left, if I collide with the one below me, I can't go down anymore, but I can move side-to-side, which is intended. But if I keep moving to the left, then I'll be able to go through the sprite on the left, and I can keep moving through it until I stop touching the sprite below me, in which collision for the sprite on the left finally kicks in and I get stuck in it. This happens in any direction, as long as I touch one side of a sprite and move into another I won't collide with it.

 


Finally, you can probably figure this out yourself.  You should have many debug statements in there to help you understand what's going on, or just set a break point on a case where your collision list is 2 or more.  that can help paint a picture of what's really going on.  You should learn to do this so you solve these bugs yourself, and, I promise, you'll have TONS of them as you continue to program, no matter how good you get.

 

Believe me, I know I'm horrible! Haha. I'm trying to figure this out as I type this, and I've been at it for days now. I should probably just give it a rest and work on another part of the engine, but this is just gnawing at me way too much.

 

I almost feel if my solution is a little abstract. I'm almost at the point of scrapping this altogether, but I really wanted to see if anyone here was wise enough to let me know if it's savable.

Share this post


Link to post
Share on other sites


Diagonal movement is possible. If two non-conflicting keys are pressed, then the character walks both those ways

 

I meant, you can't check collisions in both directions if you're moving diagonal.  You have a variable "dir" which can only be set to left, right, up or down, so, if you're moving up and right, you can only check the collision with either up or right, not both.  that needs ot be fixed.  The easier way is to remove the dir variable all together, and just use your X and Y speed to determine which way your character is moving, so, if X is positive it's moving right, and if Y is positive, it's moving down as well.

 

Also, you need to remove the "moved" variable: If you collide with something, you are setting the moved variable to true, and that stops all other collision corrections.  This is what actually sounds like your problem, combined with the dir variable.

Share this post


Link to post
Share on other sites

This topic is 672 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this