AxiosEngine-old 

AxiosEngine-old Mercurial Source Tree


Root/axios/Dynamics/BreakableBody.cs

using System;
using System.Collections.Generic;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
 
namespace FarseerPhysics.Dynamics
{
    /// <summary>
    /// A type of body that supports multiple fixtures that can break apart.
    /// </summary>
    public class BreakableBody
    {
        public bool Broken;
        public Body MainBody;
        public List<Fixture> Parts = new List<Fixture>(8);
 
        /// <summary>
        /// The force needed to break the body apart.
        /// Default: 500
        /// </summary>
        public float Strength = 500.0f;
 
        private float[] _angularVelocitiesCache = new float[8];
        private bool _break;
        private Vector2[] _velocitiesCache = new Vector2[8];
        private World _world;
 
        public BreakableBody(IEnumerable<Vertices> vertices, World world, float density)
            : this(vertices, world, density, null)
        {
        }
 
        public BreakableBody()
        {
 
        }
 
        public BreakableBody(IEnumerable<Vertices> vertices, World world, float density, object userData)
        {
            _world = world;
            _world.ContactManager.PostSolve += PostSolve;
            MainBody = new Body(_world);
            MainBody.BodyType = BodyType.Dynamic;
 
            foreach (Vertices part in vertices)
            {
                PolygonShape polygonShape = new PolygonShape(part, density);
                Fixture fixture = MainBody.CreateFixture(polygonShape, userData);
                Parts.Add(fixture);
            }
        }
 
        private void PostSolve(Contact contact, ContactConstraint impulse)
        {
            if (!Broken)
            {
                if (Parts.Contains(contact.FixtureA) || Parts.Contains(contact.FixtureB))
                {
                    float maxImpulse = 0.0f;
                    int count = contact.Manifold.PointCount;
 
                    for (int i = 0; i < count; ++i)
                    {
                        maxImpulse = Math.Max(maxImpulse, impulse.Points[i].NormalImpulse);
                    }
 
                    if (maxImpulse > Strength)
                    {
                        // Flag the body for breaking.
                        _break = true;
                    }
                }
            }
        }
 
        public void Update()
        {
            if (_break)
            {
                Decompose();
                Broken = true;
                _break = false;
            }
 
            // Cache velocities to improve movement on breakage.
            if (Broken == false)
            {
                //Enlarge the cache if needed
                if (Parts.Count > _angularVelocitiesCache.Length)
                {
                    _velocitiesCache = new Vector2[Parts.Count];
                    _angularVelocitiesCache = new float[Parts.Count];
                }
 
                //Cache the linear and angular velocities.
                for (int i = 0; i < Parts.Count; i++)
                {
                    _velocitiesCache[i] = Parts[i].Body.LinearVelocity;
                    _angularVelocitiesCache[i] = Parts[i].Body.AngularVelocity;
                }
            }
        }
 
        private void Decompose()
        {
            //Unsubsribe from the PostSolve delegate
            _world.ContactManager.PostSolve -= PostSolve;
 
            for (int i = 0; i < Parts.Count; i++)
            {
                Fixture fixture = Parts[i];
 
                Shape shape = fixture.Shape.Clone();
 
                object userdata = fixture.UserData;
                MainBody.DestroyFixture(fixture);
 
                Body body = BodyFactory.CreateBody(_world);
                body.BodyType = BodyType.Dynamic;
                body.Position = MainBody.Position;
                body.Rotation = MainBody.Rotation;
                body.UserData = MainBody.UserData;
 
                body.CreateFixture(shape, userdata);
 
                body.AngularVelocity = _angularVelocitiesCache[i];
                body.LinearVelocity = _velocitiesCache[i];
            }
 
            _world.RemoveBody(MainBody);
            _world.RemoveBreakableBody(this);
        }
 
        public void Break()
        {
            _break = true;
        }
    }
}
Source at commit ac75dc03ed16 created 12 years 8 days ago.
By Nathan Adams, Adding new extensions

Archive Download this file

Page rendered in 0.94019s using 11 queries.