碰撞检测,玩家纠正

时间:2012-03-11 06:40:37

标签: c# collision-detection

我在碰撞检测方面遇到了一些问题,除了自己的玩家外,还有2种类型的物体。 Tiles和我称之为MapObjects。

瓷砖都是16x16,其中MapObjects可以是任何一个,但我的问题是它们也是16x16。

当我的播放器运行时,mapobjects或者tile会让它变得非常麻烦。玩家无法向右移动,向左移动时会向前弯曲。

我发现了问题,那就是我的碰撞检测会在侧面碰撞物体时向左/向右移动,如果从上/下碰撞,则向上/向下移动。

现在想象我的玩家在2,12个牌上,在10,12和11,12,并且玩家主要站在11,12牌上。碰撞检测将首先在10,12瓦上运行,它计算碰撞深度,并发现它是侧面的碰撞,因此更多的是右侧的物体。之后它会用11,12进行碰撞检测,这样它会移动角色。因此,玩家不会摔倒,但无法向右移动。当向左移动时,同样的问题会让玩家变形。

这个问题一直困扰着我几天,而我却找不到解决方案!

这是我的代码,用于检测碰撞。

 public void ApplyObjectCollision(IPhysicsObject obj, List<IComponent> mapObjects, TileMap map)
        {
            PhysicsVaraibales physicsVars = GetPhysicsVariables();
            Rectangle bounds = ((IComponent)obj).GetBound();
            int leftTile = (int)Math.Floor((float)bounds.Left / map.GetTileSize());
            int rightTile = (int)Math.Ceiling(((float)bounds.Right / map.GetTileSize())) - 1;
            int topTile = (int)Math.Floor((float)bounds.Top / map.GetTileSize());
            int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / map.GetTileSize())) - 1;

            // Reset flag to search for ground collision.
            obj.IsOnGround = false;

            // For each potentially colliding tile,
            for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    IComponent tile = map.Get(x, y);
                    if (tile != null)
                    {
                        bounds = HandelCollision(obj, tile, bounds, physicsVars);
                    }
                }
            }

            // Handel collision for all Moving objects
            foreach (IComponent mo in mapObjects)
            {
                if (mo == obj)
                    continue;

                if (mo.GetBound().Intersects(((IComponent)obj).GetBound()))
                {
                    bounds = HandelCollision(obj, mo, bounds, physicsVars);
                }
            }
        }
        private Rectangle HandelCollision(IPhysicsObject obj, IComponent objb, Rectangle bounds, PhysicsVaraibales physicsVars)
        {
            // If this tile is collidable,
            SpriteCollision collision = ((IComponent)objb).GetCollisionType();

            if (collision != SpriteCollision.Passable)
            {
                // Determine collision depth (with direction) and magnitude.
                Rectangle tileBounds = ((IComponent)objb).GetBound();
                Vector2 depth = bounds.GetIntersectionDepth(tileBounds);
                if (depth != Vector2.Zero)
                {
                    float absDepthX = Math.Abs(depth.X);
                    float absDepthY = Math.Abs(depth.Y);

                    // Resolve the collision along the shallow axis.
                    if (absDepthY <= absDepthX || collision == SpriteCollision.Platform)
                    {
                        // If we crossed the top of a tile, we are on the ground.
                        if (obj.PreviousBound.Bottom <= tileBounds.Top)
                            obj.IsOnGround = true;

                        // Ignore platforms, unless we are on the ground.
                        if (collision == SpriteCollision.Impassable || obj.IsOnGround)
                        {
                            // Resolve the collision along the Y axis.
                            ((IComponent)obj).Position = new Vector2(((IComponent)obj).Position.X, ((IComponent)obj).Position.Y + depth.Y);

                            // If we hit something about us, remove all velosity upwards
                            if (depth.Y > 0 && obj.IsJumping)
                            {
                                obj.Velocity = new Vector2(obj.Velocity.X, 0);
                                obj.JumpTime = physicsVars.MaxJumpTime;
                            }

                            // Perform further collisions with the new bounds.
                            return ((IComponent)obj).GetBound();
                        }
                    }
                    else if (collision == SpriteCollision.Impassable) // Ignore platforms.
                    {
                        // Resolve the collision along the X axis.
                        ((IComponent)obj).Position = new Vector2(((IComponent)obj).Position.X + depth.X, ((IComponent)obj).Position.Y);

                        // Perform further collisions with the new bounds.
                        return ((IComponent)obj).GetBound();
                    }
                }
            }
            return bounds;
        }

0 个答案:

没有答案