A prismatic joint. This joint provides one degree of freedom: translation along an axis fixed in bodyA. Relative rotation is prevented. You can use a joint limit to restrict the range of motion and a joint motor to drive the motion or to model joint friction.
상속: Joint
예제 #1
0
        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.Add(joint);
            return(joint);
        }
예제 #2
0
        private PrismaticTest()
        {
            Body ground = BodyFactory.CreateEdge(World, new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f));

            PolygonShape shape = new PolygonShape(5);
            shape.Vertices = PolygonTools.CreateRectangle(2.0f, 0.5f);

            Body body = BodyFactory.CreateBody(World);
            body.BodyType = BodyType.Dynamic;
            body.Position = new Vector2(-10.0f, 10.0f);
            body.Rotation = 0.5f * Settings.Pi;
            body.CreateFixture(shape);

            // Bouncy limit
            Vector2 axis = new Vector2(2.0f, 1.0f);
            axis.Normalize();
            _joint = new PrismaticJoint(ground, body, Vector2.Zero, axis);

            // Non-bouncy limit
            //_joint = new PrismaticJoint(ground, body2, body2.Position, new Vector2(-10.0f, 10.0f), new Vector2(1.0f, 0.0f));

            _joint.MotorSpeed = 5.0f;
            _joint.MaxMotorForce = 1000.0f;
            _joint.MotorEnabled = true;
            _joint.LowerLimit = -10.0f;
            _joint.UpperLimit = 20.0f;
            _joint.LimitEnabled = true;

            World.AddJoint(_joint);
        }
예제 #3
0
        public Paddle(PlayerIndex playerIndex, GameplayManager gm, Vector2 position, float width, float height, float maxTranslation, World world) : base(world) {
            this.playerIndex = playerIndex;
            this.gm = gm;
            this.width = width;
            this.height = height;
            this.maxTranslation = maxTranslation;
            startPos = new Vector2(position.X,position.Y) ;

            body = BodyFactory.CreateRectangle(world, width, height, 1, position);
            body.BodyType = BodyType.Dynamic;
            body.CollidesWith = Category.Cat1 | Category.Cat3;
            body.CollisionCategories = Category.Cat2;
            body.Restitution = 1.0f;
            body.Friction = 0.0f;
            body.UserData = this;

            ground = BodyFactory.CreateRectangle(world, 1, 1, 1);


            joint = JointFactory.CreatePrismaticJoint(world, ground, body, position, new Vector2(1, 0),true);
            joint.LowerLimit = -maxTranslation + width / 2.0f;
            joint.UpperLimit = maxTranslation - width / 2.0f;
            joint.LimitEnabled = true;
            body.LinearDamping = 7.0f;

        }
예제 #4
0
        private PrismaticTest()
        {
            Body ground;
            {
                ground = BodyFactory.CreateBody(World);

                EdgeShape shape3 = new EdgeShape(new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f));
                ground.CreateFixture(shape3);
            }

            PolygonShape shape = new PolygonShape(5);
            shape.SetAsBox(2.0f, 0.5f);

            Body body = BodyFactory.CreateBody(World);
            body.BodyType = BodyType.Dynamic;
            body.Position = new Vector2(0.0f, 10.0f);

            body.CreateFixture(shape);

            _fixedJoint = new FixedPrismaticJoint(body, body.Position, new Vector2(0.5f, 1.0f));
            _fixedJoint.MotorSpeed = 5.0f;
            _fixedJoint.MaxMotorForce = 1000.0f;
            _fixedJoint.MotorEnabled = true;
            _fixedJoint.LowerLimit = -10.0f;
            _fixedJoint.UpperLimit = 20.0f;
            _fixedJoint.LimitEnabled = true;

            World.AddJoint(_fixedJoint);

            PolygonShape shape2 = new PolygonShape(5);
            shape2.SetAsBox(2.0f, 0.5f);

            Body body2 = BodyFactory.CreateBody(World);
            body2.BodyType = BodyType.Dynamic;
            body2.Position = new Vector2(10.0f, 10.0f);

            body2.CreateFixture(shape2);

            _joint = new PrismaticJoint(ground, body2, ground.GetLocalPoint(body2.Position), Vector2.Zero,
                                        new Vector2(0.5f, 1.0f));
            _joint.MotorSpeed = 5.0f;
            _joint.MaxMotorForce = 1000.0f;
            _joint.MotorEnabled = true;
            _joint.LowerLimit = -10.0f;
            _joint.UpperLimit = 20.0f;
            _joint.LimitEnabled = true;

            World.AddJoint(_joint);
        }
	public override void InitJoint ()
	{
		base.InitJoint ();
		
		//Microsoft.Xna.Framework.FVector2 angleV = new Microsoft.Xna.Framework.FVector2(BodyB.PhysicsBody.Position.X - BodyA.PhysicsBody.Position.X, BodyB.PhysicsBody.Position.Y - BodyA.PhysicsBody.Position.Y);
		float ang = Mathf.Atan2(BodyB.PhysicsBody.Position.Y - BodyA.PhysicsBody.Position.Y, BodyB.PhysicsBody.Position.X - BodyA.PhysicsBody.Position.X);
		Microsoft.Xna.Framework.FVector2 angleV = new Microsoft.Xna.Framework.FVector2(Mathf.Cos(ang), Mathf.Sin(ang));
		//angleV.Normalize();
		joint = FarseerPhysics.Factories.JointFactory.CreatePrismaticJoint(FSWorldComponent.PhysicsWorld, 
			BodyA.PhysicsBody, 
			BodyB.PhysicsBody,
			Microsoft.Xna.Framework.FVector2.Zero,
			angleV);
		joint.CollideConnected = CollideConnected;
		//joint.Frequency = Frequency;
		//joint.DampingRatio = 0.5f; d
	}
예제 #6
0
        private BodyTypesTest()
        {
            //Ground
            Body ground = BodyFactory.CreateEdge(World, new Vector2(-20.0f, 0.0f), new Vector2(20.0f, 0.0f));

            // Define attachment
            {
                _attachment = BodyFactory.CreateRectangle(World, 1, 4, 2);
                _attachment.BodyType = BodyType.Dynamic;
                _attachment.Position = new Vector2(0.0f, 3.0f);
            }

            // Define platform
            {
                _platform = BodyFactory.CreateRectangle(World, 8.0f, 1f, 2);
                _platform.BodyType = BodyType.Dynamic;
                _platform.Position = new Vector2(0.0f, 5.0f);
                _platform.Friction = 0.6f;

                RevoluteJoint rjd = new RevoluteJoint(_attachment, _platform, new Vector2(0, 5), true);
                rjd.MaxMotorTorque = 50.0f;
                rjd.MotorEnabled = true;
                World.AddJoint(rjd);

                PrismaticJoint pjd = new PrismaticJoint(ground, _platform, new Vector2(0.0f, 5.0f), new Vector2(1.0f, 0.0f), true);
                pjd.MaxMotorForce = 1000.0f;
                pjd.MotorEnabled = true;
                pjd.LowerLimit = -10.0f;
                pjd.UpperLimit = 10.0f;
                pjd.LimitEnabled = true;

                World.AddJoint(pjd);

                _speed = 3.0f;
            }

            // Create a payload
            {
                Body body = BodyFactory.CreateRectangle(World, 1.5f, 1.5f, 2);
                body.BodyType = BodyType.Dynamic;
                body.Position = new Vector2(0.0f, 8.0f);
                body.Friction = 0.6f;
            }
        }
