Beispiel #1
0
        private void CreateLeg(float s, WorldPoint wheelAnchor, WorldPoint offset, Body chassis, Body wheel)
        {
            var p1 = new Vector2(5.4f * s, -6.1f);
            var p2 = new Vector2(7.2f * s, -1.2f);
            var p3 = new Vector2(4.3f * s, -1.9f);
            var p4 = new Vector2(3.1f * s, 0.8f);
            var p5 = new Vector2(6.0f * s, 1.5f);
            var p6 = new Vector2(2.5f * s, 3.7f);

            var vertices1 = new Vector2[3];
            var vertices2 = new Vector2[3];

            if (s > 0.0f)
            {
                vertices1[0] = p1;
                vertices1[1] = p2;
                vertices1[2] = p3;

                vertices2[0] = Vector2.Zero;
                vertices2[1] = p5 - p4;
                vertices2[2] = p6 - p4;
            }
            else
            {
                vertices1[0] = p1;
                vertices1[1] = p3;
                vertices1[2] = p2;

                vertices2[0] = Vector2.Zero;
                vertices2[1] = p6 - p4;
                vertices2[2] = p5 - p4;
            }

            var body1 = Manager.AddPolygon(
                vertices1,
                type: Body.BodyType.Dynamic,
                worldPosition: offset,
                density: 1,
                collisionCategory: 2,
                collisionMask: ~2u).Body;
            var body2 = Manager.AddPolygon(
                vertices2,
                type: Body.BodyType.Dynamic,
                worldPosition: p4 + offset,
                density: 1,
                collisionCategory: 2,
                collisionMask: ~2u).Body;

            body1.AngularDamping = 10.0f;
            body2.AngularDamping = 10.0f;

            // Using a soft distance constraint can reduce some jitter.
            // It also makes the structure seem a bit more fluid by
            // acting like a suspension system.
            Manager.AddDistanceJoint(body1, body2, p2 + offset, p5 + offset, frequency: 10, dampingRatio: 0.5f);
            Manager.AddDistanceJoint(body1, body2, p3 + offset, p4 + offset, frequency: 10, dampingRatio: 0.5f);
            Manager.AddDistanceJoint(body1, wheel, p3 + offset, wheelAnchor + offset, frequency: 10, dampingRatio: 0.5f);
            Manager.AddDistanceJoint(body2, wheel, p6 + offset, wheelAnchor + offset, frequency: 10, dampingRatio: 0.5f);
            Manager.AddRevoluteJoint(body2, chassis, p4 + offset);
        }
Beispiel #2
0
        /// <summary>Creates a rectangle with the specified parameters.</summary>
        /// <param name="manager">The manager to create the object in.</param>
        /// <param name="width">The width of the rectangle.</param>
        /// <param name="height">The height of the rectangle.</param>
        /// <param name="localPosition">The offset of the rectangle relative to the body's local origin.</param>
        /// <param name="localAngle">The rotation of the rectangle relative to the body.</param>
        /// <param name="worldPosition">The initial world position of the body.</param>
        /// <param name="worldAngle">The initial world angle of the body.</param>
        /// <param name="type">The type of the body.</param>
        /// <param name="fixedRotation">
        ///     if set to <c>true</c> the rotation of the body is fixed to its initial value.
        /// </param>
        /// <param name="isBullet">
        ///     if set to <c>true</c> enables continuous collision with other dynamic bodies.
        /// </param>
        /// <param name="allowSleep">
        ///     if set to <c>true</c> allows the object to sleep when it is not moving (for improved performance).
        /// </param>
        /// <param name="density">The density of the fixture.</param>
        /// <param name="friction">The friction of the fixture.</param>
        /// <param name="restitution">The restitution of the fixture.</param>
        /// <param name="isSensor">
        ///     if set to <c>true</c> the created fixture is marked as a sensor (i.e. it will fire collision events but the
        ///     collision will not be handled by the solver).
        /// </param>
        /// <param name="collisionCategory">The collision groups for the fixture.</param>
        /// <param name="collisionMask">The collision groups to collide with.</param>
        /// <returns>The created body.</returns>
        public static PolygonFixture AddRectangle(
            this IManager manager,
            float width,
            float height,
            LocalPoint localPosition,
            float localAngle,
            WorldPoint worldPosition,
            float worldAngle       = 0,
            Body.BodyType type     = Body.BodyType.Static,
            bool fixedRotation     = false,
            bool isBullet          = false,
            bool allowSleep        = true,
            float density          = 0,
            float friction         = 0.2f,
            float restitution      = 0,
            bool isSensor          = false,
            uint collisionCategory = 1,
            uint collisionMask     = 0xFFFFFFFF)
        {
            var body = manager.AddBody(worldPosition, worldAngle, type, fixedRotation, isBullet, allowSleep);

            return(manager.AttachRectangle(
                       body,
                       width,
                       height,
                       localPosition,
                       localAngle,
                       density,
                       friction,
                       restitution,
                       isSensor,
                       collisionCategory,
                       collisionMask));
        }
