using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; namespace TalkingIsAFreeAction { public static class Physics { public const float GRAVITY = 50; public const float MINIMUM_VELOCITY = 10; public const float SLOWDOWN_RATE = 0.75f; public const float EDGE_SLOWDOWN_RATE = 0.99f; private static float lastFrameLength = 0.1f; public static List activePhysicsBodies = new List(); public static List passivePhysicsBodies = new List(); public static void CapSpeed(PhysicsObject current) { if (current.velocityX > -MINIMUM_VELOCITY && current.velocityX < MINIMUM_VELOCITY) current.velocityX = 0; if (current.velocityY > -MINIMUM_VELOCITY && current.velocityY < MINIMUM_VELOCITY) current.velocityY = 0; } public static void TryAccelerateX(PhysicsObject current, float amount) { current.velocityX += amount; //This method got a lot less complicated all of a sudden } public static void ApplyPhysics(float seconds) { lastFrameLength = seconds; for (int i = 0; i < activePhysicsBodies.Count; i++) { PhysicsObject current = activePhysicsBodies[i]; if (current.velocityX > current.maxVelocityX) current.velocityX = current.maxVelocityX; if (current.velocityX < -current.maxVelocityX) current.velocityX = -current.maxVelocityX; if (current.velocityY > current.maxVelocityY) current.velocityY = current.maxVelocityY; float targetX = current.x + current.velocityX * seconds; float targetY = current.y + current.velocityY * seconds; float reductionFactor = 0.9f; //Check for collisions for (int ii = 0; ii < passivePhysicsBodies.Count; ii++) { PhysicsObject other = passivePhysicsBodies[ii]; Vector2 collision; bool colliding = true; while (colliding) { colliding = false; //Horizontal collision = Util.CalculateCollision(targetX, current.y, current.width, current.height, other.x, other.y, other.width, other.height); if (collision.X > 0 && collision.Y > 0) { current.velocityX *= reductionFactor; colliding = true; } //Vertical collision = Util.CalculateCollision(current.x, targetY, current.width, current.height, other.x, other.y, other.width, other.height); if (collision.X > 0 && collision.Y > 0) { current.velocityY *= reductionFactor; colliding = true; } //Recalculate if velocity was modified if (colliding) { CapSpeed(current); targetX = current.x + current.velocityX * seconds; targetY = current.y + current.velocityY * seconds; } } } current.ApplyNewPosition(targetX, targetY); //Apply gravity if (!Main.climbing) { if (current.velocityY <= GRAVITY) current.velocityY += GRAVITY; else current.velocityY *= 1f + (5f * seconds); //Check if standing on ground for (int ii = 0; ii < passivePhysicsBodies.Count; ii++) { PhysicsObject other = passivePhysicsBodies[ii]; if (Util.CheckCollision(current.x, (current.y + 1), current.width, current.height, other.x, other.y, other.width, other.height)) { current.onGroundTimer += seconds; } } } } } public static bool CheckIfPassable(float x, float y, float width, float height) { for (int i = 0; i < passivePhysicsBodies.Count; i++) { PhysicsObject other = passivePhysicsBodies[i]; //If it collides... if (Util.CheckCollision(x, y, width, height, other.x, other.y, other.width, other.height)) { return false; } } return true; } } }