// Attempt to dodge a collision. private bool PerformCollisionDodge(Entity entity, int direction, object solidObject, Rectangle2F solidBox) { // Only dodge if moving perpendicular to the edge. int axis = Directions.ToAxis(direction); if (Math.Abs(entity.Physics.Velocity[1 - axis]) > 0.001f) return false; // Can't dodge moving tiles. if ((solidObject is Tile) && ((Tile) solidObject).IsMoving) return false; Rectangle2F entityBox = entity.Physics.PositionedCollisionBox; float penetrationDistance = GetClipPenetration( entity.Physics.PositionedCollisionBox, solidBox, direction); // Check dodging for both edges of the solid object. for (int side = 0; side < 2; side++) { int moveDirection = (direction + (side == 0 ? 1 : 3)) % 4; float distanceToEdge = Math.Abs(entityBox.GetEdge( Directions.Reverse(moveDirection)) - solidBox.GetEdge(moveDirection)); // Check if the distance to the edge is within dodge range. if (distanceToEdge <= entity.Physics.AutoDodgeDistance) { float moveAmount = Math.Min(entity.Physics.AutoDodgeSpeed, distanceToEdge); Vector2F nextPosition = GMath.Round(entity.Position) + (Directions.ToVector(moveDirection) * moveAmount); Vector2F goalPosition = entity.Position + Directions.ToVector(direction) + (Directions.ToVector(moveDirection) * distanceToEdge); // Make sure the entity is not colliding when placed at the solid object's edge. if (!IsCollidingAt(entity, nextPosition, false, direction, penetrationDistance) && !IsCollidingAt(entity, goalPosition, false, direction, penetrationDistance)) { entity.Position += Directions.ToVector(moveDirection) * moveAmount; entity.Physics.CollisionInfo[direction].IsAutoDodged = true; //entity.Physics.MovementCollisions[direction] = false; // TODO: Figure out complications for removing this. return true; } } } return false; }
// Returns true if two rectangles share an edge in the given direction. public static bool AreEdgesAligned(Rectangle2F box1, Rectangle2F box2, int edgeDirection) { return Math.Abs(box1.GetEdge(edgeDirection) - box2.GetEdge(edgeDirection)) < 0.1f; }
private bool PerformCollisionDodge(Rectangle2F block, int direction) { float dodgeDist = autoDodgeDistance; Rectangle2F objBox = Rectangle2F.Translate(collisionBox, entity.Position); Vector2F pos = entity.Position; Vector2F dirVect = Directions.ToVector(direction); for (int side = 0; side < 2; side++) { int moveDir = (direction + (side == 0 ? 1 : 3)) % 4; float distance = Math.Abs(objBox.GetEdge((moveDir + 2) % 4) - block.GetEdge(moveDir)); if (distance <= dodgeDist) { Vector2F checkPos = pos + dirVect + (Directions.ToVector(moveDir) * distance); Vector2F gotoPos = GMath.Round(pos) + Directions.ToVector(moveDir); if (!IsPlaceMeetingSolid(checkPos, collisionBox) && !IsPlaceMeetingSolid(gotoPos, collisionBox)) { entity.Position = gotoPos; return true; } } } return false; }