Exemplo n.º 1
0
        private static bool GetCollisionPointForTile(
            BallCollision.TileEdges edgesToTest,
            int x,
            int y,
            Vector2 center,
            ref Vector2 closestPointOut,
            ref float distanceSquaredOut)
        {
            Tile tile = Main.tile[x, y];

            if (tile == null || !tile.nactive() || !Main.tileSolid[(int)tile.type] && !Main.tileSolidTop[(int)tile.type] || !Main.tileSolid[(int)tile.type] && Main.tileSolidTop[(int)tile.type] && tile.frameY != (short)0)
            {
                return(false);
            }
            if (Main.tileSolidTop[(int)tile.type])
            {
                edgesToTest &= BallCollision.TileEdges.Top | BallCollision.TileEdges.BottomLeftSlope | BallCollision.TileEdges.BottomRightSlope;
            }
            Vector2     tilePosition = new Vector2((float)x * 16f, (float)y * 16f);
            bool        flag         = false;
            LineSegment edge         = new LineSegment();

            if (BallCollision.GetSlopeEdge(ref edgesToTest, tile, tilePosition, ref edge))
            {
                closestPointOut    = BallCollision.ClosestPointOnLineSegment(center, edge);
                distanceSquaredOut = Vector2.DistanceSquared(closestPointOut, center);
                flag = true;
            }
            if (BallCollision.GetTopOrBottomEdge(edgesToTest, x, y, tilePosition, ref edge))
            {
                Vector2 vector2 = BallCollision.ClosestPointOnLineSegment(center, edge);
                float   num     = Vector2.DistanceSquared(vector2, center);
                if (!flag || (double)num < (double)distanceSquaredOut)
                {
                    distanceSquaredOut = num;
                    closestPointOut    = vector2;
                }
                flag = true;
            }
            if (BallCollision.GetLeftOrRightEdge(edgesToTest, x, y, tilePosition, ref edge))
            {
                Vector2 vector2 = BallCollision.ClosestPointOnLineSegment(center, edge);
                float   num     = Vector2.DistanceSquared(vector2, center);
                if (!flag || (double)num < (double)distanceSquaredOut)
                {
                    distanceSquaredOut = num;
                    closestPointOut    = vector2;
                }
                flag = true;
            }
            return(flag);
        }
Exemplo n.º 2
0
        private static bool GetLeftOrRightEdge(
            BallCollision.TileEdges edgesToTest,
            int x,
            int y,
            Vector2 tilePosition,
            ref LineSegment edge)
        {
            if ((edgesToTest & BallCollision.TileEdges.Left) != BallCollision.TileEdges.None)
            {
                Tile tile1 = Main.tile[x, y];
                Tile tile2 = Main.tile[x - 1, y];
                if ((!BallCollision.IsNeighborSolid(tile2) || tile2.slope() == (byte)1 || tile2.slope() == (byte)3 ? 1 : (!tile2.halfBrick() ? 0 : (!tile1.halfBrick() ? 1 : 0))) == 0)
                {
                    return(false);
                }
                edge.Start = new Vector2(tilePosition.X, tilePosition.Y);
                edge.End   = new Vector2(tilePosition.X, tilePosition.Y + 16f);
                if (tile1.halfBrick())
                {
                    edge.Start.Y += 8f;
                }
                return(true);
            }
            if ((edgesToTest & BallCollision.TileEdges.Right) == BallCollision.TileEdges.None)
            {
                return(false);
            }
            Tile tile3 = Main.tile[x, y];
            Tile tile4 = Main.tile[x + 1, y];

            if ((!BallCollision.IsNeighborSolid(tile4) || tile4.slope() == (byte)2 || tile4.slope() == (byte)4 ? 1 : (!tile4.halfBrick() ? 0 : (!tile3.halfBrick() ? 1 : 0))) == 0)
            {
                return(false);
            }
            edge.Start = new Vector2(tilePosition.X + 16f, tilePosition.Y);
            edge.End   = new Vector2(tilePosition.X + 16f, tilePosition.Y + 16f);
            if (tile3.halfBrick())
            {
                edge.Start.Y += 8f;
            }
            return(true);
        }