Beispiel #3
0
        /// <summary>Gets the world linear velocity of a world point attached to this body.</summary>
        /// <param name="worldPoint">The point in world coordinates.</param>
        /// <returns>The world velocity of a point.</returns>
        public Vector2 GetLinearVelocityFromWorldPoint(WorldPoint worldPoint)
        {
// ReSharper disable RedundantCast Necessary for FarPhysics.
            return(LinearVelocityInternal +
                   Vector2Util.Cross(AngularVelocityInternal, (Vector2)(worldPoint - Sweep.CenterOfMass)));
// ReSharper restore RedundantCast
        }
Beispiel #4
0
        /// <summary>Initializes this joint with the specified parameters.</summary>
        internal void Initialize(
            WorldPoint anchor,
            Vector2 axis,
            float frequency,
            float dampingRatio,
            float maxMotorTorque,
            float motorSpeed,
            bool enableMotor)
        {
            _localAnchorA = BodyA.GetLocalPoint(anchor);
            _localAnchorB = BodyB.GetLocalPoint(anchor);
            _localXAxisA  = BodyA.GetLocalVector(axis);
            _localYAxisA  = Vector2Util.Cross(1.0f, ref _localXAxisA);

            _frequency    = frequency;
            _dampingRatio = dampingRatio;

            _maxMotorTorque = maxMotorTorque;
            _motorSpeed     = motorSpeed;
            _enableMotor    = enableMotor;

            _impulse       = 0;
            _motorImpulse  = 0;
            _springImpulse = 0;
        }
Beispiel #5
0
        /// <summary>
        ///     Adds a distance joint. A distance joint constrains two points on two bodies to remain at a fixed distance from
        ///     each other. You can view this as a massless, rigid rod.
        /// </summary>
        /// <param name="manager">The manager.</param>
        /// <param name="bodyA">The first body.</param>
        /// <param name="bodyB">The second body.</param>
        /// <param name="anchorA">The anchor on the first body, in world coordinates.</param>
        /// <param name="anchorB">The anchor on the second body, in world coordinates.</param>
        /// <param name="frequency">The mass-spring-damper frequency in Hertz. A value of 0 disables softness.</param>
        /// <param name="dampingRatio">The damping ratio. 0 = no damping, 1 = critical damping.</param>
        /// <param name="collideConnected">Whether the two bodies still collide.</param>
        /// <returns>The created joint.</returns>
        /// <remarks>Do not use a zero or short length.</remarks>
        public static DistanceJoint AddDistanceJoint(
            this IManager manager,
            Body bodyA,
            Body bodyB,
            WorldPoint anchorA,
            WorldPoint anchorB,
            float frequency       = 0,
            float dampingRatio    = 0,
            bool collideConnected = false)
        {
            if (bodyA == null)
            {
                throw new ArgumentNullException("bodyA");
            }
            if (bodyB == null)
            {
                throw new ArgumentNullException("bodyB");
            }
            if (bodyA == bodyB)
            {
                throw new ArgumentException("Joints must attach to two different bodies.", "bodyA");
            }

            if (WorldPoint.DistanceSquared(anchorA, anchorB) < Settings.LinearSlop * Settings.LinearSlop)
            {
                throw new ArgumentException("Points are too close together.");
            }

            var joint = (DistanceJoint)manager.GetSimulation()
                        .CreateJoint(Joint.JointType.Distance, bodyA, bodyB, collideConnected);

            joint.Initialize(anchorA, anchorB, frequency, dampingRatio);

            return(joint);
        }
Beispiel #6
0
        /// <summary>
        ///     Initializes the body with the specified type. This will not trigger mass recomputation, you will have to call
        ///     <see cref="ResetMassData"/>
        ///     to trigger that yourself.
        /// </summary>
        /// <param name="position">The world position.</param>
        /// <param name="angle">The angle.</param>
        /// <param name="type">The type.</param>
        /// <param name="fixedRotation">Whether the rotation of this body is fixed.</param>
        /// <param name="isBullet">Whether to set the body as a bullet.</param>
        /// <param name="allowSleep">Whether to allow the body to sleep.</param>
        /// <returns></returns>
        public Body Initialize(
            WorldPoint position,
            float angle        = 0,
            BodyType type      = BodyType.Static,
            bool fixedRotation = false,
            bool isBullet      = false,
            bool allowSleep    = true)
        {
            Transform.Translation = position;
            Transform.Rotation.Set(angle);

            Sweep.CenterOfMass0 = Transform.Translation;
            Sweep.CenterOfMass  = Transform.Translation;
            Sweep.Angle0        = angle;
            Sweep.Angle         = angle;

            TypeInternal = type;

            if (TypeInternal == BodyType.Dynamic)
            {
                MassInternal = 1.0f;
                InverseMass  = 1.0f;
            }

            _isRotationFixed       = fixedRotation;
            IsBulletInternal       = isBullet;
            IsSleepAllowedInternal = allowSleep;

            return(this);
        }
