(61d00a474) v0.9.7.1
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Contacts;
|
||||
using FarseerPhysics.Common.Decomposition;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of body that supports multiple fixtures that can break apart.
|
||||
/// </summary>
|
||||
public class BreakableBody
|
||||
{
|
||||
public enum BreakableBodyState
|
||||
{
|
||||
Unbroken,
|
||||
ShouldBreak,
|
||||
Broken,
|
||||
}
|
||||
|
||||
private float[] _angularVelocitiesCache = new float[8];
|
||||
private Vector2[] _velocitiesCache = new Vector2[8];
|
||||
|
||||
public List<Fixture> Parts = new List<Fixture>(8);
|
||||
|
||||
public World World { get; private set; }
|
||||
public Body MainBody { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The force needed to break the body apart.
|
||||
/// Default: 500
|
||||
/// </summary>
|
||||
public float Strength = 500.0f;
|
||||
|
||||
public BreakableBodyState State { get; private set; }
|
||||
|
||||
private BreakableBody(World world)
|
||||
{
|
||||
World = world;
|
||||
World.ContactManager.PostSolve += PostSolve;
|
||||
|
||||
State = BreakableBodyState.Unbroken;
|
||||
}
|
||||
|
||||
public BreakableBody(World world, IEnumerable<Vertices> vertices, float density, Vector2 position = new Vector2(), float rotation = 0) : this(world)
|
||||
{
|
||||
MainBody = World.CreateBody(position, rotation, BodyType.Dynamic);
|
||||
|
||||
foreach (Vertices part in vertices)
|
||||
{
|
||||
PolygonShape polygonShape = new PolygonShape(part, density);
|
||||
Fixture fixture = MainBody.CreateFixture(polygonShape);
|
||||
Parts.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
public BreakableBody(World world, IEnumerable<Shape> shapes, Vector2 position = new Vector2(), float rotation = 0) : this(world)
|
||||
{
|
||||
MainBody = World.CreateBody(position, rotation, BodyType.Dynamic);
|
||||
|
||||
foreach (Shape part in shapes)
|
||||
{
|
||||
Fixture fixture = MainBody.CreateFixture(part);
|
||||
Parts.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
public BreakableBody(World world, Vertices vertices, float density, Vector2 position = new Vector2(), float rotation = 0) : this(world)
|
||||
{
|
||||
MainBody = World.CreateBody(position, rotation, BodyType.Dynamic);
|
||||
|
||||
//TODO: Implement a Voronoi diagram algorithm to split up the vertices
|
||||
List<Vertices> triangles = Triangulate.ConvexPartition(vertices, TriangulationAlgorithm.Earclip);
|
||||
|
||||
foreach (Vertices part in triangles)
|
||||
{
|
||||
PolygonShape polygonShape = new PolygonShape(part, density);
|
||||
Fixture fixture = MainBody.CreateFixture(polygonShape);
|
||||
Parts.Add(fixture);
|
||||
}
|
||||
}
|
||||
|
||||
private void PostSolve(Contact contact, ContactVelocityConstraint impulse)
|
||||
{
|
||||
if (State != BreakableBodyState.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.
|
||||
State = BreakableBodyState.ShouldBreak;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
switch (State)
|
||||
{
|
||||
case BreakableBodyState.Unbroken:
|
||||
CacheVelocities();
|
||||
break;
|
||||
case BreakableBodyState.ShouldBreak:
|
||||
Decompose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache velocities to improve movement on breakage.
|
||||
private void CacheVelocities()
|
||||
{
|
||||
//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()
|
||||
{
|
||||
if (State == BreakableBodyState.Broken)
|
||||
throw new InvalidOperationException("BreakableBody is allready broken");
|
||||
|
||||
//Unsubsribe from the PostSolve delegate
|
||||
World.ContactManager.PostSolve -= PostSolve;
|
||||
|
||||
for (int i = 0; i < Parts.Count; i++)
|
||||
{
|
||||
Fixture oldFixture = Parts[i];
|
||||
|
||||
Shape shape = oldFixture.Shape.Clone();
|
||||
object fixtureTag = oldFixture.UserData;
|
||||
|
||||
MainBody.Remove(oldFixture);
|
||||
|
||||
Body body = World.CreateBody(MainBody.Position, MainBody.Rotation, BodyType.Dynamic);
|
||||
body.UserData = MainBody.UserData;
|
||||
|
||||
Fixture newFixture = body.CreateFixture(shape);
|
||||
newFixture.UserData = fixtureTag;
|
||||
Parts[i] = newFixture;
|
||||
|
||||
body.AngularVelocity = _angularVelocitiesCache[i];
|
||||
body.LinearVelocity = _velocitiesCache[i];
|
||||
}
|
||||
|
||||
World.Remove(MainBody);
|
||||
|
||||
State = BreakableBodyState.Broken;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2017 Kastellanos Nikolaos
|
||||
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
[Flags]
|
||||
public enum ControllerCategory
|
||||
{
|
||||
None = 0x00000000,
|
||||
Cat01 = 0x00000001,
|
||||
Cat02 = 0x00000002,
|
||||
Cat03 = 0x00000004,
|
||||
Cat04 = 0x00000008,
|
||||
Cat05 = 0x00000010,
|
||||
Cat06 = 0x00000020,
|
||||
Cat07 = 0x00000040,
|
||||
Cat08 = 0x00000080,
|
||||
Cat09 = 0x00000100,
|
||||
Cat10 = 0x00000200,
|
||||
Cat11 = 0x00000400,
|
||||
Cat12 = 0x00000800,
|
||||
Cat13 = 0x00001000,
|
||||
Cat14 = 0x00002000,
|
||||
Cat15 = 0x00004000,
|
||||
Cat16 = 0x00008000,
|
||||
Cat17 = 0x00010000,
|
||||
Cat18 = 0x00020000,
|
||||
Cat19 = 0x00040000,
|
||||
Cat20 = 0x00080000,
|
||||
Cat21 = 0x00100000,
|
||||
Cat22 = 0x00200000,
|
||||
Cat23 = 0x00400000,
|
||||
Cat24 = 0x00800000,
|
||||
Cat25 = 0x01000000,
|
||||
Cat26 = 0x02000000,
|
||||
Cat27 = 0x04000000,
|
||||
Cat28 = 0x08000000,
|
||||
Cat29 = 0x10000000,
|
||||
Cat30 = 0x20000000,
|
||||
Cat31 = 0x40000000,
|
||||
All = int.MaxValue,
|
||||
}
|
||||
|
||||
public struct ControllerFilter
|
||||
{
|
||||
public ControllerCategory ControllerCategories;
|
||||
|
||||
public ControllerFilter(ControllerCategory controllerCategory)
|
||||
{
|
||||
this.ControllerCategories = controllerCategory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the controller. The controller has no effect on this body.
|
||||
/// </summary>
|
||||
/// <param name="type">The logic type.</param>
|
||||
public void IgnoreController(ControllerCategory category)
|
||||
{
|
||||
ControllerCategories &= ~category;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore the controller. The controller affects this body.
|
||||
/// </summary>
|
||||
/// <param name="category">The logic type.</param>
|
||||
public void RestoreController(ControllerCategory category)
|
||||
{
|
||||
ControllerCategories |= category;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this body ignores the the specified controller.
|
||||
/// </summary>
|
||||
/// <param name="category">The logic type.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the body has the specified flag; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsControllerIgnored(ControllerCategory category)
|
||||
{
|
||||
return (ControllerCategories & category) != category;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
using FarseerPhysics.Dynamics;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
@@ -36,7 +41,7 @@ namespace FarseerPhysics.Common.PhysicsLogic
|
||||
/// <returns></returns>
|
||||
public virtual bool IsActiveOn(Body body)
|
||||
{
|
||||
if (body == null || !body.Enabled || body.IsStatic)
|
||||
if (body == null || !body.Enabled || body.BodyType == BodyType.Static)
|
||||
return false;
|
||||
|
||||
if (body.FixtureList == null)
|
||||
|
||||
@@ -1,66 +1,29 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using FarseerPhysics.Dynamics;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
[Flags]
|
||||
public enum PhysicsLogicType
|
||||
{
|
||||
Explosion = (1 << 0)
|
||||
}
|
||||
|
||||
public struct PhysicsLogicFilter
|
||||
{
|
||||
public PhysicsLogicType ControllerIgnores;
|
||||
|
||||
/// <summary>
|
||||
/// Ignores the controller. The controller has no effect on this body.
|
||||
/// </summary>
|
||||
/// <param name="type">The logic type.</param>
|
||||
public void IgnorePhysicsLogic(PhysicsLogicType type)
|
||||
{
|
||||
ControllerIgnores |= type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore the controller. The controller affects this body.
|
||||
/// </summary>
|
||||
/// <param name="type">The logic type.</param>
|
||||
public void RestorePhysicsLogic(PhysicsLogicType type)
|
||||
{
|
||||
ControllerIgnores &= ~type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this body ignores the the specified controller.
|
||||
/// </summary>
|
||||
/// <param name="type">The logic type.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the body has the specified flag; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsPhysicsLogicIgnored(PhysicsLogicType type)
|
||||
{
|
||||
return (ControllerIgnores & type) == type;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class PhysicsLogic : FilterData
|
||||
{
|
||||
private PhysicsLogicType _type;
|
||||
public World World;
|
||||
public ControllerCategory ControllerCategory = ControllerCategory.Cat01;
|
||||
|
||||
public World World { get; internal set; }
|
||||
|
||||
public PhysicsLogic(World world)
|
||||
{
|
||||
World = world;
|
||||
}
|
||||
public override bool IsActiveOn(Body body)
|
||||
{
|
||||
if (body.PhysicsLogicFilter.IsPhysicsLogicIgnored(_type))
|
||||
if (body.ControllerFilter.IsControllerIgnored(ControllerCategory))
|
||||
return false;
|
||||
|
||||
return base.IsActiveOn(body);
|
||||
}
|
||||
|
||||
public PhysicsLogic(World world, PhysicsLogicType type)
|
||||
{
|
||||
_type = type;
|
||||
World = world;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Collision.Shapes;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
@@ -98,8 +103,7 @@ namespace FarseerPhysics.Common.PhysicsLogic
|
||||
private List<ShapeData> _data = new List<ShapeData>();
|
||||
private RayDataComparer _rdc;
|
||||
|
||||
public RealExplosion(World world)
|
||||
: base(world, PhysicsLogicType.Explosion)
|
||||
public RealExplosion(World world) : base(world)
|
||||
{
|
||||
_rdc = new RayDataComparer();
|
||||
_data = new List<ShapeData>();
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
using System;
|
||||
/* Original source Farseer Physics Engine:
|
||||
* Copyright (c) 2014 Ian Qvist, http://farseerphysics.codeplex.com
|
||||
* Microsoft Permissive License (Ms-PL) v1.1
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.PhysicsLogic
|
||||
{
|
||||
@@ -11,8 +16,7 @@ namespace FarseerPhysics.Common.PhysicsLogic
|
||||
/// </summary>
|
||||
public sealed class SimpleExplosion : PhysicsLogic
|
||||
{
|
||||
public SimpleExplosion(World world)
|
||||
: base(world, PhysicsLogicType.Explosion)
|
||||
public SimpleExplosion(World world): base(world)
|
||||
{
|
||||
Power = 1; //linear
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user