using System.Collections.Generic; using System.Diagnostics; using Microsoft.Xna.Framework; namespace BouncyCatIsBouncy { class Physics { List m_bodies = new List(); PhysicsBody m_primaryBody; public void Add(PhysicsBody obj) { Debug.Assert(obj != null); m_bodies.Add(obj); } public void SetPrimary(PhysicsBody obj) { Debug.Assert(obj != null); m_primaryBody = obj; } public void ClearAllSecondaries() { m_bodies.Clear(); } public void ClearAll() { ClearAllSecondaries(); m_primaryBody = null; } void ResolveCollisions(List collisions) { foreach (var info in collisions) { if (m_primaryBody.CollisionResponseEnable && info.Body.CollisionResponseEnable) { m_primaryBody.Position -= m_primaryBody.Velocity * info.Penetration; m_primaryBody.Velocity = Vector2.Reflect(m_primaryBody.Velocity, info.Normal); m_primaryBody.Position += m_primaryBody.Velocity * info.Penetration; m_primaryBody.Velocity *= info.Body.CoeffRestitution * m_primaryBody.CoeffRestitution; } info.Body.Collision(m_primaryBody); m_primaryBody.Collision(info.Body); } } public void Update(float dt) { if (m_primaryBody != null) { var collidingGeoms = new List(); m_primaryBody.Update(dt); foreach (var geom in m_primaryBody.Geometry) { foreach (var body in m_bodies) { body.Update(dt); foreach (var otherGeom in body.Geometry) { CollisionInfo info = otherGeom.BroadCollides(geom); if (info.Collides) { collidingGeoms.Add(new CollidingInfo() { Body = body, Normal = info.Normal, Penetration = info.Penetration }); } } } } if (collidingGeoms.Count > 0) { ResolveCollisions(collidingGeoms); } } } [Conditional("DEBUG")] public void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch batch) { foreach (var geom in m_primaryBody.Geometry) { Debugging.RadialBBRenderer.Draw(batch, (RadialBB)geom.Bounding); } foreach (var body in m_bodies) { foreach (var geom in body.Geometry) { if (geom.Bounding is OBB) Debugging.OBBRenderer.Draw(batch, (OBB)geom.Bounding); else if (geom.Bounding is RadialBB) Debugging.RadialBBRenderer.Draw(batch, (RadialBB)geom.Bounding); } } } } }