Beispiel #7
0
        /// <summary>
        ///     Adds a wheel joint. This joint provides two degrees of freedom: translation along an axis fixed in the first
        ///     body and rotation in the plane. You can use a joint limit to restrict the range of motion and a joint motor to
        ///     drive the rotation or to model rotational friction. This joint is designed for vehicle suspensions.
        /// </summary>
        /// <param name="manager">The manager.</param>
        /// <param name="bodyA">The first body (the wheel).</param>
        /// <param name="bodyB">The second body (the car).</param>
        /// <param name="anchor">The anchor on the first body in world coordinates.</param>
        /// <param name="axis">The connection axis in world space.</param>
        /// <param name="frequency">The suspension frequency, zero indicates no suspension.</param>
        /// <param name="dampingRatio">The suspension damping ratio, one indicates critical damping.</param>
        /// <param name="maxMotorTorque">The maximum motor torque, usually in N-m.</param>
        /// <param name="motorSpeed">The desired motor speed in radians per second.</param>
        /// <param name="enableMotor">Whether to initially enable the motor..</param>
        /// <param name="collideConnected">Whether the two bodies still collide.</param>
        /// <returns>The created joint.</returns>
        public static WheelJoint AddWheelJoint(
            this IManager manager,
            Body bodyA,
            Body bodyB,
            WorldPoint anchor,
            Vector2 axis,
            float frequency       = 2,
            float dampingRatio    = 0.7f,
            float maxMotorTorque  = 0,
            float motorSpeed      = 0,
            bool enableMotor      = false,
            bool collideConnected = false)
        {
            if (bodyA == null)
            {
                throw new ArgumentNullException("bodyA");
            }
            if (bodyB == null)
            {
                throw new ArgumentNullException("bodyB");
            }
            if (bodyA == bodyB)
            {
                throw new ArgumentException("Joints must attach to two different bodies.", "bodyA");
            }

            var joint = (WheelJoint)manager.GetSimulation()
                        .CreateJoint(Joint.JointType.Wheel, bodyA, bodyB, collideConnected);

            joint.Initialize(anchor, axis, frequency, dampingRatio, maxMotorTorque, motorSpeed, enableMotor);

            return(joint);
        }
Beispiel #8
0
        /// <summary>
        ///     Adds a weld joint. A rope joint enforces a maximum distance between two points on two bodies. It has no other
        ///     effect.
        /// </summary>
        /// <param name="manager">The manager.</param>
        /// <param name="bodyA">The first body.</param>
        /// <param name="bodyB">The second body.</param>
        /// <param name="anchorA">The position at which to attach the rope to the first body, in world coordinates.</param>
        /// <param name="anchorB">The position at which to attach the rope to the second body, in world coordinates.</param>
        /// <param name="length">The maximum length of the rope.</param>
        /// <param name="collideConnected">Whether the two bodies still collide.</param>
        /// <returns>The created joint.</returns>
        /// <remarks>
        ///     Changing the maximum length during the simulation would result in non-physical behavior, thus it is not
        ///     allowed. A model that would allow you to dynamically modify the length would have some sponginess, so Erin chose
        ///     not to implement it that way. See b2DistanceJoint if you want to dynamically control length.
        /// </remarks>
        public static RopeJoint AddRopeJoint(
            this IManager manager,
            Body bodyA,
            Body bodyB,
            WorldPoint anchorA,
            WorldPoint anchorB,
            float length,
            bool collideConnected)
        {
            if (bodyA == null)
            {
                throw new ArgumentNullException("bodyA");
            }
            if (bodyB == null)
            {
                throw new ArgumentNullException("bodyB");
            }
            if (bodyA == bodyB)
            {
                throw new ArgumentException("Joints must attach to two different bodies.", "bodyA");
            }
            if (length < Settings.LinearSlop)
            {
                throw new ArgumentException("Length is too short.", "length");
            }

            var joint = (RopeJoint)manager.GetSimulation()
                        .CreateJoint(Joint.JointType.Rope, bodyA, bodyB, collideConnected);

            joint.Initialize(anchorA, anchorB, length);

            return(joint);
        }
Beispiel #9
0
        /// <summary>Initializes this joint with the specified parameters.</summary>
        internal void Initialize(
            WorldPoint anchor,
            Vector2 axis,
            float lowerTranslation = 0,
            float upperTranslation = 0,
            float maxMotorForce    = 0,
            float motorSpeed       = 0,
            bool enableLimit       = false,
            bool enableMotor       = false)
        {
            _localAnchorA = BodyA.GetLocalPoint(anchor);
            _localAnchorB = BodyB.GetLocalPoint(anchor);
            _localXAxisA  = BodyA.GetLocalVector(axis);
            _localXAxisA.Normalize();
            _localYAxisA      = Vector2Util.Cross(1.0f, ref _localXAxisA);
            _referenceAngle   = BodyB.Angle - BodyA.Angle;
            _lowerTranslation = lowerTranslation;
            _upperTranslation = upperTranslation;
            _maxMotorForce    = maxMotorForce;
            _motorSpeed       = motorSpeed;
            _enableLimit      = enableLimit;
            _enableMotor      = enableMotor;

            _impulse      = Vector3.Zero;
            _motorImpulse = 0.0f;
            _limitState   = LimitState.Inactive;
        }
