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); }
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); }
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); }
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); }
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); }
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); }