예제 #7
0
        /// <summary>
        /// Requires two existing revolute or prismatic joints (any combination will work).
        /// The provided joints must attach a dynamic body to a static body.
        /// </summary>
        /// <param name="jointA">The first joint.</param>
        /// <param name="jointB">The second joint.</param>
        /// <param name="ratio">The ratio.</param>
        public GearJoint(Joint jointA, Joint jointB, float ratio)
            : base(jointA.BodyA, jointA.BodyB)
        {
            JointType = JointType.Gear;
            JointA = jointA;
            JointB = jointB;
            Ratio = ratio;

            JointType type1 = jointA.JointType;
            JointType type2 = jointB.JointType;

            // Make sure its the right kind of joint
            Debug.Assert(type1 == JointType.Revolute ||
                         type1 == JointType.Prismatic ||
                         type1 == JointType.FixedRevolute ||
                         type1 == JointType.FixedPrismatic);
            Debug.Assert(type2 == JointType.Revolute ||
                         type2 == JointType.Prismatic ||
                         type2 == JointType.FixedRevolute ||
                         type2 == JointType.FixedPrismatic);

            // In the case of a prismatic and revolute joint, the first body must be static.
            if (type1 == JointType.Revolute || type1 == JointType.Prismatic)
                Debug.Assert(jointA.BodyA.BodyType == BodyType.Static);
            if (type2 == JointType.Revolute || type2 == JointType.Prismatic)
                Debug.Assert(jointB.BodyA.BodyType == BodyType.Static);

            float coordinate1 = 0.0f, coordinate2 = 0.0f;

            switch (type1)
            {
                case JointType.Revolute:
                    BodyA = jointA.BodyB;
                    _revolute1 = (RevoluteJoint)jointA;
                    LocalAnchor1 = _revolute1.LocalAnchorB;
                    coordinate1 = _revolute1.JointAngle;
                    break;
                case JointType.Prismatic:
                    BodyA = jointA.BodyB;
                    _prismatic1 = (PrismaticJoint)jointA;
                    LocalAnchor1 = _prismatic1.LocalAnchorB;
                    coordinate1 = _prismatic1.JointTranslation;
                    break;
                case JointType.FixedRevolute:
                    BodyA = jointA.BodyA;
                    _fixedRevolute1 = (FixedRevoluteJoint)jointA;
                    LocalAnchor1 = _fixedRevolute1.LocalAnchorA;
                    coordinate1 = _fixedRevolute1.JointAngle;
                    break;
                case JointType.FixedPrismatic:
                    BodyA = jointA.BodyA;
                    _fixedPrismatic1 = (FixedPrismaticJoint)jointA;
                    LocalAnchor1 = _fixedPrismatic1.LocalAnchorA;
                    coordinate1 = _fixedPrismatic1.JointTranslation;
                    break;
            }

            switch (type2)
            {
                case JointType.Revolute:
                    BodyB = jointB.BodyB;
                    _revolute2 = (RevoluteJoint)jointB;
                    LocalAnchor2 = _revolute2.LocalAnchorB;
                    coordinate2 = _revolute2.JointAngle;
                    break;
                case JointType.Prismatic:
                    BodyB = jointB.BodyB;
                    _prismatic2 = (PrismaticJoint)jointB;
                    LocalAnchor2 = _prismatic2.LocalAnchorB;
                    coordinate2 = _prismatic2.JointTranslation;
                    break;
                case JointType.FixedRevolute:
                    BodyB = jointB.BodyA;
                    _fixedRevolute2 = (FixedRevoluteJoint)jointB;
                    LocalAnchor2 = _fixedRevolute2.LocalAnchorA;
                    coordinate2 = _fixedRevolute2.JointAngle;
                    break;
                case JointType.FixedPrismatic:
                    BodyB = jointB.BodyA;
                    _fixedPrismatic2 = (FixedPrismaticJoint)jointB;
                    LocalAnchor2 = _fixedPrismatic2.LocalAnchorA;
                    coordinate2 = _fixedPrismatic2.JointTranslation;
                    break;
            }

            _ant = coordinate1 + Ratio * coordinate2;
        }
예제 #8
0
 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;
 }
예제 #9
0
파일: FSJointDef.cs 프로젝트: prime31/Nez
		public override Joint createJoint()
		{
			var joint = new PrismaticJoint( bodyA, bodyB, ownerBodyAnchor * FSConvert.displayToSim, otherBodyAnchor * FSConvert.displayToSim );
			joint.collideConnected = collideConnected;
			joint.axis = axis;
			joint.limitEnabled = limitEnabled;
			joint.lowerLimit = lowerLimit;
			joint.upperLimit = upperLimit;
			joint.motorEnabled = motorEnabled;
			joint.motorSpeed = motorSpeed;
			joint.maxMotorForce = maxMotorForce;
			joint.motorImpulse = motorImpulse;
			return joint;
		}
예제 #10
0
        private SliderCrankTest()
        {
            Body ground;
            {
                ground = BodyFactory.CreateBody(World);

                EdgeShape shape = new EdgeShape(new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f));
                ground.CreateFixture(shape);
            }

            {
                Body prevBody = ground;

                // Define crank.
                {
                    PolygonShape shape = new PolygonShape(2);
                    shape.Vertices = PolygonTools.CreateRectangle(0.5f, 2.0f);

                    Body body = BodyFactory.CreateBody(World);
                    body.BodyType = BodyType.Dynamic;
                    body.Position = new Vector2(0.0f, 7.0f);

                    body.CreateFixture(shape);

                    _joint1 = new RevoluteJoint(prevBody, body, new Vector2(0f, 5f), true);
                    _joint1.MotorSpeed = 1.0f * Settings.Pi;
                    _joint1.MaxMotorTorque = 10000.0f;
                    _joint1.MotorEnabled = true;
                    World.AddJoint(_joint1);

                    prevBody = body;
                }

                // Define follower.
                {
                    PolygonShape shape = new PolygonShape(2);
                    shape.Vertices = PolygonTools.CreateRectangle(0.5f, 4.0f);

                    Body body = BodyFactory.CreateBody(World);
                    body.BodyType = BodyType.Dynamic;
                    body.Position = new Vector2(0.0f, 13.0f);

                    body.CreateFixture(shape);

                    RevoluteJoint rjd3 = new RevoluteJoint(prevBody, body, new Vector2(0, 9), true);
                    rjd3.MotorEnabled = false;
                    World.AddJoint(rjd3);

                    prevBody = body;
                }

                // Define piston
                {
                    PolygonShape shape = new PolygonShape(2);
                    shape.Vertices = PolygonTools.CreateRectangle(1.5f, 1.5f);

                    Body body = BodyFactory.CreateBody(World);
                    body.BodyType = BodyType.Dynamic;
                    body.Position = new Vector2(0.0f, 17.0f);

                    body.CreateFixture(shape);

                    RevoluteJoint rjd = new RevoluteJoint(prevBody, body, new Vector2(0, 17), true);
                    World.AddJoint(rjd);

                    _joint2 = new PrismaticJoint(ground, body, new Vector2(0.0f, 17.0f), new Vector2(0.0f, 1.0f), true);
                    _joint2.MaxMotorForce = 1000.0f;
                    _joint2.MotorEnabled = true;

                    World.AddJoint(_joint2);
                }

                // Create a payload
                {
                    PolygonShape shape = new PolygonShape(2);
                    shape.Vertices = PolygonTools.CreateRectangle(1.5f, 1.5f);

                    Body body = BodyFactory.CreateBody(World);
                    body.BodyType = BodyType.Dynamic;
                    body.Position = new Vector2(0.0f, 23.0f);

                    body.CreateFixture(shape);
                }
            }
        }
예제 #11
0
 /// <summary>
 /// Creates a prsimatic joint
 /// </summary>
 /// <param name="bodyA"></param>
 /// <param name="bodyB"></param>
 /// <param name="localanchorB"></param>
 /// <param name="axis"></param>
 /// <returns></returns>
 public static PrismaticJoint CreatePrismaticJoint(Body bodyA, Body bodyB, Vector2 localanchorB, Vector2 axis)
 {
     Vector2 localanchorA = bodyA.GetLocalPoint(bodyB.GetWorldPoint(localanchorB));
     PrismaticJoint joint = new PrismaticJoint(bodyA, bodyB, localanchorA, localanchorB, axis);
     return joint;
 }