Beispiel #10
0
 /// <summary>Creates a circle with the specified parameters.</summary>
 /// <param name="manager">The manager to create the object in.</param>
 /// <param name="radius">The radius of the circle.</param>
 /// <param name="worldPosition">The initial world position of the body.</param>
 /// <param name="worldAngle">The initial world angle of the body.</param>
 /// <param name="type">The type of the body.</param>
 /// <param name="fixedRotation">
 ///     if set to <c>true</c> the rotation of the body is fixed to its initial value.
 /// </param>
 /// <param name="isBullet">
 ///     if set to <c>true</c> enables continuous collision with other dynamic bodies.
 /// </param>
 /// <param name="allowSleep">
 ///     if set to <c>true</c> allows the object to sleep when it is not moving (for improved performance).
 /// </param>
 /// <param name="density">The density of the fixture.</param>
 /// <param name="friction">The friction of the fixture.</param>
 /// <param name="restitution">The restitution of the fixture.</param>
 /// <param name="isSensor">
 ///     if set to <c>true</c> the created fixture is marked as a sensor (i.e. it will fire collision events but the
 ///     collision will not be handled by the solver).
 /// </param>
 /// <param name="collisionCategory">The collision groups for the fixture.</param>
 /// <param name="collisionMask">The collision groups to collide with.</param>
 /// <returns>The created body.</returns>
 public static CircleFixture AddCircle(
     this IManager manager,
     float radius,
     WorldPoint worldPosition,
     float worldAngle       = 0,
     Body.BodyType type     = Body.BodyType.Static,
     bool fixedRotation     = false,
     bool isBullet          = false,
     bool allowSleep        = true,
     float density          = 0,
     float friction         = 0.2f,
     float restitution      = 0,
     bool isSensor          = false,
     uint collisionCategory = 1,
     uint collisionMask     = 0xFFFFFFFF)
 {
     return(manager.AddCircle(
                LocalPoint.Zero,
                radius,
                worldPosition,
                worldAngle,
                type,
                fixedRotation,
                isBullet,
                allowSleep,
                density,
                friction,
                restitution,
                isSensor,
                collisionCategory,
                collisionMask));
 }
Beispiel #11
0
        /// <summary>
        ///     Adds a pulley joint. The pulley joint is connected to two bodies and two fixed ground points. The pulley supports a
        ///     ratio such that
        ///     <c>length1 + ratio * length2 &lt;= constant</c>.
        ///     <para>Thus, the force transmitted is scaled by the ratio.</para>
        /// </summary>
        /// <param name="manager">The manager.</param>
        /// <param name="bodyA">The first body.</param>
        /// <param name="bodyB">The second body.</param>
        /// <param name="groundAnchorA">The first ground anchor, in world coordinates.</param>
        /// <param name="groundAnchorB">The second ground anchor, in world coordinates.</param>
        /// <param name="anchorA">The anchor for the first body, in world coordinates.</param>
        /// <param name="anchorB">The anchor for the second body, in world coordinates.</param>
        /// <param name="ratio">The transmission ratio.</param>
        /// <param name="collideConnected">Whether the two bodies still collide.</param>
        /// <returns>The created joint.</returns>
        /// <remarks>
        ///     Warning: the pulley joint can get a bit squirrelly by itself. They often work better when combined with
        ///     prismatic joints. You should also cover the the anchor points with static shapes to prevent one side from going to
        ///     zero length.
        /// </remarks>
        public static PulleyJoint AddPulleyJoint(
            this IManager manager,
            Body bodyA,
            Body bodyB,
            WorldPoint groundAnchorA,
            WorldPoint groundAnchorB,
            WorldPoint anchorA,
            WorldPoint anchorB,
            float ratio           = 1,
            bool collideConnected = true)
        {
            if (bodyA == null)
            {
                throw new ArgumentNullException("bodyA");
            }
            if (bodyB == null)
            {
                throw new ArgumentNullException("bodyB");
            }
            if (bodyA == bodyB)
            {
                throw new ArgumentException("Joints must attach to two different bodies.", "bodyA");
            }

            var joint = (PulleyJoint)manager.GetSimulation()
                        .CreateJoint(Joint.JointType.Pulley, bodyA, bodyB, collideConnected);

            joint.Initialize(groundAnchorA, groundAnchorB, anchorA, anchorB, ratio);

            return(joint);
        }