Exemplo n.º 3
0
        private static bool CheckForPassThrough(
            Vector2 center,
            out BallPassThroughType type,
            out Tile contactTile)
        {
            Point tileCoordinates = center.ToTileCoordinates();
            Tile  tile            = Main.tile[tileCoordinates.X, tileCoordinates.Y];

            contactTile = tile;
            type        = BallPassThroughType.None;
            if (tile == null)
            {
                return(false);
            }
            if (tile.nactive())
            {
                type = BallPassThroughType.Tile;
                return(BallCollision.IsPositionInsideTile(center, tileCoordinates, tile));
            }
            if (tile.liquid <= (byte)0)
            {
                return(false);
            }
            float num = (float)((double)(tileCoordinates.Y + 1) * 16.0 - (double)tile.liquid / (double)byte.MaxValue * 16.0);

            switch (tile.liquidType())
            {
            case 1:
                type = BallPassThroughType.Lava;
                break;

            case 2:
                type = BallPassThroughType.Honey;
                break;

            default:
                type = BallPassThroughType.Water;
                break;
            }
            return((double)num < (double)center.Y);
        }
Exemplo n.º 4
0
        private static bool GetClosestEdgeToCircle(
            Vector2 position,
            Vector2 size,
            Vector2 velocity,
            out Vector2 collisionPoint,
            out Tile collisionTile)
        {
            Rectangle tileBounds = BallCollision.GetTileBounds(position, size);
            Vector2   center     = position + size * 0.5f;

            BallCollision.TileEdges tileEdges1  = BallCollision.TileEdges.None;
            BallCollision.TileEdges tileEdges2  = (double)velocity.Y >= 0.0 ? tileEdges1 | BallCollision.TileEdges.Top : tileEdges1 | BallCollision.TileEdges.Bottom;
            BallCollision.TileEdges tileEdges3  = (double)velocity.X >= 0.0 ? tileEdges2 | BallCollision.TileEdges.Left : tileEdges2 | BallCollision.TileEdges.Right;
            BallCollision.TileEdges tileEdges4  = (double)velocity.Y <= (double)velocity.X ? tileEdges3 | BallCollision.TileEdges.TopRightSlope : tileEdges3 | BallCollision.TileEdges.BottomLeftSlope;
            BallCollision.TileEdges edgesToTest = (double)velocity.Y <= -(double)velocity.X ? tileEdges4 | BallCollision.TileEdges.TopLeftSlope : tileEdges4 | BallCollision.TileEdges.BottomRightSlope;
            collisionPoint = Vector2.Zero;
            collisionTile  = (Tile)null;
            float   num1               = float.MaxValue;
            Vector2 closestPointOut    = new Vector2();
            float   distanceSquaredOut = 0.0f;

            for (int left = tileBounds.Left; left < tileBounds.Right; ++left)
            {
                for (int top = tileBounds.Top; top < tileBounds.Bottom; ++top)
                {
                    if (BallCollision.GetCollisionPointForTile(edgesToTest, left, top, center, ref closestPointOut, ref distanceSquaredOut) && (double)distanceSquaredOut < (double)num1 && (double)Vector2.Dot(velocity, center - closestPointOut) <= 0.0)
                    {
                        num1           = distanceSquaredOut;
                        collisionPoint = closestPointOut;
                        collisionTile  = Main.tile[left, top];
                    }
                }
            }
            float num2 = size.X / 2f;

            return((double)num1 < (double)num2 * (double)num2);
        }
Exemplo n.º 5
0
        private static bool GetTopOrBottomEdge(
            BallCollision.TileEdges edgesToTest,
            int x,
            int y,
            Vector2 tilePosition,
            ref LineSegment edge)
        {
            if ((edgesToTest & BallCollision.TileEdges.Bottom) != BallCollision.TileEdges.None)
            {
                Tile tile = Main.tile[x, y + 1];
                if ((!BallCollision.IsNeighborSolid(tile) || tile.slope() == (byte)1 || tile.slope() == (byte)2 ? 1 : (tile.halfBrick() ? 1 : 0)) == 0)
                {
                    return(false);
                }
                edge.Start = new Vector2(tilePosition.X, tilePosition.Y + 16f);
                edge.End   = new Vector2(tilePosition.X + 16f, tilePosition.Y + 16f);
                return(true);
            }
            if ((edgesToTest & BallCollision.TileEdges.Top) == BallCollision.TileEdges.None)
            {
                return(false);
            }
            Tile tile1 = Main.tile[x, y - 1];

            if ((Main.tile[x, y].halfBrick() || !BallCollision.IsNeighborSolid(tile1) || tile1.slope() == (byte)3 ? 1 : (tile1.slope() == (byte)4 ? 1 : 0)) == 0)
            {
                return(false);
            }
            if (Main.tile[x, y].halfBrick())
            {
                tilePosition.Y += 8f;
            }
            edge.Start = new Vector2(tilePosition.X, tilePosition.Y);
            edge.End   = new Vector2(tilePosition.X + 16f, tilePosition.Y);
            return(true);
        }