예제 #12
0
        public Player(Vector2 spawn)
        {
            // To locomote the player, we're going to create a model like this:
            //   +-----+
            //   |     |
            //   |torso|  <-- Rectangle
            //   |/---\|
            //   |legs |  <-- circle
            //    \---/
            // With the torso having a fixed angle joint, and the legs having a motorized joint.
            var torsoWidth = playerWidth + 0.25f;
            var torsoHeight = playerHeight - playerWidth;
            Torso.Body = BodyFactory.CreateRectangle(PhysicsSubsystem.Instance.World, torsoWidth, playerHeight - playerWidth / 4, 0.1f, spawn);
            Torso.Body.IgnoreGravity = true;
            Torso.Body.BodyType = BodyType.Dynamic;
            Torso.Body.FixedRotation = true;
            Torso.Body.Friction = 0;
            Torso.Body.UserData = this;

            Legs.Body = BodyFactory.CreateCircle(PhysicsSubsystem.Instance.World, playerWidth/2, 4f, new Vector2(spawn.X, spawn.Y + torsoHeight / 2 + playerWidth / 4));
            Legs.Body.BodyType = BodyType.Dynamic;
            Legs.Body.Friction = 1000;

            Piston.Body = BodyFactory.CreateRectangle(PhysicsSubsystem.Instance.World, playerWidth, playerHeight / 2,
                                                      0.5f, spawn);
            Piston.Body.BodyType = BodyType.Dynamic;

            axis = JointFactory.CreateRevoluteJoint(PhysicsSubsystem.Instance.World, Torso.Body, Legs.Body, Vector2.Zero);
            axis.CollideConnected = false;
            axis.MotorEnabled = true;
            axis.MaxMotorTorque = 20;

            //prismatic = JointFactory.CreatePrismaticJoint(PhysicsSubsystem.Instance.World, Piston.Body, Torso.Body,
            //                                              Vector2.Zero, -Vector2.UnitY);
            spring = JointFactory.CreateDistanceJoint(PhysicsSubsystem.Instance.World, Piston.Body, Torso.Body);
            spring.Frequency = 10f;
            spring.DampingRatio = 1f;
            spring.CollideConnected = false;

            prismatic = JointFactory.CreatePrismaticJoint(PhysicsSubsystem.Instance.World, Piston.Body, Torso.Body,
                                                          Vector2.Zero, Vector2.UnitY);
            prismatic.CollideConnected = false;
            Piston.Body.IgnoreCollisionWith(Legs.Body);

            Graphics.Sprite = new Sprite(Content.Player);
            Graphics.Animation = standingAnimation;
            Graphics.FrameSize = new Vector2i(64, 64);
            Graphics.Sprite.Origin = new Vector2f(32, 40);

            Slicing = 45;

            bool jumpInProgress = false, canJump = true, attacking = false, canAttack = true; // 1WEEK
            // Map the input to the legs
            Input.NoInput += () =>
                             {
                                 axis.MotorSpeed = 0;
                                 if (!jumpInProgress && !attacking)
                                    Graphics.Animation = standingAnimation;
                             };

            Input.KeyEvents[Keyboard.Key.A] = (key, mods, time) =>
                                           {
                                               if (attacking) return;

                                               if (!jumpInProgress)
                                               {
                                                   axis.MotorSpeed = -playerSpeed;
                                                   Graphics.Animation = walkingAnimation;
                                               }
                                               else
                                                   Legs.Body.ApplyLinearImpulse(new Vector2(-playerAirSpeed * (float)time, 0));

                                               Graphics.Sprite.Scale = new Vector2f(-1, 1); // just flip it
                                           };

            Input.KeyEvents[Keyboard.Key.D] = (key, mods, time) =>
                                           {
                                               if (attacking) return;

                                               if (!jumpInProgress)
                                               {
                                                   axis.MotorSpeed = playerSpeed;
                                                   Graphics.Animation = walkingAnimation;
                                               }
                                               else
                                                   Legs.Body.ApplyLinearImpulse(new Vector2(playerAirSpeed * (float)time, 0));

                                               Graphics.Sprite.Scale = new Vector2f(1, 1); // flip it good
                                           };

            Input.KeyEvents[Keyboard.Key.W] = (key, mods, time) =>
            {
                if (canJump)// && !jumpInProgress && !attacking)
                {
                    jumpInProgress = true;
                    canJump = false;
                    //Legs.Body.ApplyLinearImpulse(new Vector2(0, -playerJumpForce));
                    //Piston.Body.ApplyLinearImpulse(new Vector2(0, -playerJumpForce));
                    spring.Length = playerJumpForce;
                    axis.MotorSpeed = 0;
                    Legs.Body.Friction = 0;
                    jumpTimer.Start();
                    springResetTimer.Start();
                }
            };

            Input.MouseInput += (btn) =>
                                {
                Vector2 mousePos, position, direction, endPos;

                switch (btn)
                {
                    case Mouse.Button.Left:
                        if (!canAttack) break;

                        canAttack = false;
                        Graphics.Animation = jumpInProgress ? vSwingAerialAnimation : vSwingAnimation;
                        axis.MotorSpeed = 0;
                        attacking = true;
                        attackTimer.Start();

                        mousePos = new Vector2(ConvertUnits.ToSimUnits(Input.MousePosition.X),
                            ConvertUnits.ToSimUnits(Input.MousePosition.Y));
                        position = new Vector2(Torso.Position.X, Torso.Position.Y);
                        direction = mousePos - position;
                        direction.Normalize();
                        endPos = position + (direction * 2.5f);

                        PhysicsSubsystem.Instance.World.RayCast((f, p, n, fr) =>
                        {
                            var candy = f.Body.UserData as CandyObject;
                            if (candy != null && candy.HitPoints > 0)
                            {
                                candy.Hit(1, p, direction);
                                return 0;
                            }
                            if (f.Body.UserData is PlatformObject)
                                return 0;
                            return 1;
                        }, position, endPos);

                        break;
                    case Mouse.Button.Middle:
                        break;
                    case Mouse.Button.Right:
                        if (!canAttack || Slicing <= 0) break;

                        canAttack = false;
                        Graphics.Animation = jumpInProgress ? hSwingAerialAnimation : hSwingAnimation;
                        axis.MotorSpeed = 0;
                        attacking = true;
                        attackTimer.Start();

                        mousePos = new Vector2(ConvertUnits.ToSimUnits(Input.MousePosition.X),
                            ConvertUnits.ToSimUnits(Input.MousePosition.Y));
                        position = new Vector2(Torso.Position.X, Torso.Position.Y);
                        direction = mousePos - position;
                        direction.Normalize();
                        direction *= 2.5f;
                        endPos = position + direction;

                        // Find the first thing hit, and if it's a candy, keep track of it.
                        List<Fixture> fixtures = new List<Fixture>();
                        List<Vector2> entryPoints = new List<Vector2>();
                        List<Vector2> exitPoints = new List<Vector2>();

                        //Get the entry points
                        PhysicsSubsystem.Instance.World.RayCast((f, p, n, fr) =>
                                          {
                                              if (f.Body.UserData is PlatformObject)
                                              {
                                                  return 0;
                                              }
                                              if (f.Body.UserData is CandyObject)
                                              {
                                                  fixtures.Add(f);
                                                  entryPoints.Add(p);
                                              }
                                              return 1;
                                          }, position, endPos);
                        if (!entryPoints.Any())
                            return;
                        //Reverse the ray to get the exitpoints
                        PhysicsSubsystem.Instance.World.RayCast((f, p, n, fr) =>
                                          {
                                              if(f.Body.UserData is CandyObject)
                                                  exitPoints.Add(p);
                                              return 1;
                                          }, endPos, position);

                        while (fixtures.Count > exitPoints.Count)
                        {
                            fixtures.Remove(fixtures.Last());
                            entryPoints.Remove(entryPoints.Last());
                        }

                        GameplayState.Score += fixtures.Count * 500;
                        if (fixtures.Count > 0)
                            Content.SliceSound.Play();

                        for (int i = 0; i < fixtures.Count; i++)
                        {
                            if (fixtures[i].Body.Mass < 2.5) continue;
                            var originalCandy = fixtures[i].Body.UserData as CandyObject;
                            Debug.Assert(originalCandy != null);
                            Slicing = Math.Max(Slicing - originalCandy.Physics.Body.Mass, 0);
                            originalCandy.Slice(entryPoints[i], exitPoints[i]);
                        }

                        break;
                }
            };

            #if DEBUG
            Input.KeyEvents[Keyboard.Key.RShift] = (key, mod) => Framework.Graphics.TakeScreenshot();
            #endif

            Torso.OnFalling += (isFalling) =>
            {
                if (isFalling)
                {
                    if (!attacking)
                        Graphics.Animation = fallingAnimation;
                    jumpInProgress = true;
                }
            };

            Legs.Body.OnCollision += (a, b, c) =>
            {
                var userData = (a.Body.UserData ?? b.Body.UserData) as WallObject;
                if (userData == null)
                {
                    jumpInProgress = false;
                    Legs.Body.Friction = c.Friction = 1000;
                    if (!attacking)
                        Graphics.Animation = standingAnimation;
                }
                return true;
            };

            Piston.Body.OnCollision += (a, b, c) =>
                                       {
                                           Graphics.Animation = jumpingAnimation;
                                           Content.JumpSound.Play();
                                           return true;
                                       };

            var swingFinished = new EventHandler((sender, args) =>
                                      {
                                          attacking = false;
                                          Graphics.Animation = jumpInProgress ? aerialAnimation : standingAnimation;
                                      });

            vSwingAnimation.Finished += swingFinished;
            vSwingAerialAnimation.Finished += swingFinished;
            hSwingAnimation.Finished += swingFinished;
            hSwingAerialAnimation.Finished += swingFinished;

            attackTimer.DingDingDing += (sender, args) => canAttack = true;
            jumpTimer.DingDingDing += (sender, args) => canJump = true;
            springResetTimer.DingDingDing += (sender, args) => spring.Length = 0;
        }
예제 #13
0
 /// <summary>
 /// Creates a prismatic joint and adds it to the world
 /// </summary>
 /// <param name="world"></param>
 /// <param name="bodyA"></param>
 /// <param name="bodyB"></param>
 /// <param name="anchor"></param>
 /// <param name="axis"></param>
 /// <returns></returns>
 public static PrismaticJoint CreatePrismaticJoint(World world, Body bodyA, Body bodyB, Vector2 anchor, Vector2 axis)
 {
     PrismaticJoint joint = new PrismaticJoint(bodyA, bodyB, anchor, axis);
     world.AddJoint(joint);
     return joint;
 }
