public void Update(GameTime gameTime) { if (LinearVelocity.LengthSquared() >= 1e-7) { var step = LinearVelocity * World.TimeScale * (float)gameTime.ElapsedGameTime.TotalSeconds; bool stopped = false; var rf = this; World.Physics.RayCast((Fixture arg1, Vector2 arg2, Vector2 arg3, float arg4) => { if (arg1.Body.Tag is TerrainComponent) { Position = arg2 * 64f; LinearVelocity = Vector2.Zero; stopped = true; } else if (arg1.Body.Tag is Entity) { var ent = arg1.Body.Tag as Entity; if (ent.Tags.Any(t => TargetedTags.Contains(t))) { var ch = ent.GetComponent <CharacterComponent>(); if (ch != null) { ch.Damage(World.GetEntity(OwnerID), Damage); Position = arg2 * 64f; LinearVelocity = Vector2.Zero; stopped = true; Parent.AddComponent(new BindedBodyComponent().BindTo(ent, Position, Rotation)); rf.Remove = true; return(0); } } } return(arg4); }, Position / 64f, (Position + step) / 64f); if (!stopped) { Position += step; } else { Gravity = false; } } if (Gravity) { LinearVelocity += new Vector2(0, World.Physics.Gravity.Y * 64f * (float)gameTime.ElapsedGameTime.TotalSeconds * World.TimeScale); } if (Friction > 0) { LinearVelocity /= Friction; } }
public override void _Process(float delta) { Delta = delta; ProcessTask(); if (LinearVelocity.LengthSquared() > 0.01) { var visual = GetNode <Spatial>("Visual"); var angle = Mathf.Atan2(LinearVelocity.x, LinearVelocity.z); visual.Rotation = new Vector3(0, angle, 0); } }
/// <summary> /// Updates the sleeping state. Is called in <see cref="UpdateVelocity"/>. /// </summary> /// <param name="deltaTime">The time step.</param> private void UpdateSleeping(float deltaTime) { if (IsSleeping || !CanSleep) { return; } if (MotionType == MotionType.Dynamic) { if (LinearVelocity.LengthSquared() < Simulation.Settings.Sleeping.LinearVelocityThresholdSquared && AngularVelocity.LengthSquared() < Simulation.Settings.Sleeping.AngularVelocityThresholdSquared) { // Movement is below threshold. Increase counter. _noMovementTime += deltaTime; // Static bodies sleep immediately. Kinematic and dynamic bodies are handled here. // Dynamic bodies can only sleep if their whole island is sleeping. (Note: When the island // is processed the sleeping of the dynamic body is deferred if the island is awake.) if (_noMovementTime > Simulation.Settings.Sleeping.TimeThreshold) { IsSleeping = true; } } else { // Movement detected. _noMovementTime = 0; } } else { if (LinearVelocity.LengthSquared() < Numeric.EpsilonFSquared && AngularVelocity.LengthSquared() < Numeric.EpsilonFSquared) { // Kinematic bodies are set to sleep immediately! IsSleeping = true; _linearVelocity = Vector3.Zero; _angularVelocity = Vector3.Zero; _noMovementTime = float.PositiveInfinity; } else { // Movement detected. _noMovementTime = 0; } } }
public void UpdateDeactivation(float timeStep) { if ((ActivationState == ActivationState.IslandSleeping) || (ActivationState == ActivationState.DisableDeactivation)) { return; } if ((LinearVelocity.LengthSquared() < LinearSleepingThreshold * LinearSleepingThreshold) && (AngularVelocity.LengthSquared() < AngularSleepingThreshold * AngularSleepingThreshold)) { DeactivationTime += timeStep; } else { DeactivationTime = 0; ActivationState = ActivationState.Nothing; } }
/// <summary> /// Applies buoyancy, drag and angular drag caused by water /// </summary> public void ApplyWaterForces() { //buoyancy Vector2 buoyancy = new Vector2(0, Mass * 9.6f); Vector2 dragForce = Vector2.Zero; if (LinearVelocity.LengthSquared() > 0.00001f) { //drag Vector2 velDir = Vector2.Normalize(LinearVelocity); float vel = LinearVelocity.Length() * 2.0f; float drag = vel * vel * Math.Max(height + radius * 2, height); dragForce = Math.Min(drag, Mass * 500.0f) * -velDir; } ApplyForce(dragForce + buoyancy); ApplyTorque(body.AngularVelocity * body.Mass * -0.08f); }
/// <summary> /// Applies buoyancy, drag and angular drag caused by water /// </summary> public void ApplyWaterForces() { //buoyancy Vector2 buoyancy = new Vector2(0, Mass * 9.6f); Vector2 dragForce = Vector2.Zero; float speedSqr = LinearVelocity.LengthSquared(); if (speedSqr > 0.00001f) { //drag float speed = (float)Math.Sqrt(speedSqr); Vector2 velDir = LinearVelocity / speed; float vel = speed * 2.0f; float drag = vel * vel * Math.Max(height + radius * 2, height); dragForce = Math.Min(drag, Mass * 500.0f) * -velDir; } ApplyForce(dragForce + buoyancy, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); ApplyTorque(body.AngularVelocity * body.Mass * -0.08f); }
/// <summary> /// Updates the pose using numerical integration. /// </summary> /// <param name="deltaTime">The time step.</param> internal void UpdatePose(float deltaTime) { // Static bodies do not move. if (MotionType == MotionType.Static) { return; } if (IsSleeping) { // Previously in this time step the sleeping could still be deferred. Therefore the // velocities have not been reset. At this point the rigid body is definitely sleeping. // Reset the velocities... _linearVelocity = Vector3.Zero; _angularVelocity = Vector3.Zero; // ...and exit. return; } // Clamp velocities before we apply them. if (_linearVelocity.IsNaN) { _linearVelocity = Vector3.Zero; } else if (_linearVelocity.LengthSquared() > Simulation.Settings.Motion.MaxLinearVelocitySquared) { _linearVelocity.Length = Simulation.Settings.Motion.MaxLinearVelocity; } if (_angularVelocity.IsNaN) { _angularVelocity = Vector3.Zero; } else if (_angularVelocity.LengthSquared() > Simulation.Settings.Motion.MaxAngularVelocitySquared) { _angularVelocity.Length = Simulation.Settings.Motion.MaxAngularVelocity; } // Important: Use the center-of-mass pose! var x = PoseCenterOfMass.Position; var q = Quaternion.CreateFromRotationMatrix(PoseCenterOfMass.Orientation); // Derivative of position: velocity // Derivative of orientation: q' = 1/2 * (0, ω) * q var xDerivative = LinearVelocity + LinearCorrectionVelocity; var qDerivative = 0.5f * new Quaternion(0, AngularVelocity + AngularCorrectionVelocity) * q; Pose targetPoseCOM = new Pose(x + deltaTime * xDerivative, (q + deltaTime * qDerivative).Normalized); if (CcdEnabled && Simulation.Settings.Motion.CcdEnabled && LinearVelocity.LengthSquared() > Simulation.Settings.Motion.CcdVelocityThresholdSquared) { // Continuous collision detection. IsCcdActive = true; TimeOfImpact = 1; Simulation.CcdRequested = true; TargetPose = targetPoseCOM * MassFrame.Pose.Inverse; // Trigger PoseChanged event. The pose has not changed but the AABB will be set to the // temporal AABB during motion clamping. _aabbIsValid = false; OnPoseChanged(EventArgs.Empty); } else { IsCcdActive = false; PoseCenterOfMass = targetPoseCOM; } LinearCorrectionVelocity = Vector3.Zero; AngularCorrectionVelocity = Vector3.Zero; }