123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- using System;
- using System.Collections.Generic;
- using FarseerPhysics.Collision.Shapes;
- using FarseerPhysics.Common;
- using FarseerPhysics.Common.Decomposition;
- using FarseerPhysics.Dynamics;
- using FarseerPhysics.Dynamics.Joints;
- using Microsoft.Xna.Framework;
- namespace FarseerPhysics.Factories
- {
- /// <summary>
- /// An easy to use manager for creating paths.
- /// </summary>
- public static class PathManager
- {
- #region LinkType enum
- public enum LinkType
- {
- Revolute,
- Slider
- }
- #endregion
- //Contributed by Matthew Bettcher
- /// <summary>
- /// Convert a path into a set of edges and attaches them to the specified body.
- /// Note: use only for static edges.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="body">The body.</param>
- /// <param name="subdivisions">The subdivisions.</param>
- public static void ConvertPathToEdges(Path path, Body body, int subdivisions)
- {
- Vertices verts = path.GetVertices(subdivisions);
- if (path.Closed)
- {
- LoopShape loop = new LoopShape(verts);
- body.CreateFixture(loop);
- }
- else
- {
- for (int i = 1; i < verts.Count; i++)
- {
- body.CreateFixture(new EdgeShape(verts[i], verts[i - 1]));
- }
- }
- }
- /// <summary>
- /// Convert a closed path into a polygon.
- /// Convex decomposition is automatically performed.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="body">The body.</param>
- /// <param name="density">The density.</param>
- /// <param name="subdivisions">The subdivisions.</param>
- public static void ConvertPathToPolygon(Path path, Body body, float density, int subdivisions)
- {
- if (!path.Closed)
- throw new Exception("The path must be closed to convert to a polygon.");
- List<Vector2> verts = path.GetVertices(subdivisions);
- List<Vertices> decomposedVerts = EarclipDecomposer.ConvexPartition(new Vertices(verts));
- //List<Vertices> decomposedVerts = BayazitDecomposer.ConvexPartition(new Vertices(verts));
- foreach (Vertices item in decomposedVerts)
- {
- body.CreateFixture(new PolygonShape(item, density));
- }
- }
- /// <summary>
- /// Duplicates the given Body along the given path for approximatly the given copies.
- /// </summary>
- /// <param name="world">The world.</param>
- /// <param name="path">The path.</param>
- /// <param name="shapes">The shapes.</param>
- /// <param name="type">The type.</param>
- /// <param name="copies">The copies.</param>
- /// <param name="userData"></param>
- /// <returns></returns>
- public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, IEnumerable<Shape> shapes,
- BodyType type, int copies, object userData)
- {
- List<Vector3> centers = path.SubdivideEvenly(copies);
- List<Body> bodyList = new List<Body>();
- for (int i = 0; i < centers.Count; i++)
- {
- Body b = new Body(world);
- // copy the type from original body
- b.BodyType = type;
- b.Position = new Vector2(centers[i].X, centers[i].Y);
- b.Rotation = centers[i].Z;
- foreach (Shape shape in shapes)
- {
- b.CreateFixture(shape, userData);
- }
- bodyList.Add(b);
- }
- return bodyList;
- }
- public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, IEnumerable<Shape> shapes,
- BodyType type, int copies)
- {
- return EvenlyDistributeShapesAlongPath(world, path, shapes, type, copies, null);
- }
- /// <summary>
- /// Duplicates the given Body along the given path for approximatly the given copies.
- /// </summary>
- /// <param name="world">The world.</param>
- /// <param name="path">The path.</param>
- /// <param name="shape">The shape.</param>
- /// <param name="type">The type.</param>
- /// <param name="copies">The copies.</param>
- /// <param name="userData">The user data.</param>
- /// <returns></returns>
- public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type,
- int copies, object userData)
- {
- List<Shape> shapes = new List<Shape>(1);
- shapes.Add(shape);
- return EvenlyDistributeShapesAlongPath(world, path, shapes, type, copies, userData);
- }
- public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type,
- int copies)
- {
- return EvenlyDistributeShapesAlongPath(world, path, shape, type, copies, null);
- }
- //TODO: Comment better
- /// <summary>
- /// Moves the body on the path.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="body">The body.</param>
- /// <param name="time">The time.</param>
- /// <param name="strength">The strength.</param>
- /// <param name="timeStep">The time step.</param>
- public static void MoveBodyOnPath(Path path, Body body, float time, float strength, float timeStep)
- {
- Vector2 destination = path.GetPosition(time);
- Vector2 positionDelta = body.Position - destination;
- Vector2 velocity = (positionDelta / timeStep) * strength;
- body.LinearVelocity = -velocity;
- }
- /// <summary>
- /// Attaches the bodies with revolute joints.
- /// </summary>
- /// <param name="world">The world.</param>
- /// <param name="bodies">The bodies.</param>
- /// <param name="localAnchorA">The local anchor A.</param>
- /// <param name="localAnchorB">The local anchor B.</param>
- /// <param name="connectFirstAndLast">if set to <c>true</c> [connect first and last].</param>
- /// <param name="collideConnected">if set to <c>true</c> [collide connected].</param>
- public static List<RevoluteJoint> AttachBodiesWithRevoluteJoint(World world, List<Body> bodies,
- Vector2 localAnchorA,
- Vector2 localAnchorB, bool connectFirstAndLast,
- bool collideConnected)
- {
- List<RevoluteJoint> joints = new List<RevoluteJoint>(bodies.Count + 1);
- for (int i = 1; i < bodies.Count; i++)
- {
- RevoluteJoint joint = new RevoluteJoint(bodies[i], bodies[i - 1], localAnchorA, localAnchorB);
- joint.CollideConnected = collideConnected;
- world.AddJoint(joint);
- joints.Add(joint);
- }
- if (connectFirstAndLast)
- {
- RevoluteJoint lastjoint = new RevoluteJoint(bodies[0], bodies[bodies.Count - 1], localAnchorA,
- localAnchorB);
- lastjoint.CollideConnected = collideConnected;
- world.AddJoint(lastjoint);
- joints.Add(lastjoint);
- }
- return joints;
- }
- /// <summary>
- /// Attaches the bodies with revolute joints.
- /// </summary>
- /// <param name="world">The world.</param>
- /// <param name="bodies">The bodies.</param>
- /// <param name="localAnchorA">The local anchor A.</param>
- /// <param name="localAnchorB">The local anchor B.</param>
- /// <param name="connectFirstAndLast">if set to <c>true</c> [connect first and last].</param>
- /// <param name="collideConnected">if set to <c>true</c> [collide connected].</param>
- /// <param name="minLength">Minimum length of the slider joint.</param>
- /// <param name="maxLength">Maximum length of the slider joint.</param>
- /// <returns></returns>
- public static List<SliderJoint> AttachBodiesWithSliderJoint(World world, List<Body> bodies, Vector2 localAnchorA,
- Vector2 localAnchorB, bool connectFirstAndLast,
- bool collideConnected, float minLength,
- float maxLength)
- {
- List<SliderJoint> joints = new List<SliderJoint>(bodies.Count + 1);
- for (int i = 1; i < bodies.Count; i++)
- {
- SliderJoint joint = new SliderJoint(bodies[i], bodies[i - 1], localAnchorA, localAnchorB, minLength,
- maxLength);
- joint.CollideConnected = collideConnected;
- world.AddJoint(joint);
- joints.Add(joint);
- }
- if (connectFirstAndLast)
- {
- SliderJoint lastjoint = new SliderJoint(bodies[0], bodies[bodies.Count - 1], localAnchorA, localAnchorB,
- minLength, maxLength);
- lastjoint.CollideConnected = collideConnected;
- world.AddJoint(lastjoint);
- joints.Add(lastjoint);
- }
- return joints;
- }
- }
- }
|