예제 #14
0
        /// <summary>
        /// Requires two existing revolute or prismatic joints (any combination will work).
        /// The provided joints must attach a dynamic body to a static body.
        /// </summary>
        /// <param name="jointA">The first joint.</param>
        /// <param name="jointB">The second joint.</param>
        /// <param name="ratio">The ratio.</param>
        /// <param name="bodyA">The first body</param>
        /// <param name="bodyB">The second body</param>
        public GearJoint(Body bodyA, Body bodyB, Joint jointA, Joint jointB, float ratio = 1f)
        {
            JointType = JointType.Gear;
            BodyA     = bodyA;
            BodyB     = bodyB;
            JointA    = jointA;
            JointB    = jointB;
            Ratio     = ratio;

            _typeA = jointA.JointType;
            _typeB = jointB.JointType;

            Debug.Assert(_typeA == JointType.Revolute || _typeA == JointType.Prismatic || _typeA == JointType.FixedRevolute || _typeA == JointType.FixedPrismatic);
            Debug.Assert(_typeB == JointType.Revolute || _typeB == JointType.Prismatic || _typeB == JointType.FixedRevolute || _typeB == JointType.FixedPrismatic);

            float coordinateA, coordinateB;

            // TODO_ERIN there might be some problem with the joint edges in b2Joint.

            _bodyC = JointA.BodyA;
            _bodyA = JointA.BodyB;

            // Get geometry of joint1
            Transform xfA = _bodyA._xf;
            float     aA  = _bodyA._sweep.A;
            Transform xfC = _bodyC._xf;
            float     aC  = _bodyC._sweep.A;

            if (_typeA == JointType.Revolute)
            {
                RevoluteJoint revolute = (RevoluteJoint)jointA;
                _localAnchorC    = revolute.LocalAnchorA;
                _localAnchorA    = revolute.LocalAnchorB;
                _referenceAngleA = revolute.ReferenceAngle;
                _localAxisC      = Vector2.Zero;

                coordinateA = aA - aC - _referenceAngleA;
            }
            else
            {
                PrismaticJoint prismatic = (PrismaticJoint)jointA;
                _localAnchorC    = prismatic.LocalAnchorA;
                _localAnchorA    = prismatic.LocalAnchorB;
                _referenceAngleA = prismatic.ReferenceAngle;
                _localAxisC      = prismatic.LocalXAxis;

                Vector2 pC = _localAnchorC;
                Vector2 pA = MathUtils.MulT(xfC.q, MathUtils.Mul(xfA.q, _localAnchorA) + (xfA.p - xfC.p));
                coordinateA = Vector2.Dot(pA - pC, _localAxisC);
            }

            _bodyD = JointB.BodyA;
            _bodyB = JointB.BodyB;

            // Get geometry of joint2
            Transform xfB = _bodyB._xf;
            float     aB  = _bodyB._sweep.A;
            Transform xfD = _bodyD._xf;
            float     aD  = _bodyD._sweep.A;

            if (_typeB == JointType.Revolute)
            {
                RevoluteJoint revolute = (RevoluteJoint)jointB;
                _localAnchorD    = revolute.LocalAnchorA;
                _localAnchorB    = revolute.LocalAnchorB;
                _referenceAngleB = revolute.ReferenceAngle;
                _localAxisD      = Vector2.Zero;

                coordinateB = aB - aD - _referenceAngleB;
            }
            else
            {
                PrismaticJoint prismatic = (PrismaticJoint)jointB;
                _localAnchorD    = prismatic.LocalAnchorA;
                _localAnchorB    = prismatic.LocalAnchorB;
                _referenceAngleB = prismatic.ReferenceAngle;
                _localAxisD      = prismatic.LocalXAxis;

                Vector2 pD = _localAnchorD;
                Vector2 pB = MathUtils.MulT(xfD.q, MathUtils.Mul(xfB.q, _localAnchorB) + (xfB.p - xfD.p));
                coordinateB = Vector2.Dot(pB - pD, _localAxisD);
            }

            _ratio    = ratio;
            _constant = coordinateA + _ratio * coordinateB;
            _impulse  = 0.0f;
        }
예제 #15
0
        /// <summary>
        /// Requires two existing revolute or prismatic joints (any combination will work).
        /// The provided joints must attach a dynamic body to a static body.
        /// </summary>
        /// <param name="jointA">The first joint.</param>
        /// <param name="jointB">The second joint.</param>
        /// <param name="ratio">The ratio.</param>
        public GearJoint(Joint jointA, Joint jointB, float ratio)
            : base(jointA.BodyA, jointA.BodyB)
        {
            JointType = JointType.Gear;
            JointA    = jointA;
            JointB    = jointB;
            Ratio     = ratio;

            JointType type1 = jointA.JointType;
            JointType type2 = jointB.JointType;

            // Make sure its the right kind of joint
            Debug.Assert(type1 == JointType.Revolute ||
                         type1 == JointType.Prismatic ||
                         type1 == JointType.FixedRevolute ||
                         type1 == JointType.FixedPrismatic);
            Debug.Assert(type2 == JointType.Revolute ||
                         type2 == JointType.Prismatic ||
                         type2 == JointType.FixedRevolute ||
                         type2 == JointType.FixedPrismatic);

            // In the case of a prismatic and revolute joint, the first body must be static.
            if (type1 == JointType.Revolute || type1 == JointType.Prismatic)
            {
                Debug.Assert(jointA.BodyA.Type == BodyType.Static);
            }
            if (type2 == JointType.Revolute || type2 == JointType.Prismatic)
            {
                Debug.Assert(jointB.BodyA.Type == BodyType.Static);
            }

            float coordinate1 = 0.0f, coordinate2 = 0.0f;

            switch (type1)
            {
            case JointType.Revolute:
                BodyA        = jointA.BodyB;
                _revolute1   = (RevoluteJoint)jointA;
                LocalAnchor1 = _revolute1.LocalAnchorB;
                coordinate1  = _revolute1.JointAngle;
                break;

            case JointType.Prismatic:
                BodyA        = jointA.BodyB;
                _prismatic1  = (PrismaticJoint)jointA;
                LocalAnchor1 = _prismatic1.LocalAnchorB;
                coordinate1  = _prismatic1.JointTranslation;
                break;

            case JointType.FixedRevolute:
                BodyA           = jointA.BodyA;
                _fixedRevolute1 = (FixedRevoluteJoint)jointA;
                LocalAnchor1    = _fixedRevolute1.LocalAnchorA;
                coordinate1     = _fixedRevolute1.JointAngle;
                break;

            case JointType.FixedPrismatic:
                BodyA            = jointA.BodyA;
                _fixedPrismatic1 = (FixedPrismaticJoint)jointA;
                LocalAnchor1     = _fixedPrismatic1.LocalAnchorA;
                coordinate1      = _fixedPrismatic1.JointTranslation;
                break;
            }

            switch (type2)
            {
            case JointType.Revolute:
                BodyB        = jointB.BodyB;
                _revolute2   = (RevoluteJoint)jointB;
                LocalAnchor2 = _revolute2.LocalAnchorB;
                coordinate2  = _revolute2.JointAngle;
                break;

            case JointType.Prismatic:
                BodyB        = jointB.BodyB;
                _prismatic2  = (PrismaticJoint)jointB;
                LocalAnchor2 = _prismatic2.LocalAnchorB;
                coordinate2  = _prismatic2.JointTranslation;
                break;

            case JointType.FixedRevolute:
                BodyB           = jointB.BodyA;
                _fixedRevolute2 = (FixedRevoluteJoint)jointB;
                LocalAnchor2    = _fixedRevolute2.LocalAnchorA;
                coordinate2     = _fixedRevolute2.JointAngle;
                break;

            case JointType.FixedPrismatic:
                BodyB            = jointB.BodyA;
                _fixedPrismatic2 = (FixedPrismaticJoint)jointB;
                LocalAnchor2     = _fixedPrismatic2.LocalAnchorA;
                coordinate2      = _fixedPrismatic2.JointTranslation;
                break;
            }

            _ant = coordinate1 + Ratio * coordinate2;
        }