Beispiel #12
0
        /// <summary>
        ///     Gets the interpolated position of an entity, if possible. Otherwise it will use the current position in the
        ///     simulation, and if that fails will set it to zero.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="position">The interpolated position.</param>
        /// <param name="angle">The interpolated angle.</param>
        public void GetInterpolatedTransform(int entity, out WorldPoint position, out float angle)
        {
            // Try to get the interpolated position.
            InterpolationEntry entry;

            if (Enabled && _entries.TryGetValue(entity, out entry))
            {
                position = entry.InterpolatedPosition;
                angle    = entry.InterpolatedAngle;
                return;
            }

            // We don't have one, use the fixed one instead.
            var transform = (ITransform)Manager.GetComponent(entity, TransformTypeId);

            if (transform == null)
            {
                position = WorldPoint.Zero;
                angle    = 0f;
            }
            else
            {
                position = transform.Position;
                angle    = transform.Angle;
            }
        }
Beispiel #13
0
        protected override void Create()
        {
            Manager.AddEdge(new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f));

            var columOrigin = new WorldPoint(-7.0f, 0.75f);
            var deltaX      = new Vector2(0.5625f, 1.25f);
            var deltaY      = new Vector2(1.125f, 0.0f);

            const int count = 35;

            for (var i = 0; i < count; ++i)
            {
                var columnPosition = columOrigin;

                for (var j = i; j < count; ++j)
                {
                    Manager.AddRectangle(width: 1, height: 1,
                                         worldPosition: columnPosition,
                                         type: Body.BodyType.Dynamic,
                                         density: 5);

                    columnPosition += deltaY;
                }

                columOrigin += deltaX;
            }
        }
        /// <summary>Compute minimal bounding rectangle around line.</summary>
        /// <param name="a">Start of the line.</param>
        /// <param name="b">End of the line.</param>
        /// <param name="t">The fraction of the line to bound.</param>
        /// <returns></returns>
        public static TRectangle BoundsFor(TPoint a, TPoint b, float t)
        {
// ReSharper disable RedundantCast Necessary for FarCollections.
            TRectangle rectangle;
            var        c = a + (Microsoft.Xna.Framework.Vector2)(b - a) * t;

            if (a.X < c.X)
            {
                rectangle.X     = a.X;
                rectangle.Width = (float)(c.X - a.X);
            }
            else
            {
                rectangle.X     = c.X;
                rectangle.Width = (float)(a.X - c.X);
            }
            if (a.Y < c.Y)
            {
                rectangle.Y      = a.Y;
                rectangle.Height = (float)(c.Y - a.Y);
            }
            else
            {
                rectangle.Y      = c.Y;
                rectangle.Height = (float)(a.Y - c.Y);
            }
            return(rectangle);
// ReSharper restore RedundantCast
        }
Beispiel #15
0
        /// <summary>
        ///     Adds a weld joint. A weld joint essentially glues two bodies together. A weld joint may distort somewhat
        ///     because the island constraint solver is approximate.
        /// </summary>
        /// <param name="manager">The manager.</param>
        /// <param name="bodyA">The first body.</param>
        /// <param name="bodyB">The second body.</param>
        /// <param name="anchor">The anchor to weld the bodies at in world coordinates.</param>
        /// <param name="frequency">The mass-spring-damper frequency in Hertz. Rotation only. Disable softness with a value of 0.</param>
        /// <param name="dampingRatio">The damping ratio. 0 = no damping, 1 = critical damping.</param>
        /// <returns>The created joint.</returns>
        public static WeldJoint AddWeldJoint(
            this IManager manager,
            Body bodyA,
            Body bodyB,
            WorldPoint anchor,
            float frequency,
            float dampingRatio)
        {
            if (bodyA == null)
            {
                throw new ArgumentNullException("bodyA");
            }
            if (bodyB == null)
            {
                throw new ArgumentNullException("bodyB");
            }
            if (bodyA == bodyB)
            {
                throw new ArgumentException("Joints must attach to two different bodies.", "bodyA");
            }

            var joint = (WeldJoint)manager.GetSimulation()
                        .CreateJoint(Joint.JointType.Weld, bodyA, bodyB, false);

            joint.Initialize(anchor, frequency, dampingRatio);

            return(joint);
        }
Beispiel #16
0
        /// <summary>
        ///     Applies the translation set to be used next. Called from system, because we want to keep the setter in debug
        ///     private to make sure no one actually writes directly to the translation variable.
        /// </summary>
        /// <remarks>This must be called from a synchronous context (i.e. not from a parallel system).</remarks>
        public void Update()
        {
            if (_positionChanged)
            {
                TranslationChanged message;
                message.Component        = this;
                message.PreviousPosition = _position;
                message.CurrentPosition  = _nextPosition;

                _position        = _nextPosition;
                _positionChanged = false;

                Manager.SendMessage(message);
            }

            if (_angleChanged)
            {
                RotationChanged message;
                message.Component        = this;
                message.PreviousRotation = _angle;
                message.CurrentRotation  = _nextAngle;

                _angle        = MathHelper.WrapAngle(_nextAngle);
                _angleChanged = false;

                Manager.SendMessage(message);
            }
        }
