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); }
/// <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)); }
/// <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 }
/// <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; }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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; }
/// <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)); }
/// <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 <= 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); }
/// <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; } }
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 }
/// <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); }
/// <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); } }
/// <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); }
/// <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)); }
/// <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); }
/// <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)); }
/// <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; }
/// <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); }
/// <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)); }
/// <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); }
/// <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; }
/// <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; }
/// <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); }
/// <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)); }
/// <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); }