예제 #16
0
        private void Resize(float scaleFactor) {
            width *= scaleFactor;
            List<Ball> tmpBalls = new List<Ball>();
            while (ballAttachments.Count > 0)
            {
                tmpBalls.Add(ballAttachments[0].BodyB.UserData as Ball);
                world.RemoveJoint(ballAttachments[0]);
                ballAttachments.RemoveAt(0);
            }

            world.RemoveJoint(joint);

            
            Vector2 pos = body.Position;
            Vector2 linearVel = body.LinearVelocity;
            float mass = body.Mass;
            world.RemoveBody(body);
            body = BodyFactory.CreateRectangle(world, width, height, 1, pos);
            body.BodyType = BodyType.Dynamic;
            body.CollidesWith = Category.Cat1 | Category.Cat3;
            body.CollisionCategories = Category.Cat2;
            body.Restitution = 1.0f;
            body.Friction = 0.0f;
            body.UserData = this;
            body.Mass = mass;
            body.LinearVelocity = linearVel;



            joint = JointFactory.CreatePrismaticJoint(world, ground, body, startPos, new Vector2(1, 0), true);
            joint.LowerLimit = -maxTranslation + width / 2.0f + (startPos.X - pos.X);
            joint.UpperLimit = maxTranslation - width / 2.0f + (startPos.X - pos.X);
            joint.LimitEnabled = true;
            body.LinearDamping = 5.0f;

            foreach (Ball b in tmpBalls)
                Attach(b);
        }
예제 #17
0
        public virtual bool OnCollidedWith(Fixture f, UserControlledCharacter character, Fixture charfix, Contact info)
        {
            if (!Hanging && character.Physics.LinearVelocity.Y > 0)
            {
                character.Physics.ResetDynamics();
                character.WheelBody.ResetDynamics();

                joint = JointFactory.CreatePrismaticJoint(
                    world,
                    character.WheelBody,
                    Physics,
                    Vector2.Zero,
                    Vector2.UnitX);

                origLinearDamping = character.Physics.LinearDamping;
                character.Physics.LinearDamping = 10;

                Hanging = true;
            }

            return true;
        }
예제 #18
0
        /// <summary>
        /// Requires two existing revolute or prismatic joints (any combination will work).
        /// The provided joints must attach a dynamic body to a static body.
        /// </summary>
        /// <param name="jointA">The first joint.</param>
        /// <param name="jointB">The second joint.</param>
        /// <param name="ratio">The ratio.</param>
        public GearJoint(FarseerJoint jointA, FarseerJoint jointB, float ratio)
            : base(jointA.BodyA, jointA.BodyB)
        {
            JointType = JointType.Gear;
            JointA    = jointA;
            JointB    = jointB;
            Ratio     = ratio;

            m_typeA = jointA.JointType;
            m_typeB = jointB.JointType;

            // Make sure its the right kind of joint
            Debug.Assert(m_typeA == JointType.Revolute || m_typeA == JointType.Prismatic || m_typeA == JointType.FixedRevolute || m_typeA == JointType.FixedPrismatic);
            Debug.Assert(m_typeB == JointType.Revolute || m_typeB == JointType.Prismatic || m_typeB == JointType.FixedRevolute || m_typeB == JointType.FixedPrismatic);

            float coordinateA = 0.0f, coordinateB = 0.0f;

            m_bodyC = JointA.BodyA;
            BodyA   = JointA.BodyB;

            // Get geometry of joint1
            Transform xfA = BodyA.Xf;
            float     aA  = BodyA.Sweep.A;
            Transform xfC = m_bodyC.Xf;
            float     aC  = m_bodyC.Sweep.A;

            if (m_typeA == JointType.Revolute)
            {
                RevoluteJoint revolute = (RevoluteJoint)jointA;
                m_localAnchorC    = revolute.LocalAnchorA;
                m_localAnchorA    = revolute.LocalAnchorB;
                m_referenceAngleA = revolute.ReferenceAngle;
                m_localAxisC      = FVector2.Zero;

                coordinateA = aA - aC - m_referenceAngleA;
            }
            else
            {
                PrismaticJoint prismatic = (PrismaticJoint)jointA;
                m_localAnchorC    = prismatic.LocalAnchorA;
                m_localAnchorA    = prismatic.LocalAnchorB;
                m_referenceAngleA = prismatic.ReferenceAngle;
                m_localAxisC      = prismatic.LocalXAxisA;

                FVector2 pC = m_localAnchorC;
                FVector2 pA = MathUtils.MulT(xfC.q, MathUtils.Mul(xfA.q, m_localAnchorA) + (xfA.p - xfC.p));
                coordinateA = FVector2.Dot(pA - pC, m_localAxisC);
            }

            m_bodyD = JointB.BodyA;
            BodyB   = JointB.BodyB;

            // Get geometry of joint2
            Transform xfB = BodyB.Xf;
            float     aB  = BodyB.Sweep.A;
            Transform xfD = m_bodyD.Xf;
            float     aD  = m_bodyD.Sweep.A;

            if (m_typeB == JointType.Revolute)
            {
                RevoluteJoint revolute = (RevoluteJoint)jointB;
                m_localAnchorD    = revolute.LocalAnchorA;
                m_localAnchorB    = revolute.LocalAnchorB;
                m_referenceAngleB = revolute.ReferenceAngle;
                m_localAxisD      = FVector2.Zero;

                coordinateB = aB - aD - m_referenceAngleB;
            }
            else
            {
                PrismaticJoint prismatic = (PrismaticJoint)jointB;
                m_localAnchorD    = prismatic.LocalAnchorA;
                m_localAnchorB    = prismatic.LocalAnchorB;
                m_referenceAngleB = prismatic.ReferenceAngle;
                m_localAxisD      = prismatic.LocalXAxisA;

                FVector2 pD = m_localAnchorD;
                FVector2 pB = MathUtils.MulT(xfD.q, MathUtils.Mul(xfB.q, m_localAnchorB) + (xfB.p - xfD.p));
                coordinateB = FVector2.Dot(pB - pD, m_localAxisD);
            }

            _ratio     = ratio;
            m_constant = coordinateA + _ratio * coordinateB;
        }
        private CollisionFilteringTest()
        {
            //Ground
            BodyFactory.CreateEdge(World, new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f));

            {
                // Small triangle
                Vertices vertices = new Vertices(3);
                vertices.Add(new Vector2(-1.0f, 0.0f));
                vertices.Add(new Vector2(1.0f, 0.0f));
                vertices.Add(new Vector2(0.0f, 2.0f));
                PolygonShape polygon = new PolygonShape(vertices, 1);

                Body triangleBody = BodyFactory.CreateBody(World);
                triangleBody.BodyType = BodyType.Dynamic;
                triangleBody.Position = new Vector2(-5.0f, 2.0f);

                Fixture triangleFixture = triangleBody.CreateFixture(polygon);
                triangleFixture.CollisionGroup = SmallGroup;
                triangleFixture.CollisionCategories = TriangleCategory;
                triangleFixture.CollidesWith = TriangleMask;

                // Large triangle (recycle definitions)
                vertices[0] *= 2.0f;
                vertices[1] *= 2.0f;
                vertices[2] *= 2.0f;
                polygon.Set(vertices);

                Body triangleBody2 = BodyFactory.CreateBody(World);
                triangleBody2.BodyType = BodyType.Dynamic;
                triangleBody2.Position = new Vector2(-5.0f, 6.0f);
                triangleBody2.FixedRotation = true; // look at me!

                Fixture triangleFixture2 = triangleBody2.CreateFixture(polygon);
                triangleFixture2.CollisionGroup = LargeGroup;
                triangleFixture2.CollisionCategories = TriangleCategory;
                triangleFixture2.CollidesWith = TriangleMask;

                {
                    Body body = BodyFactory.CreateBody(World);
                    body.BodyType = BodyType.Dynamic;
                    body.Position = new Vector2(-5.0f, 10.0f);

                    Vertices box = PolygonTools.CreateRectangle(0.5f, 1.0f);
                    PolygonShape p = new PolygonShape(box, 1);
                    body.CreateFixture(p);

                    PrismaticJoint jd = new PrismaticJoint(triangleBody2, body,
                                                           triangleBody2.GetLocalPoint(body.Position),
                                                           Vector2.Zero, new Vector2(0.0f, 1.0f));
                    jd.LimitEnabled = true;
                    jd.LowerLimit = -1.0f;
                    jd.UpperLimit = 1.0f;

                    World.AddJoint(jd);
                }

                // Small box
                polygon.SetAsBox(1.0f, 0.5f);

                Body boxBody = BodyFactory.CreateBody(World);
                boxBody.BodyType = BodyType.Dynamic;
                boxBody.Position = new Vector2(0.0f, 2.0f);

                Fixture boxFixture = boxBody.CreateFixture(polygon);
                boxFixture.Restitution = 0.1f;

                boxFixture.CollisionGroup = SmallGroup;
                boxFixture.CollisionCategories = BoxCategory;
                boxFixture.CollidesWith = BoxMask;

                // Large box (recycle definitions)
                polygon.SetAsBox(2, 1);

                Body boxBody2 = BodyFactory.CreateBody(World);
                boxBody2.BodyType = BodyType.Dynamic;
                boxBody2.Position = new Vector2(0.0f, 6.0f);

                Fixture boxFixture2 = boxBody2.CreateFixture(polygon);
                boxFixture2.CollisionGroup = LargeGroup;
                boxFixture2.CollisionCategories = BoxCategory;
                boxFixture2.CollidesWith = BoxMask;

                // Small circle
                CircleShape circle = new CircleShape(1.0f, 1);

                Body circleBody = BodyFactory.CreateBody(World);
                circleBody.BodyType = BodyType.Dynamic;
                circleBody.Position = new Vector2(5.0f, 2.0f);

                Fixture circleFixture = circleBody.CreateFixture(circle);

                circleFixture.CollisionGroup = SmallGroup;
                circleFixture.CollisionCategories = CircleCategory;
                circleFixture.CollidesWith = CircleMask;

                // Large circle
                circle.Radius *= 2.0f;

                Body circleBody2 = BodyFactory.CreateBody(World);
                circleBody2.BodyType = BodyType.Dynamic;
                circleBody2.Position = new Vector2(5.0f, 6.0f);

                Fixture circleFixture2 = circleBody2.CreateFixture(circle);
                circleFixture2.CollisionGroup = LargeGroup;
                circleFixture2.CollisionCategories = CircleCategory;
                circleFixture2.CollidesWith = CircleMask;

                // Large circle - Ignore with other large circle
                Body circleBody3 = BodyFactory.CreateBody(World);
                circleBody3.BodyType = BodyType.Dynamic;
                circleBody3.Position = new Vector2(6.0f, 9.0f);

                //Another large circle. This one uses IgnoreCollisionWith() logic instead of categories.
                Fixture circleFixture3 = circleBody3.CreateFixture(circle);
                circleFixture3.CollisionGroup = LargeGroup;
                circleFixture3.CollisionCategories = CircleCategory;
                circleFixture3.CollidesWith = CircleMask;

                circleFixture3.IgnoreCollisionWith(circleFixture2);
            }
        }