Beispiel #17
0
        /// <summary>
        ///     Adds a revolute joint. A revolute joint constrains two bodies to share a common point while they are free to
        ///     rotate about the point. The relative rotation about the shared point is the joint angle. You can limit the relative
        ///     rotation with a joint limit that specifies a lower and upper angle. You can use a motor to drive the relative
        ///     rotation about the shared point. A maximum motor torque is provided so that infinite forces are not generated.
        /// </summary>
        /// <param name="manager">The manager.</param>
        /// <param name="bodyA">The first body.</param>
        /// <param name="bodyB">The second body.</param>
        /// <param name="anchor">The anchor point in world coordinates.</param>
        /// <param name="lowerAngle">The lower angle.</param>
        /// <param name="upperAngle">The upper angle.</param>
        /// <param name="maxMotorTorque">The maximum motor torque.</param>
        /// <param name="motorSpeed">The motor speed.</param>
        /// <param name="enableLimit">Whether to enable the lower and upper angle limits.</param>
        /// <param name="enableMotor">Whether to enable the motor.</param>
        /// <param name="collideConnected">Whether the two bodies still collide.</param>
        /// <returns>The created joint.</returns>
        public static RevoluteJoint AddRevoluteJoint(
            this IManager manager,
            Body bodyA,
            Body bodyB,
            WorldPoint anchor,
            float lowerAngle      = 0,
            float upperAngle      = 0,
            float maxMotorTorque  = 0,
            float motorSpeed      = 0,
            bool enableLimit      = false,
            bool enableMotor      = false,
            bool collideConnected = false)
        {
            if (bodyA == null)
            {
                throw new ArgumentNullException("bodyA");
            }
            if (bodyB == null)
            {
                throw new ArgumentNullException("bodyB");
            }
            if (bodyA == bodyB)
            {
                throw new ArgumentException("Joints must attach to two different bodies.", "bodyA");
            }

            var joint = (RevoluteJoint)manager.GetSimulation()
                        .CreateJoint(Joint.JointType.Revolute, bodyA, bodyB, collideConnected);

            joint.Initialize(anchor, lowerAngle, upperAngle, maxMotorTorque, motorSpeed, enableLimit, enableMotor);

            return(joint);
        }
Beispiel #18
0
        /// <summary>Creates an edge with the specified parameters.</summary>
        /// <param name="manager">The manager to create the object in.</param>
        /// <param name="ghostStart">The ghost point for the start point, for chained edges.</param>
        /// <param name="localStart">The start point of the edge relative to the body's local origin.</param>
        /// <param name="localEnd">The end point of the shape relative to the body's local origin.</param>
        /// <param name="ghostEnd">The ghost point for end point, for chained edges.</param>
        /// <param name="worldPosition">The initial world position of the body.</param>
        /// <param name="worldAngle">The initial world angle of the body.</param>
        /// <param name="friction">The friction of the fixture.</param>
        /// <param name="restitution">The restitution of the fixture.</param>
        /// <param name="isSensor">
        ///     if set to <c>true</c> the created fixture is marked as a sensor (i.e. it will fire collision events but the
        ///     collision will not be handled by the solver).
        /// </param>
        /// <param name="collisionCategory">The collision groups for the fixture.</param>
        /// <param name="collisionMask">The collision groups to collide with.</param>
        /// <returns>The created body.</returns>
        public static EdgeFixture AddEdge(
            this IManager manager,
            LocalPoint ghostStart,
            LocalPoint localStart,
            LocalPoint localEnd,
            LocalPoint ghostEnd,
            WorldPoint worldPosition,
            float worldAngle       = 0,
            float friction         = 0.2f,
            float restitution      = 0,
            bool isSensor          = false,
            uint collisionCategory = 1,
            uint collisionMask     = 0xFFFFFFFF)
        {
            var body = manager.AddBody(worldPosition, worldAngle);

            return(manager.AttachEdge(
                       body,
                       ghostStart,
                       localStart,
                       localEnd,
                       ghostEnd,
                       friction,
                       restitution,
                       isSensor,
                       collisionCategory,
                       collisionMask));
        }
Beispiel #19
0
 /// <summary>
 ///     Adds 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.
 ///     <para/>
 ///     This overload attaches a body to a fixed point in the world.
 /// </summary>
 /// <param name="manager">The manager.</param>
 /// <param name="body">The body.</param>
 /// <param name="anchor">The anchor in world coordinates.</param>
 /// <param name="axis">The axis as a world vector.</param>
 /// <param name="lowerTranslation">The lower translation limit.</param>
 /// <param name="upperTranslation">The upper translation limit.</param>
 /// <param name="maxMotorForce">The maximum motor force.</param>
 /// <param name="motorSpeed">The motor speed.</param>
 /// <param name="enableLimit">Whether to enable the translation limits.</param>
 /// <param name="enableMotor">Whether to enable the motor.</param>
 /// <param name="collideConnected">Whether the two bodies still collide.</param>
 /// <returns>The created joint.</returns>
 public static PrismaticJoint AddPrismaticJoint(
     this IManager manager,
     Body body,
     WorldPoint anchor,
     Vector2 axis,
     float lowerTranslation = 0,
     float upperTranslation = 0,
     float maxMotorForce    = 0,
     float motorSpeed       = 0,
     bool enableLimit       = false,
     bool enableMotor       = false,
     bool collideConnected  = false)
 {
     return(manager.AddPrismaticJoint(
                manager.GetSimulation().FixPoint,
                body,
                anchor,
                axis,
                lowerTranslation,
                upperTranslation,
                maxMotorForce,
                motorSpeed,
                enableLimit,
                enableMotor,
                collideConnected));
 }
        /// <summary>Compute minimal bounding rectangle around a circle.</summary>
        /// <param name="center">The center.</param>
        /// <param name="radius">The radius.</param>
        /// <returns></returns>
        public static TRectangle BoundsFor(TPoint center, float radius)
        {
            TRectangle rectangle;

            rectangle.X     = center.X - radius;
            rectangle.Y     = center.Y - radius;
            rectangle.Width = rectangle.Height = radius + radius;
            return(rectangle);
        }