Exemplo n.º 6
0
        public static BallStepResult Step(
            PhysicsProperties physicsProperties,
            Entity entity,
            ref float entityAngularVelocity,
            IBallContactListener listener)
        {
            Vector2 position  = entity.position;
            Vector2 velocity1 = entity.velocity;
            Vector2 size      = entity.Size;
            float   num1      = entityAngularVelocity;
            float   num2      = size.X * 0.5f;
            float   num3      = num1 * physicsProperties.Drag;
            Vector2 vector2_1 = velocity1 * physicsProperties.Drag;
            float   num4      = vector2_1.Length();

            if ((double)num4 > 1000.0)
            {
                vector2_1 = 1000f * Vector2.Normalize(vector2_1);
                num4      = 1000f;
            }
            int     num5            = Math.Max(1, (int)Math.Ceiling((double)num4 / 2.0));
            float   timeScale       = 1f / (float)num5;
            Vector2 velocity2       = vector2_1 * timeScale;
            float   angularVelocity = num3 * timeScale;
            float   num6            = physicsProperties.Gravity / (float)(num5 * num5);
            bool    flag            = false;

            for (int index = 0; index < num5; ++index)
            {
                velocity2.Y += num6;
                BallPassThroughType type;
                Tile tile;
                if (BallCollision.CheckForPassThrough(position + size * 0.5f, out type, out tile))
                {
                    if (type == BallPassThroughType.Tile && Main.tileSolid[(int)tile.type] && !Main.tileSolidTop[(int)tile.type])
                    {
                        velocity2       *= 0.0f;
                        angularVelocity *= 0.0f;
                        flag             = true;
                    }
                    else
                    {
                        BallPassThroughEvent passThrough = new BallPassThroughEvent(timeScale, tile, entity, type);
                        listener.OnPassThrough(physicsProperties, ref position, ref velocity2, ref angularVelocity, ref passThrough);
                    }
                }
                position += velocity2;
                if (!BallCollision.IsBallInWorld(position, size))
                {
                    return(BallStepResult.OutOfBounds());
                }
                Vector2 collisionPoint;
                if (BallCollision.GetClosestEdgeToCircle(position, size, velocity2, out collisionPoint, out tile))
                {
                    Vector2 normal = Vector2.Normalize(position + size * 0.5f - collisionPoint);
                    position = collisionPoint + normal * (num2 + 0.0001f) - size * 0.5f;
                    BallCollisionEvent collision = new BallCollisionEvent(timeScale, normal, collisionPoint, tile, entity);
                    flag      = true;
                    velocity2 = Vector2.Reflect(velocity2, collision.Normal);
                    listener.OnCollision(physicsProperties, ref position, ref velocity2, ref collision);
                    angularVelocity = (float)((double)collision.Normal.X * (double)velocity2.Y - (double)collision.Normal.Y * (double)velocity2.X) / num2;
                }
            }
            Vector2        vector2_2      = velocity2 / timeScale;
            float          num7           = angularVelocity / timeScale;
            BallStepResult ballStepResult = BallStepResult.Moving();

            if (flag && (double)vector2_2.X > -0.00999999977648258 && ((double)vector2_2.X < 0.00999999977648258 && (double)vector2_2.Y <= 0.0) && (double)vector2_2.Y > -(double)physicsProperties.Gravity)
            {
                ballStepResult = BallStepResult.Resting();
            }
            entity.position       = position;
            entity.velocity       = vector2_2;
            entityAngularVelocity = num7;
            return(ballStepResult);
        }