예제 #20
0
        private GearsTest()
        {
            Body ground = BodyFactory.CreateEdge(World, new Vector2(50.0f, 0.0f), new Vector2(-50.0f, 0.0f));

            {
                CircleShape circle1 = new CircleShape(1.0f, 5f);

                PolygonShape box = new PolygonShape(5f);
                box.Vertices = PolygonTools.CreateRectangle(0.5f, 5.0f);

                CircleShape circle2 = new CircleShape(2.0f, 5f);

                Body body1 = BodyFactory.CreateBody(World, new Vector2(10.0f, 9.0f));
                body1.CreateFixture(circle1);

                Body body2 = BodyFactory.CreateBody(World, new Vector2(10.0f, 8.0f));
                body2.BodyType = BodyType.Dynamic;
                body2.CreateFixture(box);

                Body body3 = BodyFactory.CreateBody(World, new Vector2(10.0f, 6.0f));
                body3.BodyType = BodyType.Dynamic;
                body3.CreateFixture(circle2);

                RevoluteJoint joint1 = new RevoluteJoint(body2, body1, body1.Position, true);
                World.AddJoint(joint1);

                RevoluteJoint joint2 = new RevoluteJoint(body2, body3, body3.Position, true);
                World.AddJoint(joint2);

                GearJoint joint4 = new GearJoint(joint1, joint2, circle2.Radius / circle1.Radius);
                joint4.BodyA = body1;
                joint4.BodyB = body3;
                World.AddJoint(joint4);
            }

            {
                CircleShape circle1 = new CircleShape(1.0f, 5.0f);

                CircleShape circle2 = new CircleShape(2.0f, 5.0f);

                PolygonShape box = new PolygonShape(5f);
                box.Vertices = PolygonTools.CreateRectangle(0.5f, 5.0f);

                Body body1 = BodyFactory.CreateBody(World, new Vector2(-3.0f, 12.0f));
                body1.BodyType = BodyType.Dynamic;
                body1.CreateFixture(circle1);

                _joint1 = new RevoluteJoint(ground, body1, body1.Position, true);
                _joint1.ReferenceAngle = body1.Rotation - ground.Rotation;
                World.AddJoint(_joint1);

                Body body2 = BodyFactory.CreateBody(World, new Vector2(0.0f, 12.0f));
                body2.BodyType = BodyType.Dynamic;
                body2.CreateFixture(circle2);

                _joint2 = new RevoluteJoint(ground, body2, body2.Position, true);
                World.AddJoint(_joint2);

                Body body3 = BodyFactory.CreateBody(World, new Vector2(2.5f, 12.0f));
                body3.BodyType = BodyType.Dynamic;
                body3.CreateFixture(box);

                _joint3 = new PrismaticJoint(ground, body3, body3.Position, new Vector2(0.0f, 1.0f));
                _joint3.LowerLimit = -5.0f;
                _joint3.UpperLimit = 5.0f;
                _joint3.LimitEnabled = true;

                World.AddJoint(_joint3);

                _joint4 = new GearJoint(_joint1, _joint2, circle2.Radius / circle1.Radius);
                _joint4.BodyA = body1;
                _joint4.BodyB = body2;
                World.AddJoint(_joint4);

                _joint5 = new GearJoint(_joint2, _joint3, -1.0f / circle2.Radius);
                _joint5.BodyA = body2;
                _joint5.BodyB = body3;
                World.AddJoint(_joint5);
            }
        }