Beispiel #21
0
 /// <summary>
 ///     Adds a weld joint. A weld joint essentially glues two bodies together. A weld joint may distort somewhat
 ///     because the island constraint solver is approximate.
 ///     <para/>
 ///     This overload attaches a body to a fixed point in the world.
 /// </summary>
 /// <param name="manager">The manager.</param>
 /// <param name="body">The body.</param>
 /// <param name="anchor">The anchor to weld the body at in world coordinates.</param>
 /// <param name="frequency">The mass-spring-damper frequency in Hertz. Rotation only. Disable softness with a value of 0.</param>
 /// <param name="dampingRatio">The damping ratio. 0 = no damping, 1 = critical damping.</param>
 /// <returns>The created joint.</returns>
 public static WeldJoint AddWeldJoint(
     this IManager manager,
     Body body,
     WorldPoint anchor,
     float frequency,
     float dampingRatio)
 {
     return(manager.AddWeldJoint(manager.GetSimulation().FixPoint, body, anchor, frequency, dampingRatio));
 }
Beispiel #22
0
        /// <summary>Initializes this joint with the specified parameters.</summary>
        internal void Initialize(WorldPoint anchorA, WorldPoint anchorB, float length)
        {
            _localAnchorA = BodyA.GetLocalPoint(anchorA);
            _localAnchorB = BodyB.GetLocalPoint(anchorB);
            _maxLength    = length;

            _impulse = 0;
            _length  = 0;
        }
Beispiel #23
0
        /// <summary>Test for collision between two moving spheres.</summary>
        /// <param name="radiusA">radius of first sphere.</param>
        /// <param name="positionA0">previous center of first sphere.</param>
        /// <param name="positionA1">current center of first sphere.</param>
        /// <param name="radiusB">radius of second sphere.</param>
        /// <param name="positionB0">previous center of second sphere.</param>
        /// <param name="positionB1">current center of second sphere.</param>
        /// <param name="t">The relative time between previous and current position at which the spheres intersected.</param>
        /// <returns>true if the spheres (did) collide.</returns>
        /// <see cref="http://www.gamasutra.com/view/feature/3383/simple_intersection_tests_for_games.php?page=2"/>
        public static bool Test(
            float radiusA,
            ref WorldPoint positionA0,
            ref WorldPoint positionA1,
            float radiusB,
            ref WorldPoint positionB0,
            ref WorldPoint positionB1,
            out float t)
        {
            //displacement of A
            var va = (Vector2)(positionA1 - positionA0);
            //displacement of B
            var vb = (Vector2)(positionB1 - positionB0);

            // relative position of B to A
            var ab = (Vector2)(positionB0 - positionA0);

            // relative velocity (in normalized time)
            var vab = vb - va;
            var rab = radiusA + radiusB;

            // u*u coefficient
            var a = Vector2.Dot(vab, vab);

            // u coefficient
            var b = -2f * Vector2.Dot(vab, ab);

            // constant term
            var c = Vector2.Dot(ab, ab) - rab * rab;

            //check if they're currently overlapping
            if (Vector2.Dot(ab, ab) <= rab * rab)
            {
                t = 0;
                return(true);
            }

            // check if they hit each other
            // during the frame
            var q = b * b - 4 * a * c;

            if (q < 0)
            {
                t = 0;
                return(false);
            }

            var sq = (float)System.Math.Sqrt(q);
            var d  = 1f / (a + a);
            var r1 = (b + sq) * d;
            var r2 = (b - sq) * d;

            t = r2 > r1 ? r2 : r1;

            return(t >= 0f && t <= 1f);
        }
