Server job assigning logic, submarine movement syncing, submarine collision improvements, spawnpoints in levels

This commit is contained in:
Regalis
2015-07-08 11:37:47 +03:00
parent 3af9b8183b
commit d56f7f3f77
155 changed files with 39772 additions and 261 deletions
@@ -0,0 +1,281 @@
using System;
using System.Collections.Generic;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Common.Decomposition;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
namespace FarseerPhysics.Factories
{
public static class BodyFactory
{
public static Body CreateBody(World world, object userData = null)
{
Body body = new Body(world, null, 0, userData);
return body;
}
public static Body CreateBody(World world, Vector2 position, float rotation = 0, object userData = null)
{
Body body = new Body(world, position, rotation, userData);
return body;
}
public static Body CreateEdge(World world, Vector2 start, Vector2 end, object userData = null)
{
Body body = CreateBody(world);
FixtureFactory.AttachEdge(start, end, body, userData);
return body;
}
public static Body CreateChainShape(World world, Vertices vertices, object userData = null)
{
return CreateChainShape(world, vertices, Vector2.Zero, userData);
}
public static Body CreateChainShape(World world, Vertices vertices, Vector2 position, object userData = null)
{
Body body = CreateBody(world, position);
FixtureFactory.AttachChainShape(vertices, body, userData);
return body;
}
public static Body CreateLoopShape(World world, Vertices vertices, object userData = null)
{
return CreateLoopShape(world, vertices, Vector2.Zero, userData);
}
public static Body CreateLoopShape(World world, Vertices vertices, Vector2 position, object userData = null)
{
Body body = CreateBody(world, position);
FixtureFactory.AttachLoopShape(vertices, body, userData);
return body;
}
public static Body CreateRectangle(World world, float width, float height, float density, object userData = null)
{
return CreateRectangle(world, width, height, density, Vector2.Zero, userData);
}
public static Body CreateRectangle(World world, float width, float height, float density, Vector2 position, object userData = null)
{
if (width <= 0)
throw new ArgumentOutOfRangeException("width", "Width must be more than 0 meters");
if (height <= 0)
throw new ArgumentOutOfRangeException("height", "Height must be more than 0 meters");
Body newBody = CreateBody(world, position);
newBody.UserData = userData;
Vertices rectangleVertices = PolygonTools.CreateRectangle(width / 2, height / 2);
PolygonShape rectangleShape = new PolygonShape(rectangleVertices, density);
newBody.CreateFixture(rectangleShape);
return newBody;
}
public static Body CreateCircle(World world, float radius, float density, object userData = null)
{
return CreateCircle(world, radius, density, Vector2.Zero, userData);
}
public static Body CreateCircle(World world, float radius, float density, Vector2 position, object userData = null)
{
Body body = CreateBody(world, position);
FixtureFactory.AttachCircle(radius, density, body, userData);
return body;
}
public static Body CreateEllipse(World world, float xRadius, float yRadius, int edges, float density, object userData = null)
{
return CreateEllipse(world, xRadius, yRadius, edges, density, Vector2.Zero, userData);
}
public static Body CreateEllipse(World world, float xRadius, float yRadius, int edges, float density,
Vector2 position, object userData = null)
{
Body body = CreateBody(world, position);
FixtureFactory.AttachEllipse(xRadius, yRadius, edges, density, body, userData);
return body;
}
public static Body CreatePolygon(World world, Vertices vertices, float density, object userData = null)
{
return CreatePolygon(world, vertices, density, Vector2.Zero, userData);
}
public static Body CreatePolygon(World world, Vertices vertices, float density, Vector2 position, object userData = null)
{
Body body = CreateBody(world, position);
FixtureFactory.AttachPolygon(vertices, density, body, userData);
return body;
}
public static Body CreateCompoundPolygon(World world, List<Vertices> list, float density, object userData = null)
{
return CreateCompoundPolygon(world, list, density, Vector2.Zero, userData);
}
public static Body CreateCompoundPolygon(World world, List<Vertices> list, float density, Vector2 position, object userData = null)
{
//We create a single body
Body polygonBody = CreateBody(world, position);
FixtureFactory.AttachCompoundPolygon(list, density, polygonBody, userData);
return polygonBody;
}
public static Body CreateGear(World world, float radius, int numberOfTeeth, float tipPercentage, float toothHeight, float density, object userData = null)
{
Vertices gearPolygon = PolygonTools.CreateGear(radius, numberOfTeeth, tipPercentage, toothHeight);
//Gears can in some cases be convex
if (!gearPolygon.IsConvex())
{
//Decompose the gear:
List<Vertices> list = Triangulate.ConvexPartition(gearPolygon, TriangulationAlgorithm.Earclip);
return CreateCompoundPolygon(world, list, density, userData);
}
return CreatePolygon(world, gearPolygon, density, userData);
}
/// <summary>
/// Creates a capsule.
/// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices)
/// </summary>
/// <returns></returns>
public static Body CreateCapsule(World world, float height, float topRadius, int topEdges, float bottomRadius, int bottomEdges, float density, Vector2 position, object userData = null)
{
Vertices verts = PolygonTools.CreateCapsule(height, topRadius, topEdges, bottomRadius, bottomEdges);
Body body;
//There are too many vertices in the capsule. We decompose it.
if (verts.Count >= Settings.MaxPolygonVertices)
{
List<Vertices> vertList = Triangulate.ConvexPartition(verts, TriangulationAlgorithm.Earclip);
body = CreateCompoundPolygon(world, vertList, density, userData);
body.Position = position;
return body;
}
body = CreatePolygon(world, verts, density, userData);
body.Position = position;
return body;
}
public static Body CreateCapsule(World world, float height, float endRadius, float density,
object userData = null)
{
//Create the middle rectangle
Vertices rectangle = PolygonTools.CreateRectangle(endRadius, height / 2);
List<Vertices> list = new List<Vertices>();
list.Add(rectangle);
Body body = CreateCompoundPolygon(world, list, density, userData);
body.UserData = userData;
//Create the two circles
CircleShape topCircle = new CircleShape(endRadius, density);
topCircle.Position = new Vector2(0, height / 2);
body.CreateFixture(topCircle);
CircleShape bottomCircle = new CircleShape(endRadius, density);
bottomCircle.Position = new Vector2(0, -(height / 2));
body.CreateFixture(bottomCircle);
return body;
}
/// <summary>
/// Creates a rounded rectangle.
/// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices)
/// </summary>
/// <param name="world">The world.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="xRadius">The x radius.</param>
/// <param name="yRadius">The y radius.</param>
/// <param name="segments">The segments.</param>
/// <param name="density">The density.</param>
/// <param name="position">The position.</param>
/// <returns></returns>
public static Body CreateRoundedRectangle(World world, float width, float height, float xRadius, float yRadius, int segments, float density, Vector2 position, object userData = null)
{
Vertices verts = PolygonTools.CreateRoundedRectangle(width, height, xRadius, yRadius, segments);
//There are too many vertices in the capsule. We decompose it.
if (verts.Count >= Settings.MaxPolygonVertices)
{
List<Vertices> vertList = Triangulate.ConvexPartition(verts, TriangulationAlgorithm.Earclip);
Body body = CreateCompoundPolygon(world, vertList, density, userData);
body.Position = position;
return body;
}
return CreatePolygon(world, verts, density);
}
public static Body CreateRoundedRectangle(World world, float width, float height, float xRadius, float yRadius, int segments, float density, object userData = null)
{
return CreateRoundedRectangle(world, width, height, xRadius, yRadius, segments, density, Vector2.Zero, userData);
}
public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density)
{
return CreateBreakableBody(world, vertices, density, Vector2.Zero);
}
public static BreakableBody CreateBreakableBody(World world, IEnumerable<Shape> shapes)
{
return CreateBreakableBody(world, shapes, Vector2.Zero);
}
/// <summary>
/// Creates a breakable body. You would want to remove collinear points before using this.
/// </summary>
/// <param name="world">The world.</param>
/// <param name="vertices">The vertices.</param>
/// <param name="density">The density.</param>
/// <param name="position">The position.</param>
/// <returns></returns>
public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density, Vector2 position)
{
List<Vertices> triangles = Triangulate.ConvexPartition(vertices, TriangulationAlgorithm.Earclip);
BreakableBody breakableBody = new BreakableBody(triangles, world, density);
breakableBody.MainBody.Position = position;
world.AddBreakableBody(breakableBody);
return breakableBody;
}
public static BreakableBody CreateBreakableBody(World world, IEnumerable<Shape> shapes, Vector2 position)
{
BreakableBody breakableBody = new BreakableBody(shapes, world);
breakableBody.MainBody.Position = position;
world.AddBreakableBody(breakableBody);
return breakableBody;
}
public static Body CreateLineArc(World world, float radians, int sides, float radius, Vector2 position, float angle, bool closed)
{
Body body = CreateBody(world);
FixtureFactory.AttachLineArc(radians, sides, radius, position, angle, closed, body);
return body;
}
public static Body CreateSolidArc(World world, float density, float radians, int sides, float radius, Vector2 position, float angle)
{
Body body = CreateBody(world);
FixtureFactory.AttachSolidArc(density, radians, sides, radius, position, angle, body);
return body;
}
}
}
@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Common.Decomposition;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
namespace FarseerPhysics.Factories
{
/// <summary>
/// An easy to use factory for creating bodies
/// </summary>
public static class FixtureFactory
{
public static Fixture AttachEdge(Vector2 start, Vector2 end, Body body, object userData = null)
{
EdgeShape edgeShape = new EdgeShape(start, end);
return body.CreateFixture(edgeShape, userData);
}
public static Fixture AttachChainShape(Vertices vertices, Body body, object userData = null)
{
ChainShape shape = new ChainShape(vertices);
return body.CreateFixture(shape, userData);
}
public static Fixture AttachLoopShape(Vertices vertices, Body body, object userData = null)
{
ChainShape shape = new ChainShape(vertices, true);
return body.CreateFixture(shape, userData);
}
public static Fixture AttachRectangle(float width, float height, float density, Vector2 offset, Body body, object userData = null)
{
Vertices rectangleVertices = PolygonTools.CreateRectangle(width / 2, height / 2);
rectangleVertices.Translate(ref offset);
PolygonShape rectangleShape = new PolygonShape(rectangleVertices, density);
return body.CreateFixture(rectangleShape, userData);
}
public static Fixture AttachCircle(float radius, float density, Body body, object userData = null)
{
if (radius <= 0)
throw new ArgumentOutOfRangeException("radius", "Radius must be more than 0 meters");
CircleShape circleShape = new CircleShape(radius, density);
return body.CreateFixture(circleShape, userData);
}
public static Fixture AttachCircle(float radius, float density, Body body, Vector2 offset, object userData = null)
{
if (radius <= 0)
throw new ArgumentOutOfRangeException("radius", "Radius must be more than 0 meters");
CircleShape circleShape = new CircleShape(radius, density);
circleShape.Position = offset;
return body.CreateFixture(circleShape, userData);
}
public static Fixture AttachPolygon(Vertices vertices, float density, Body body, object userData = null)
{
if (vertices.Count <= 1)
throw new ArgumentOutOfRangeException("vertices", "Too few points to be a polygon");
PolygonShape polygon = new PolygonShape(vertices, density);
return body.CreateFixture(polygon, userData);
}
public static Fixture AttachEllipse(float xRadius, float yRadius, int edges, float density, Body body, object userData = null)
{
if (xRadius <= 0)
throw new ArgumentOutOfRangeException("xRadius", "X-radius must be more than 0");
if (yRadius <= 0)
throw new ArgumentOutOfRangeException("yRadius", "Y-radius must be more than 0");
Vertices ellipseVertices = PolygonTools.CreateEllipse(xRadius, yRadius, edges);
PolygonShape polygonShape = new PolygonShape(ellipseVertices, density);
return body.CreateFixture(polygonShape, userData);
}
public static List<Fixture> AttachCompoundPolygon(List<Vertices> list, float density, Body body, object userData = null)
{
List<Fixture> res = new List<Fixture>(list.Count);
//Then we create several fixtures using the body
foreach (Vertices vertices in list)
{
if (vertices.Count == 2)
{
EdgeShape shape = new EdgeShape(vertices[0], vertices[1]);
res.Add(body.CreateFixture(shape, userData));
}
else
{
PolygonShape shape = new PolygonShape(vertices, density);
res.Add(body.CreateFixture(shape, userData));
}
}
return res;
}
public static Fixture AttachLineArc(float radians, int sides, float radius, Vector2 position, float angle, bool closed, Body body)
{
Vertices arc = PolygonTools.CreateArc(radians, sides, radius);
arc.Rotate((MathHelper.Pi - radians) / 2 + angle);
arc.Translate(ref position);
return closed ? AttachLoopShape(arc, body) : AttachChainShape(arc, body);
}
public static List<Fixture> AttachSolidArc(float density, float radians, int sides, float radius, Vector2 position, float angle, Body body)
{
Vertices arc = PolygonTools.CreateArc(radians, sides, radius);
arc.Rotate((MathHelper.Pi - radians) / 2 + angle);
arc.Translate(ref position);
//Close the arc
arc.Add(arc[0]);
List<Vertices> triangles = Triangulate.ConvexPartition(arc, TriangulationAlgorithm.Earclip);
return AttachCompoundPolygon(triangles, density, body);
}
}
}
@@ -0,0 +1,168 @@
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
namespace FarseerPhysics.Factories
{
/// <summary>
/// An easy to use factory for using joints.
/// </summary>
public static class JointFactory
{
#region Motor Joint
public static MotorJoint CreateMotorJoint(World world, Body bodyA, Body bodyB, bool useWorldCoordinates = false)
{
MotorJoint joint = new MotorJoint(bodyA, bodyB, useWorldCoordinates);
world.AddJoint(joint);
return joint;
}
#endregion
#region Revolute Joint
public static RevoluteJoint CreateRevoluteJoint(World world, Body bodyA, Body bodyB, Vector2 anchorA, Vector2 anchorB, bool useWorldCoordinates = false)
{
RevoluteJoint joint = new RevoluteJoint(bodyA, bodyB, anchorA, anchorB, useWorldCoordinates);
world.AddJoint(joint);
return joint;
}
public static RevoluteJoint CreateRevoluteJoint(World world, Body bodyA, Body bodyB, Vector2 anchor)
{
Vector2 localanchorA = bodyA.GetLocalPoint(bodyB.GetWorldPoint(anchor));
RevoluteJoint joint = new RevoluteJoint(bodyA, bodyB, localanchorA, anchor);
world.AddJoint(joint);
return joint;
}
#endregion
#region Rope Joint
public static RopeJoint CreateRopeJoint(World world, Body bodyA, Body bodyB, Vector2 anchorA, Vector2 anchorB, bool useWorldCoordinates = false)
{
RopeJoint ropeJoint = new RopeJoint(bodyA, bodyB, anchorA, anchorB, useWorldCoordinates);
world.AddJoint(ropeJoint);
return ropeJoint;
}
#endregion
#region Weld Joint
public static WeldJoint CreateWeldJoint(World world, Body bodyA, Body bodyB, Vector2 anchorA, Vector2 anchorB, bool useWorldCoordinates = false)
{
WeldJoint weldJoint = new WeldJoint(bodyA, bodyB, anchorA, anchorB, useWorldCoordinates);
world.AddJoint(weldJoint);
return weldJoint;
}
#endregion
#region Prismatic Joint
public static PrismaticJoint CreatePrismaticJoint(World world, Body bodyA, Body bodyB, Vector2 anchor, Vector2 axis, bool useWorldCoordinates = false)
{
PrismaticJoint joint = new PrismaticJoint(bodyA, bodyB, anchor, axis, useWorldCoordinates);
world.AddJoint(joint);
return joint;
}
#endregion
#region Wheel Joint
public static WheelJoint CreateWheelJoint(World world, Body bodyA, Body bodyB, Vector2 anchor, Vector2 axis, bool useWorldCoordinates = false)
{
WheelJoint joint = new WheelJoint(bodyA, bodyB, anchor, axis, useWorldCoordinates);
world.AddJoint(joint);
return joint;
}
public static WheelJoint CreateWheelJoint(World world, Body bodyA, Body bodyB, Vector2 axis)
{
return CreateWheelJoint(world, bodyA, bodyB, Vector2.Zero, axis);
}
#endregion
#region Angle Joint
public static AngleJoint CreateAngleJoint(World world, Body bodyA, Body bodyB)
{
AngleJoint angleJoint = new AngleJoint(bodyA, bodyB);
world.AddJoint(angleJoint);
return angleJoint;
}
#endregion
#region Distance Joint
public static DistanceJoint CreateDistanceJoint(World world, Body bodyA, Body bodyB, Vector2 anchorA, Vector2 anchorB, bool useWorldCoordinates = false)
{
DistanceJoint distanceJoint = new DistanceJoint(bodyA, bodyB, anchorA, anchorB, useWorldCoordinates);
world.AddJoint(distanceJoint);
return distanceJoint;
}
public static DistanceJoint CreateDistanceJoint(World world, Body bodyA, Body bodyB)
{
return CreateDistanceJoint(world, bodyA, bodyB, Vector2.Zero, Vector2.Zero);
}
#endregion
#region Friction Joint
public static FrictionJoint CreateFrictionJoint(World world, Body bodyA, Body bodyB, Vector2 anchor, bool useWorldCoordinates = false)
{
FrictionJoint frictionJoint = new FrictionJoint(bodyA, bodyB, anchor, useWorldCoordinates);
world.AddJoint(frictionJoint);
return frictionJoint;
}
public static FrictionJoint CreateFrictionJoint(World world, Body bodyA, Body bodyB)
{
return CreateFrictionJoint(world, bodyA, bodyB, Vector2.Zero);
}
#endregion
#region Gear Joint
public static GearJoint CreateGearJoint(World world, Body bodyA, Body bodyB, Joint jointA, Joint jointB, float ratio)
{
GearJoint gearJoint = new GearJoint(bodyA, bodyB, jointA, jointB, ratio);
world.AddJoint(gearJoint);
return gearJoint;
}
#endregion
#region Pulley Joint
public static PulleyJoint CreatePulleyJoint(World world, Body bodyA, Body bodyB, Vector2 anchorA, Vector2 anchorB, Vector2 worldAnchorA, Vector2 worldAnchorB, float ratio, bool useWorldCoordinates = false)
{
PulleyJoint pulleyJoint = new PulleyJoint(bodyA, bodyB, anchorA, anchorB, worldAnchorA, worldAnchorB, ratio, useWorldCoordinates);
world.AddJoint(pulleyJoint);
return pulleyJoint;
}
#endregion
#region MouseJoint
public static FixedMouseJoint CreateFixedMouseJoint(World world, Body body, Vector2 worldAnchor)
{
FixedMouseJoint joint = new FixedMouseJoint(body, worldAnchor);
world.AddJoint(joint);
return joint;
}
#endregion
}
}
@@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.Diagnostics;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
namespace FarseerPhysics.Factories
{
public static class LinkFactory
{
/// <summary>
/// Creates a chain.
/// </summary>
/// <param name="world">The world.</param>
/// <param name="start">The start.</param>
/// <param name="end">The end.</param>
/// <param name="linkWidth">The width.</param>
/// <param name="linkHeight">The height.</param>
/// <param name="numberOfLinks">The number of links.</param>
/// <param name="linkDensity">The link density.</param>
/// <param name="attachRopeJoint">Creates a rope joint between start and end. This enforces the length of the rope. Said in another way: it makes the rope less bouncy.</param>
/// <returns></returns>
public static Path CreateChain(World world, Vector2 start, Vector2 end, float linkWidth, float linkHeight, int numberOfLinks, float linkDensity, bool attachRopeJoint)
{
Debug.Assert(numberOfLinks >= 2);
//Chain start / end
Path path = new Path();
path.Add(start);
path.Add(end);
//A single chainlink
PolygonShape shape = new PolygonShape(PolygonTools.CreateRectangle(linkWidth, linkHeight), linkDensity);
//Use PathManager to create all the chainlinks based on the chainlink created before.
List<Body> chainLinks = PathManager.EvenlyDistributeShapesAlongPath(world, path, shape, BodyType.Dynamic, numberOfLinks);
//TODO
//if (fixStart)
//{
// //Fix the first chainlink to the world
// JointFactory.CreateFixedRevoluteJoint(world, chainLinks[0], new Vector2(0, -(linkHeight / 2)),
// chainLinks[0].Position);
//}
//if (fixEnd)
//{
// //Fix the last chainlink to the world
// JointFactory.CreateFixedRevoluteJoint(world, chainLinks[chainLinks.Count - 1],
// new Vector2(0, (linkHeight / 2)),
// chainLinks[chainLinks.Count - 1].Position);
//}
//Attach all the chainlinks together with a revolute joint
PathManager.AttachBodiesWithRevoluteJoint(world, chainLinks, new Vector2(0, -linkHeight), new Vector2(0, linkHeight), false, false);
if (attachRopeJoint)
JointFactory.CreateRopeJoint(world, chainLinks[0], chainLinks[chainLinks.Count - 1], Vector2.Zero, Vector2.Zero);
return (path);
}
}
}