예제 #21
0
        public void Deserialize(World world, Stream stream)
        {
            world.Clear();

            XMLFragmentElement root = XMLFragmentParser.LoadFromStream(stream);

            if (root.Name.ToLower() != "world")
                throw new Exception();

            foreach (XMLFragmentElement main in root.Elements)
            {
                if (main.Name.ToLower() == "gravity")
                {
                    world.Gravity = ReadVector(main);
                }
            }

            foreach (XMLFragmentElement shapeElement in root.Elements)
            {
                if (shapeElement.Name.ToLower() == "shapes")
                {
                    foreach (XMLFragmentElement n in shapeElement.Elements)
                    {
                        if (n.Name.ToLower() != "shape")
                            throw new Exception();

                        ShapeType type = (ShapeType)Enum.Parse(typeof(ShapeType), n.Attributes[0].Value, true);

                        switch (type)
                        {
                            case ShapeType.Circle:
                                {
                                    CircleShape shape = new CircleShape();

                                    foreach (XMLFragmentElement sn in n.Elements)
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "radius":
                                                shape.Radius = float.Parse(sn.Value);
                                                break;
                                            case "position":
                                                shape.Position = ReadVector(sn);
                                                break;
                                            default:
                                                throw new Exception();
                                        }
                                    }

                                    _shapes.Add(shape);
                                }
                                break;
                            case ShapeType.Polygon:
                                {
                                    PolygonShape shape = new PolygonShape();

                                    foreach (XMLFragmentElement sn in n.Elements)
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "vertices":
                                                {
                                                    List<Vector2> verts = new List<Vector2>();

                                                    foreach (XMLFragmentElement vert in sn.Elements)
                                                        verts.Add(ReadVector(vert));

                                                    shape.Set(new Vertices(verts.ToArray()));
                                                }
                                                break;
                                            case "centroid":
                                                shape.MassData.Centroid = ReadVector(sn);
                                                break;
                                        }
                                    }

                                    _shapes.Add(shape);
                                }
                                break;
                            case ShapeType.Edge:
                                {
                                    EdgeShape shape = new EdgeShape();
                                    foreach (XMLFragmentElement sn in n.Elements)
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "hasvertex0":
                                                shape.HasVertex0 = bool.Parse(sn.Value);
                                                break;
                                            case "hasvertex3":
                                                shape.HasVertex0 = bool.Parse(sn.Value);
                                                break;
                                            case "vertex0":
                                                shape.Vertex0 = ReadVector(sn);
                                                break;
                                            case "vertex1":
                                                shape.Vertex1 = ReadVector(sn);
                                                break;
                                            case "vertex2":
                                                shape.Vertex2 = ReadVector(sn);
                                                break;
                                            case "vertex3":
                                                shape.Vertex3 = ReadVector(sn);
                                                break;
                                            default:
                                                throw new Exception();
                                        }
                                    }
                                    _shapes.Add(shape);
                                }
                                break;
                        }
                    }
                }
            }

            foreach (XMLFragmentElement fixtureElement in root.Elements)
            {
                if (fixtureElement.Name.ToLower() == "fixtures")
                {
                    foreach (XMLFragmentElement n in fixtureElement.Elements)
                    {
                        Fixture fixture = new Fixture();

                        if (n.Name.ToLower() != "fixture")
                            throw new Exception();

                        foreach (XMLFragmentElement sn in n.Elements)
                        {
                            switch (sn.Name.ToLower())
                            {
                                case "shape":
                                    fixture.Shape = _shapes[int.Parse(sn.Value)];
                                    break;
                                case "density":
                                    fixture.Shape.Density = float.Parse(sn.Value);
                                    break;
                                case "filterdata":
                                    foreach (XMLFragmentElement ssn in sn.Elements)
                                    {
                                        switch (ssn.Name.ToLower())
                                        {
                                            case "categorybits":
                                                fixture._collisionCategories = (Category)int.Parse(ssn.Value);
                                                break;
                                            case "maskbits":
                                                fixture._collidesWith = (Category)int.Parse(ssn.Value);
                                                break;
                                            case "groupindex":
                                                fixture._collisionGroup = short.Parse(ssn.Value);
                                                break;
                                        }
                                    }

                                    break;
                                case "friction":
                                    fixture.Friction = float.Parse(sn.Value);
                                    break;
                                case "issensor":
                                    fixture.IsSensor = bool.Parse(sn.Value);
                                    break;
                                case "restitution":
                                    fixture.Restitution = float.Parse(sn.Value);
                                    break;
                                case "userdata":
                                    fixture.UserData = ReadSimpleType(sn, null, false);
                                    break;
                            }
                        }

                        _fixtures.Add(fixture);
                    }
                }
            }

            foreach (XMLFragmentElement bodyElement in root.Elements)
            {
                if (bodyElement.Name.ToLower() == "bodies")
                {
                    foreach (XMLFragmentElement n in bodyElement.Elements)
                    {
                        Body body = new Body(world);

                        if (n.Name.ToLower() != "body")
                            throw new Exception();

                        body.BodyType = (BodyType)Enum.Parse(typeof(BodyType), n.Attributes[0].Value, true);

                        foreach (XMLFragmentElement sn in n.Elements)
                        {
                            switch (sn.Name.ToLower())
                            {
                                case "active":
                                    if (bool.Parse(sn.Value))
                                        body.Flags |= BodyFlags.Enabled;
                                    else
                                        body.Flags &= ~BodyFlags.Enabled;
                                    break;
                                case "allowsleep":
                                    body.SleepingAllowed = bool.Parse(sn.Value);
                                    break;
                                case "angle":
                                    {
                                        Vector2 position = body.Position;
                                        body.SetTransformIgnoreContacts(ref position, float.Parse(sn.Value));
                                    }
                                    break;
                                case "angulardamping":
                                    body.AngularDamping = float.Parse(sn.Value);
                                    break;
                                case "angularvelocity":
                                    body.AngularVelocity = float.Parse(sn.Value);
                                    break;
                                case "awake":
                                    body.Awake = bool.Parse(sn.Value);
                                    break;
                                case "bullet":
                                    body.IsBullet = bool.Parse(sn.Value);
                                    break;
                                case "fixedrotation":
                                    body.FixedRotation = bool.Parse(sn.Value);
                                    break;
                                case "lineardamping":
                                    body.LinearDamping = float.Parse(sn.Value);
                                    break;
                                case "linearvelocity":
                                    body.LinearVelocity = ReadVector(sn);
                                    break;
                                case "position":
                                    {
                                        float rotation = body.Rotation;
                                        Vector2 position = ReadVector(sn);
                                        body.SetTransformIgnoreContacts(ref position, rotation);
                                    }
                                    break;
                                case "userdata":
                                    body.UserData = ReadSimpleType(sn, null, false);
                                    break;
                                case "fixtures":
                                    {
                                        foreach (XMLFragmentElement v in sn.Elements)
                                        {
                                            Fixture blueprint = _fixtures[int.Parse(v.Value)];
                                            Fixture f = new Fixture(body, blueprint.Shape, blueprint.CollisionCategories);
                                            f.Restitution = blueprint.Restitution;
                                            f.UserData = blueprint.UserData;
                                            f.Friction = blueprint.Friction;
                                            f.CollidesWith = blueprint.CollidesWith;
                                            f.CollisionGroup = blueprint.CollisionGroup;
                                        }
                                        break;
                                    }
                            }
                        }

                        _bodies.Add(body);
                    }
                }
            }

            foreach (XMLFragmentElement jointElement in root.Elements)
            {
                if (jointElement.Name.ToLower() == "joints")
                {
                    foreach (XMLFragmentElement n in jointElement.Elements)
                    {
                        Joint joint;

                        if (n.Name.ToLower() != "joint")
                            throw new Exception();

                        JointType type = (JointType)Enum.Parse(typeof(JointType), n.Attributes[0].Value, true);

                        int bodyAIndex = -1, bodyBIndex = -1;
                        bool collideConnected = false;
                        object userData = null;

                        foreach (XMLFragmentElement sn in n.Elements)
                        {
                            switch (sn.Name.ToLower())
                            {
                                case "bodya":
                                    bodyAIndex = int.Parse(sn.Value);
                                    break;
                                case "bodyb":
                                    bodyBIndex = int.Parse(sn.Value);
                                    break;
                                case "collideconnected":
                                    collideConnected = bool.Parse(sn.Value);
                                    break;
                                case "userdata":
                                    userData = ReadSimpleType(sn, null, false);
                                    break;
                            }
                        }

                        Body bodyA = _bodies[bodyAIndex];
                        Body bodyB = _bodies[bodyBIndex];

                        switch (type)
                        {
                            case JointType.Distance:
                                joint = new DistanceJoint();
                                break;
                            case JointType.Friction:
                                joint = new FrictionJoint();
                                break;
                            case JointType.Line:
                                joint = new LineJoint();
                                break;
                            case JointType.Prismatic:
                                joint = new PrismaticJoint();
                                break;
                            case JointType.Pulley:
                                joint = new PulleyJoint();
                                break;
                            case JointType.Revolute:
                                joint = new RevoluteJoint();
                                break;
                            case JointType.Weld:
                                joint = new WeldJoint();
                                break;
                            case JointType.Rope:
                                joint = new RopeJoint();
                                break;
                            case JointType.Angle:
                                joint = new AngleJoint();
                                break;
                            case JointType.Slider:
                                joint = new SliderJoint();
                                break;
                            case JointType.Gear:
                                throw new Exception("GearJoint is not supported.");
                            default:
                                throw new Exception("Invalid or unsupported joint.");
                        }

                        joint.CollideConnected = collideConnected;
                        joint.UserData = userData;
                        joint.BodyA = bodyA;
                        joint.BodyB = bodyB;
                        _joints.Add(joint);
                        world.AddJoint(joint);

                        foreach (XMLFragmentElement sn in n.Elements)
                        {
                            // check for specific nodes
                            switch (type)
                            {
                                case JointType.Distance:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "dampingratio":
                                                ((DistanceJoint)joint).DampingRatio = float.Parse(sn.Value);
                                                break;
                                            case "frequencyhz":
                                                ((DistanceJoint)joint).Frequency = float.Parse(sn.Value);
                                                break;
                                            case "length":
                                                ((DistanceJoint)joint).Length = float.Parse(sn.Value);
                                                break;
                                            case "localanchora":
                                                ((DistanceJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((DistanceJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Friction:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "localanchora":
                                                ((FrictionJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((FrictionJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                            case "maxforce":
                                                ((FrictionJoint)joint).MaxForce = float.Parse(sn.Value);
                                                break;
                                            case "maxtorque":
                                                ((FrictionJoint)joint).MaxTorque = float.Parse(sn.Value);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Line:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "enablemotor":
                                                ((LineJoint)joint).MotorEnabled = bool.Parse(sn.Value);
                                                break;
                                            case "localanchora":
                                                ((LineJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((LineJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                            case "motorspeed":
                                                ((LineJoint)joint).MotorSpeed = float.Parse(sn.Value);
                                                break;
                                            case "dampingratio":
                                                ((LineJoint)joint).DampingRatio = float.Parse(sn.Value);
                                                break;
                                            case "maxmotortorque":
                                                ((LineJoint)joint).MaxMotorTorque = float.Parse(sn.Value);
                                                break;
                                            case "frequencyhz":
                                                ((LineJoint)joint).Frequency = float.Parse(sn.Value);
                                                break;
                                            case "localxaxis":
                                                ((LineJoint)joint).LocalXAxis = ReadVector(sn);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Prismatic:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "enablelimit":
                                                ((PrismaticJoint)joint).LimitEnabled = bool.Parse(sn.Value);
                                                break;
                                            case "enablemotor":
                                                ((PrismaticJoint)joint).MotorEnabled = bool.Parse(sn.Value);
                                                break;
                                            case "localanchora":
                                                ((PrismaticJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((PrismaticJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                            case "local1axis1":
                                                ((PrismaticJoint)joint).LocalXAxis1 = ReadVector(sn);
                                                break;
                                            case "maxmotorforce":
                                                ((PrismaticJoint)joint).MaxMotorForce = float.Parse(sn.Value);
                                                break;
                                            case "motorspeed":
                                                ((PrismaticJoint)joint).MotorSpeed = float.Parse(sn.Value);
                                                break;
                                            case "lowertranslation":
                                                ((PrismaticJoint)joint).LowerLimit = float.Parse(sn.Value);
                                                break;
                                            case "uppertranslation":
                                                ((PrismaticJoint)joint).UpperLimit = float.Parse(sn.Value);
                                                break;
                                            case "referenceangle":
                                                ((PrismaticJoint)joint).ReferenceAngle = float.Parse(sn.Value);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Pulley:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "groundanchora":
                                                ((PulleyJoint)joint).GroundAnchorA = ReadVector(sn);
                                                break;
                                            case "groundanchorb":
                                                ((PulleyJoint)joint).GroundAnchorB = ReadVector(sn);
                                                break;
                                            case "lengtha":
                                                ((PulleyJoint)joint).LengthA = float.Parse(sn.Value);
                                                break;
                                            case "lengthb":
                                                ((PulleyJoint)joint).LengthB = float.Parse(sn.Value);
                                                break;
                                            case "localanchora":
                                                ((PulleyJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((PulleyJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                            case "maxlengtha":
                                                ((PulleyJoint)joint).MaxLengthA = float.Parse(sn.Value);
                                                break;
                                            case "maxlengthb":
                                                ((PulleyJoint)joint).MaxLengthB = float.Parse(sn.Value);
                                                break;
                                            case "ratio":
                                                ((PulleyJoint)joint).Ratio = float.Parse(sn.Value);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Revolute:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "enablelimit":
                                                ((RevoluteJoint)joint).LimitEnabled = bool.Parse(sn.Value);
                                                break;
                                            case "enablemotor":
                                                ((RevoluteJoint)joint).MotorEnabled = bool.Parse(sn.Value);
                                                break;
                                            case "localanchora":
                                                ((RevoluteJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((RevoluteJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                            case "maxmotortorque":
                                                ((RevoluteJoint)joint).MaxMotorTorque = float.Parse(sn.Value);
                                                break;
                                            case "motorspeed":
                                                ((RevoluteJoint)joint).MotorSpeed = float.Parse(sn.Value);
                                                break;
                                            case "lowerangle":
                                                ((RevoluteJoint)joint).LowerLimit = float.Parse(sn.Value);
                                                break;
                                            case "upperangle":
                                                ((RevoluteJoint)joint).UpperLimit = float.Parse(sn.Value);
                                                break;
                                            case "referenceangle":
                                                ((RevoluteJoint)joint).ReferenceAngle = float.Parse(sn.Value);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Weld:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "localanchora":
                                                ((WeldJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((WeldJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Rope:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "localanchora":
                                                ((RopeJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((RopeJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                            case "maxlength":
                                                ((RopeJoint)joint).MaxLength = float.Parse(sn.Value);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Gear:
                                    throw new Exception("Gear joint is unsupported");
                                case JointType.Angle:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "biasfactor":
                                                ((AngleJoint)joint).BiasFactor = float.Parse(sn.Value);
                                                break;
                                            case "maximpulse":
                                                ((AngleJoint)joint).MaxImpulse = float.Parse(sn.Value);
                                                break;
                                            case "softness":
                                                ((AngleJoint)joint).Softness = float.Parse(sn.Value);
                                                break;
                                            case "targetangle":
                                                ((AngleJoint)joint).TargetAngle = float.Parse(sn.Value);
                                                break;
                                        }
                                    }
                                    break;
                                case JointType.Slider:
                                    {
                                        switch (sn.Name.ToLower())
                                        {
                                            case "dampingratio":
                                                ((SliderJoint)joint).DampingRatio = float.Parse(sn.Value);
                                                break;
                                            case "frequencyhz":
                                                ((SliderJoint)joint).Frequency = float.Parse(sn.Value);
                                                break;
                                            case "maxlength":
                                                ((SliderJoint)joint).MaxLength = float.Parse(sn.Value);
                                                break;
                                            case "minlength":
                                                ((SliderJoint)joint).MinLength = float.Parse(sn.Value);
                                                break;
                                            case "localanchora":
                                                ((SliderJoint)joint).LocalAnchorA = ReadVector(sn);
                                                break;
                                            case "localanchorb":
                                                ((SliderJoint)joint).LocalAnchorB = ReadVector(sn);
                                                break;
                                        }
                                    }
                                    break;
                            }
                        }
                    }
                }
            }
        }
        public static Joint CopyJoint(Joint joint, Body bodyA, Body bodyB, World world)
        {
            Joint newJoint = null;

            switch (joint.JointType)
            {
                case JointType.Angle:
                    newJoint = JointFactory.CreateAngleJoint(world, bodyA, bodyB);
                    break;
                case JointType.Distance:
                    newJoint = new DistanceJoint(bodyA, bodyB, bodyA.WorldCenter, bodyB.WorldCenter);
                    break;
                case JointType.FixedAngle:
                    newJoint = new FixedAngleJoint(bodyA);
                    break;
                case JointType.FixedDistance:
                    newJoint = new FixedDistanceJoint(bodyA, bodyA.WorldCenter, Vector2.Zero);
                    break;
                case JointType.FixedFriction:
                    newJoint = new FixedFrictionJoint(bodyA, bodyA.WorldCenter);
                    break;
                case JointType.FixedPrismatic:
                    var fpJoint = joint as FixedPrismaticJoint;
                    var fpAxis = fpJoint.LocalXAxis1;
                    newJoint = new FixedPrismaticJoint(bodyA, bodyA.WorldCenter, fpAxis);
                    break;
                case JointType.FixedRevolute:
                    newJoint = new FixedRevoluteJoint(bodyA, bodyA.WorldCenter, Vector2.Zero);
                    break;
                case JointType.Friction:
                    newJoint = new FrictionJoint(bodyA, bodyB, bodyA.WorldCenter, bodyB.WorldCenter);
                    break;
                case JointType.Line:
                    var lineJoint = joint as LineJoint;
                    var axis = lineJoint.LocalXAxis;
                    newJoint = new LineJoint(bodyA, bodyB, bodyA.WorldCenter, axis);
                    break;
                case JointType.Prismatic:
                    var pJoint = joint as PrismaticJoint;
                    var pAxis = pJoint.LocalXAxis1;
                    newJoint = new PrismaticJoint(bodyA, bodyB, bodyA.WorldCenter, bodyB.WorldCenter, pAxis);
                    ((PrismaticJoint)newJoint).LimitEnabled = pJoint.LimitEnabled;
                    ((PrismaticJoint)newJoint).MotorEnabled = pJoint.MotorEnabled;
                    ((PrismaticJoint)newJoint).MaxMotorForce = pJoint.MaxMotorForce;
                    ((PrismaticJoint)newJoint).MotorSpeed = pJoint.MotorSpeed;
                    ((PrismaticJoint)newJoint).LowerLimit = pJoint.LowerLimit;
                    ((PrismaticJoint)newJoint).UpperLimit = pJoint.UpperLimit;
                    ((PrismaticJoint)newJoint).ReferenceAngle = pJoint.ReferenceAngle;
                    ((PrismaticJoint)newJoint).LocalXAxis1 = pJoint.LocalXAxis1;
                    break;
                case JointType.Pulley:
                    var pulleyJoint = joint as PulleyJoint;
                    var ratio = pulleyJoint.Ratio;
                    newJoint = new PulleyJoint(bodyA, bodyB, Vector2.Zero, Vector2.Zero, bodyA.WorldCenter, bodyB.WorldCenter, ratio);
                    break;
                case JointType.Revolute:
                    newJoint = new RevoluteJoint(bodyA, bodyB, bodyA.WorldCenter, bodyB.WorldCenter);
                    break;
                case JointType.Slider:
                    var sliderJoint = joint as SliderJoint;
                    var minLength = sliderJoint.MinLength;
                    var maxLength = sliderJoint.MaxLength;
                    newJoint = new SliderJoint(bodyA, bodyB, bodyA.WorldCenter, bodyB.WorldCenter, minLength, maxLength);
                    break;
                case JointType.Weld:
                    newJoint = new WeldJoint(bodyA, bodyB, bodyA.WorldCenter, bodyB.WorldCenter);
                    break;
            }

            var data = new FarseerJointUserData();
            data.BodyAName = ((FarseerJointUserData) joint.UserData).BodyAName;
            data.BodyBName = ((FarseerJointUserData) joint.UserData).BodyBName;

            joint.UserData = data;

            return newJoint;
        }