Beispiel #24
0
        /// <summary>
        ///     Update an entry by changing its position. If the item is not stored in the index, this will return
        ///     <code>false</code>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="index">The index to update.</param>
        /// <param name="newPoint">The new position of the item.</param>
        /// <param name="item">The item for which to update the bounds.</param>
        /// <returns>
        ///     <c>true</c> if the update was successful; <c>false</c> otherwise.
        /// </returns>
        /// <remarks>
        ///     This will lead to the point being converted to an empty rectangle at the point's position, which will then be
        ///     used, instead.
        /// </remarks>
        public static bool Update <T>(this IIndex <T, TRectangle, TPoint> index, TPoint newPoint, T item)
        {
            // Convert to rectangle, then update with that.
            TRectangle bounds;

            bounds.X     = newPoint.X;
            bounds.Y     = newPoint.Y;
            bounds.Width = bounds.Height = 0;
            return(index.Update(bounds, Vector2.Zero, item));
        }
Beispiel #25
0
        /// <summary>Add a new item to the index, with the specified position.</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="index">The index to add to.</param>
        /// <param name="point">The position of the item.</param>
        /// <param name="item">The item.</param>
        /// <exception cref="T:System.ArgumentException">The item is already stored in the index.</exception>
        /// <remarks>
        ///     This will lead to the point being converted to an empty rectangle at the point's position, which will then be
        ///     inserted, instead.
        /// </remarks>
        public static void Add <T>(this IIndex <T, TRectangle, TPoint> index, TPoint point, T item)
        {
            // Convert to rectangle, then add that.
            TRectangle bounds;

            bounds.X     = point.X;
            bounds.Y     = point.Y;
            bounds.Width = bounds.Height = 0;
            index.Add(bounds, item);
        }
Beispiel #26
0
        /// <summary>Initializes this joint with the specified parameters.</summary>
        internal void Initialize(WorldPoint anchor, float frequency, float dampingRatio)
        {
            _localAnchorA   = BodyA.GetLocalPoint(anchor);
            _localAnchorB   = BodyB.GetLocalPoint(anchor);
            _referenceAngle = BodyB.Angle - BodyA.Angle;

            _frequency    = frequency;
            _dampingRatio = dampingRatio;

            _impulse = Vector3.Zero;
        }
Beispiel #27
0
        /// <summary>Reset the component to its initial state, so that it may be reused without side effects.</summary>
        public override void Reset()
        {
            base.Reset();

            _position        = WorldPoint.Zero;
            _nextPosition    = WorldPoint.Zero;
            _positionChanged = false;
            _angle           = 0;
            _nextAngle       = 0;
            _angleChanged    = false;
        }
Beispiel #28
0
        /// <summary>Tests if two circles intersect.</summary>
        /// <param name="radiusA">The radius of the first circle.</param>
        /// <param name="positionA">The center of the first circle.</param>
        /// <param name="radiusB">The radius of the second circle.</param>
        /// <param name="positionB">The center of the second circle.</param>
        /// <returns></returns>
        public static bool Test(
            float radiusA,
            ref WorldPoint positionA,
            float radiusB,
            ref WorldPoint positionB)
        {
            var d = (Vector2)(positionB - positionA);
            var r = radiusA + radiusB;

            return((d.X * d.X + d.Y * d.Y) <= r * r);
        }
Beispiel #29
0
 /// <summary>Creates the a new body with the specified properties.</summary>
 /// <param name="manager">The manager to create the body in.</param>
 /// <param name="worldPosition">The initial world position of the body.</param>
 /// <param name="worldAngle">The initial world angle of the body.</param>
 /// <param name="type">The type of the body.</param>
 /// <param name="fixedRotation">
 ///     if set to <c>true</c> the rotation of the body is fixed to its initial value.
 /// </param>
 /// <param name="isBullet">
 ///     if set to <c>true</c> enables continuous collision with other dynamic bodies.
 /// </param>
 /// <param name="allowSleep">
 ///     if set to <c>true</c> allows the object to sleep when it is not moving (for improved performance).
 /// </param>
 /// <returns>The created body.</returns>
 public static Body AddBody(
     this IManager manager,
     WorldPoint worldPosition,
     float worldAngle   = 0,
     Body.BodyType type = Body.BodyType.Static,
     bool fixedRotation = false,
     bool isBullet      = false,
     bool allowSleep    = true)
 {
     return(manager.AddBody(manager.AddEntity(), worldPosition, worldAngle, type, fixedRotation, isBullet, allowSleep));
 }
Beispiel #30
0
 /// <summary>Initializes the specified local anchor A.</summary>
 /// <param name="anchorA">The world anchor point for the first body.</param>
 /// <param name="anchorB">The world anchor point for the second body.</param>
 /// <param name="frequency">The mass-spring-damper frequency in Hertz. A value of 0 disables softness.</param>
 /// <param name="dampingRatio">The damping ratio. 0 = no damping, 1 = critical damping.</param>
 internal void Initialize(
     WorldPoint anchorA,
     WorldPoint anchorB,
     float frequency,
     float dampingRatio)
 {
     _localAnchorA = BodyA.GetLocalPoint(anchorA);
     _localAnchorB = BodyB.GetLocalPoint(anchorB);
     _length       = System.Math.Max(0.1f, WorldPoint.Distance(anchorA, anchorB));
     _frequency    = System.Math.Max(0, frequency);
     _dampingRatio = System.Math.Max(0, dampingRatio);
 }