public override int GetHashCode() { int hash = 1; if (TimeStamp != 0D) { hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeStamp); } if (position_ != null) { hash ^= Position.GetHashCode(); } if (orientation_ != null) { hash ^= Orientation.GetHashCode(); } if (linearVelocity_ != null) { hash ^= LinearVelocity.GetHashCode(); } if (angularVelocity_ != null) { hash ^= AngularVelocity.GetHashCode(); } if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } return(hash); }
private void ReflectAcrossNormal(Vector2 normalVector) { if (normalVector == Vector2.Zero) { return; } // Assuming n is the normal of the fixture at the point of the raycast contact // We just reflect the previous velocity accross the normal // Use angle - pi/2 for current angle float normalAngle = ((float)Math.Atan(normalVector.Y / normalVector.X) - (float)Math.PI / 2); Rotation += (2 * (normalAngle - (Rotation))); Rotation += (float)Math.PI; Vector2 oldvel = LinearVelocity; Vector2 tempVel; tempVel.X = (float)(LinearVelocity.Length() * Math.Sin(Rotation)); tempVel.Y = -(float)(LinearVelocity.Length() * Math.Cos(Rotation)); LinearVelocity = tempVel; // Manipulate velocity so that collisions reflect at 100% speed. Some weapons might not have this. LinearVelocity *= Math.Max(oldvel.Length() / LinearVelocity.Length(), 1f); futurePos = Position + (TimeKeeper.MsSinceInitialization - _lastTimeStamp) * LinearVelocity; CheckCollisions(); }
public override void _PhysicsProcess(float delta) { if (dragging) { //We continuesly update the start position for our force add direction to the position the blob is dragStartPos = GlobalPosition; } //If the dragging has not completed we just exit out of hte method if (!dragComplete) { return; } moveDirection = dragEndPos - dragStartPos; moveDirection = moveDirection.Normalized(); ApplyCentralImpulse(moveDirection * speed); dragging = false; dragComplete = false; //Bug or feature? Tis piece of code forces the red blob to stop before being able to shoot of in a direction again if (Mathf.Abs(LinearVelocity.x) > maxSpeed || Mathf.Abs(LinearVelocity.y) > maxSpeed) { Vector2 newSpeed = LinearVelocity.Normalized(); newSpeed *= maxSpeed; LinearVelocity = newSpeed; } }
/// <summary> /// Checks for collisions. Handles collisions and calls terminate() as necessary /// </summary> public virtual void CheckCollisions() { if (numRecursiveCalls == 5) { Terminate(); return; } numRecursiveCalls++;//Prevents stack overflow that can result when projectiles get stuck between very close reflectors if (LinearVelocity.Length() < 1e-3)//Might need to tweak this tolerance { //When the projectile velocity becomes very small, //the raycast future position becomes tiny and it //becomes almost impossible to collide. For now, //switch to a point test. TODO: Convert to multi-point test, testing bounds of projectile var hitFixtures = _world.TestPointAll(Position); foreach (var f in hitFixtures) { if (f.Body.UserData != null) { HandleCollision((CollisionDataObject)f.Body.UserData, Vector2.Zero); } } } if (futurePos != Position) { _world.RayCast(RayCastCallback, Position, futurePos); } }
public override void _PhysicsProcess(float delta) { var d = 2f; if (_isBeingKnockedback) { if (LinearVelocity.Length() <= d) { _isBeingKnockedback = false; } else { return; } } if (!isChasing()) { return; } try { var toTarget = GlobalPosition.DirectionTo(_chasing.GlobalPosition); LinearVelocity = toTarget.Normalized() * 100; PlayAnimation(DirectionService.VelocityToDirection(LinearVelocity)); } catch (ObjectDisposedException e) { _chasing = null; } }
private void ApplyLinear(float delta) { Vector3 force = GetLinearAction(); Vector3 dirForce = Transform.basis.Xform(force); ApplyCentralImpulse(dirForce * acceleration * delta); Vector3 lin_vel = LinearVelocity.Normalized(); Vector3 remainder = lin_vel - dirForce.Normalized(); ApplyCentralImpulse(remainder * -accelerationDampening); }
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); } }
public void Serialize(BitWriter bw) { bw.Write(Sleeping); Position.Serialize(bw); Rotation.SerializeFixed(bw); if (!Sleeping) { LinearVelocity.Serialize(bw); AngularVelocity.Serialize(bw); } }
public override void _PhysicsProcess(float delta) { if (_picked) { var axis = (_touchPos - GlobalPosition + _offset.Rotated(GlobalRotation)).Normalized(); LinearVelocity += axis * _acceleration * delta; if (LinearVelocity.Length() > _VelocityLimit) { LinearVelocity = LinearVelocity.Clamped(_VelocityLimit); } } }
public void MergeFrom(NavigationRequest other) { if (other == null) { return; } if (other.TimeStamp != 0D) { TimeStamp = other.TimeStamp; } if (other.position_ != null) { if (position_ == null) { Position = new global::Navigation.Vec3(); } Position.MergeFrom(other.Position); } if (other.orientation_ != null) { if (orientation_ == null) { Orientation = new global::Navigation.Quaternion(); } Orientation.MergeFrom(other.Orientation); } if (other.linearVelocity_ != null) { if (linearVelocity_ == null) { LinearVelocity = new global::Navigation.Vec3(); } LinearVelocity.MergeFrom(other.LinearVelocity); } if (other.angularVelocity_ != null) { if (angularVelocity_ == null) { AngularVelocity = new global::Navigation.Vec3(); } AngularVelocity.MergeFrom(other.AngularVelocity); } if (other.VesselName.Length != 0) { VesselName = other.VesselName; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); }
/// <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; } }
public override int GetHashCode() { int hash = 1; if (header_ != null) { hash ^= Header.GetHashCode(); } if (MeasurementTime != 0D) { hash ^= MeasurementTime.GetHashCode(); } if (Type != 0) { hash ^= Type.GetHashCode(); } if (position_ != null) { hash ^= Position.GetHashCode(); } if (eulerAngles_ != null) { hash ^= EulerAngles.GetHashCode(); } if (linearVelocity_ != null) { hash ^= LinearVelocity.GetHashCode(); } if (angularVelocity_ != null) { hash ^= AngularVelocity.GetHashCode(); } if (linearAcceleration_ != null) { hash ^= LinearAcceleration.GetHashCode(); } hash ^= positionCovariance_.GetHashCode(); hash ^= eulerAnglesCovariance_.GetHashCode(); hash ^= linearVelocityCovariance_.GetHashCode(); hash ^= angularVelocityCovariance_.GetHashCode(); hash ^= linearAccelerationCovariance_.GetHashCode(); return(hash); }
public override int GetHashCode() { int hash = 1; if (position_ != null) { hash ^= Position.GetHashCode(); } if (orientation_ != null) { hash ^= Orientation.GetHashCode(); } if (linearVelocity_ != null) { hash ^= LinearVelocity.GetHashCode(); } if (linearAcceleration_ != null) { hash ^= LinearAcceleration.GetHashCode(); } if (angularVelocity_ != null) { hash ^= AngularVelocity.GetHashCode(); } if (Heading != 0D) { hash ^= Heading.GetHashCode(); } if (linearAccelerationVrf_ != null) { hash ^= LinearAccelerationVrf.GetHashCode(); } if (angularVelocityVrf_ != null) { hash ^= AngularVelocityVrf.GetHashCode(); } if (eulerAngles_ != null) { hash ^= EulerAngles.GetHashCode(); } return(hash); }
public SpeedInfo getSpeed() { Vector2 direction = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation)); float angleCos = 0; if (LinearVelocity.Length() != 0 && direction.Length() != 0) { angleCos = getAngleCos(LinearVelocity, direction); } Vector2 speed = direction * angleCos * LinearVelocity.Length(); return(new SpeedInfo() { speed = speed, sideSpeed = LinearVelocity - speed, direction = direction, angleCos = angleCos }); }
public void Serialize(BitWriter bw, UInt32 netVersion) { bw.Write(Sleeping); Position.Serialize(bw, netVersion); if (netVersion >= 7) { ((Quaternion)Rotation).Serialize(bw); } else { ((Vector3D)Rotation).SerializeFixed(bw); } if (!Sleeping) { LinearVelocity.Serialize(bw, netVersion); AngularVelocity.Serialize(bw, netVersion); } }
/// <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); }
//update the rigidbodies position based on currently applied force, velocity, and gravity public void Step(float dt, Vector2D gravity) { //tick the cooldown if (multiUseCooldown > 0.0f) { multiUseCooldown -= dt; } //only update position if the object can move if (moveable) { Vector2D acceleration = Force / Mass; if (obeysGravity) { acceleration += gravity; } //update velocity, locking it below maximum speed LinearVelocity = LinearVelocity + acceleration * dt; if (LinearVelocity.Length() > maxSpeed) { LinearVelocity = LinearVelocity.Normalised() * maxSpeed; } //Update position based on velocity (uses Runge Kutta integration) Vector2D k1 = LinearVelocity + acceleration * dt; Vector2D k2 = LinearVelocity + k1 * (dt / 2); Vector2D k3 = LinearVelocity + k2 * (dt / 2); Vector2D k4 = LinearVelocity + k3 * dt; SetPosition(Position + (k1 + k2 * 2 + k3 * 2 + k4) * (dt / 6)); //reset force Force.X = 0; Force.Y = 0; //reset collision information (assumes collision detection will take place immediately after stepping all rigidbodies) otherBody = null; collisionNormal = null; } }
// Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(float delta) { // Get all Node bodies that are currently colliding with the Ball Godot.Collections.Array bodies = GetCollidingBodies(); // The base level class is Node2D, this is why the body variable is being initiliazed as the Node2D type foreach (Node2D body in bodies) { // Check if the collided body is a StaticBody2D type and if the Node is part of the "Bricks" group if (body is StaticBody2D hit && hit.IsInGroup("Bricks")) { // Get the World Node and increment the Score by 10 GetNode <World>("/root/World").Score += 10; // Queue Node for deletion at the end of the current frame hit.QueueFree(); } // Check if the Node's name is "Paddle" if (body.Name.Equals("Paddle")) { // Get the speed at which the Ball is travelling float currentSpeed = LinearVelocity.Length(); // Reference to the anchor right below the Paddle object Position2D anchor = body.GetNode <Position2D>("Anchor"); // Get the direction that the ball is travelling in relative to the anchor Vector2 direction = Position - anchor.GlobalPosition; // Normalize (value of 0-1) the direction and multiply it by the minimum value of the current speed + the speedup constant, or the maximum speed Vector2 boostVelocity = direction.Normalized() * Math.Min(currentSpeed + speedUp, MAXSPEED); // Set the Ball's LinearVelocity to the new velocity LinearVelocity = boostVelocity; } } // If the position of the Ball's Y position exceeds the extend of the ViewPort's Y position if (Position.y > GetViewportRect().End.y) { // Queue the Ball for deletion QueueFree(); } }
private void LookFollow(PhysicsDirectBodyState state, Transform currentTransform, Vector3 targetPosition) { var myPosition = currentTransform.origin; var dist = (myPosition - targetPosition).Length(); var _targetDir = myPosition - (myPosition - targetPosition).Normalized(); var targetDir = currentTransform.XformInv(_targetDir); var forward = targetDir.Dot(new Vector3(0, 0, 1)); var rightn = targetDir.Dot(new Vector3(1, 0, 0)); var upn = targetDir.Dot(new Vector3(0, 1, 0)); currentTransform.origin = new Vector3(); float spiral = dist * 0.01f; var worldVelDir = LinearVelocity.Normalized(); var worldTargetDir = currentTransform.Xform(targetDir); var turnRate = 30.0f; if (forward > 0.99f) { GetNode <Particles>("Particles").Emitting = true; var correction = ((worldTargetDir - worldVelDir) * 20.0f) + (Transform.basis.z * 100); state.ApplyCentralImpulse(correction * state.GetStep()); } else { GetNode <Particles>("Particles").Emitting = false; spiral = 0; turnRate = 5; var correction = (worldTargetDir - worldVelDir) * 40.0f; state.ApplyCentralImpulse(correction * state.GetStep()); } float ss = (float)Math.Sin(TTL * 10.0f) * spiral; float cs = (float)Math.Cos(TTL * 10.0f) * spiral; var turn = new Vector3(-upn + ss, rightn - cs, 0) / turnRate; turn = Transform.Xform(turn) - Transform.origin; state.SetAngularVelocity(turn / state.GetStep()); }
/// <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); }
// Called every frame. 'delta' is the elapsed time since the previous frame. public override void _PhysicsProcess(float delta) { //If we dont have a target then return out of the method if (target == null) { return; } //Impliment movement here hahaha pproblem for future Gerrie? dont know yet Vector2 moveDir = target.Position - Position; moveDir = moveDir.Normalized(); ApplyImpulse(moveDir, moveDir * speed); //AddForce(moveDir, moveDir * speed); if (Mathf.Abs(LinearVelocity.x) > maxSpeed || Mathf.Abs(LinearVelocity.y) > maxSpeed) { Vector2 newSpeed = LinearVelocity.Normalized(); newSpeed *= maxSpeed; LinearVelocity = newSpeed; } }
public void Serialize(BitWriter bw, UInt32 netVersion) { bw.Write(Sleeping); Position.Serialize(bw, netVersion); if (netVersion >= 7) { bw.Write(Unknown1); } Rotation.SerializeFixed(bw, netVersion); if (netVersion >= 7) { bw.Write(Unknown2); } if (!Sleeping) { LinearVelocity.Serialize(bw, netVersion); AngularVelocity.Serialize(bw, netVersion); } }
protected override void Update(float dt) { if (TimeDeath > 0 && TimeDeath < World.Time) { Die(); } if (World.DistanceOutOfBounds(Position) > 0) { var speed = LinearVelocity.Length(); if (Position != Vector2.Zero) { LinearVelocity = Vector2.Normalize(Vector2.Zero - Position) * speed; } } if (Drag != 0) { LinearVelocity *= (1 - Drag * dt); } base.Update(dt); }
void TriggerJumpDrive() { var overlaps = overlapArea2D.GetOverlappingAreas(); foreach (Area2D area in overlaps) { if (area is WarpGate) { WarpGate warpGate = area as WarpGate; string departureSolarSystemName = CurrentSolarSystemName; bool warpSuccess = warpGate.TryTeleportShip(this, out string arrivalSolarSystemName, out float jumpCost); if (warpSuccess) { float jumpSpeedOverLimit = Mathf.Max(0, LinearVelocity.Length() - safeJumpSpeed); ReceiveDamage(jumpSpeedOverLimit * jumpVelocityDamageMultiplier); RecordJumpCost(jumpCost); //GD.Print("Jumpcost: " + jumpCost); OnShipWarped?.Invoke(this, departureSolarSystemName, arrivalSolarSystemName); } } } }
public void SetZeroVelocities() { LinearVelocity.Set(0.0F, 0.0F, 0.0F); AngularVelocity.Set(0.0F, 0.0F, 0.0F); }
/* * private void MarkDetecting(ObservableEntity e) { * long id = e.EntityId; * if (EntitiesDetecting.ContainsKey(id)) { * Log.Error("Already added " + id, "MarkDetecting"); * return; * } * * Log.Error("Adding " + id, "MarkDetecting"); * EntitiesDetecting.Add(id, e); * e.MarkDetectedBy(this); * } * * private void UnmarkDetecting(ObservableEntity e) { * long id = e.EntityId; * if (!EntitiesDetecting.ContainsKey(id)) { * Log.Error("Not stored " + id, "UnmarkDetecting"); * return; * } * * Log.Error("Removing " + id, "UnmarkDetecting"); * EntitiesDetecting.Remove(id); * e.UnmarkDetectedBy(this); * } * * private void UnmarkDetectingAll() { * Log.Trace("Unmarking all Detected entities", "UnmarkDetectingAll"); * foreach (ObservableEntity e in EntitiesDetecting.Values) { * e.UnmarkDetectedBy(this); * } * EntitiesDetecting.Clear(); * } * * private void MarkReceivingFrom(ObservableEntity e) { * long id = e.EntityId; * if (EntitiesReceivingFrom.ContainsKey(id)) { * Log.Error("Already added " + id, "ReceivingFrom"); * return; * } * * Log.Error("Adding " + id, "ReceivingFrom"); * EntitiesReceivingFrom.Add(id, e); * e.MarkBroadcastingTo(this); * } * * private void UnmarkReceivingFrom(ObservableEntity e) { * long id = e.EntityId; * if (!EntitiesReceivingFrom.ContainsKey(id)) { * Log.Error("Not stored " + id, "UnmarkReceivingFrom"); * return; * } * * Log.Error("Removing " + id, "UnmarkReceivingFrom"); * EntitiesReceivingFrom.Remove(id); * e.UnmarkBroadcastingTo(this); * } * * private void UnmarkReceivingAll() { * Log.Trace("Unmarking all comm receiving entities", "UnmarkReceivingAll"); * foreach (ObservableEntity e in EntitiesReceivingFrom.Values) { * e.UnmarkBroadcastingTo(this); * } * EntitiesReceivingFrom.Clear(); * } */ #endregion #region Describe public String ObservationDetails() { String result = ""; // Ids result += DisplayName + "\" - " + EntityId + "\n"; // Owners // TODO: show owner names instead of playerIds result += " Owners: TODO\n"; /* * if (BigOwners != null) { * result += " Owners: " + String.Join(", ", BigOwners) + "\n"; * } * else { * Log.Error("Grid had null BigOwners", "ReceiveRevealedGridsResponse"); * } * */ // Position result += " Position: " + Position.ToRoundedString() + "\n"; // Control if (IsControlled) { result += " Controlled:\n"; if (IsMoving) { result += " Moving at " + System.Math.Truncate(LinearVelocity.Length()) + " m/s"; } else if (RecentlyMoved) { result += " Recently moved until " + RecentlyMovedEnds; } result += "\n"; } else { result += " Not Controlled. (Shouldn't be viewing anything.)\n"; } // Last check details if (!PreviouslyObserving) { result += " Hasn't yet had an observe check.\n"; } //else { result += " Last View Check at pos: " + LastObservingPosition.ToRoundedString() + "\n"; result += " Distance from last view check: " + DistanceSinceLastObservingCheck + "\n"; result += " Last View Check at time: " + LastObservingTime.ToLocalTime() + "\n"; result += " View radius: " + ViewDistance + "\n"; result += " Viewed entities: \n"; //} // TODO: fetch the entities ingame on client side so we can have their details foreach (long id in EntitiesViewing.Keys) { result += " " + id + "\n"; } return(result); }
public String ConcealDetails() { // Revealed entities cannot be concealed if they // Are controlled (i.e. moving) // Are near a controlled entity // Are "working" (refining, assembling, oxy creating, battery charging) // Are needed as a spawn point for a logged-in player String result = ""; // Ids result += "\"" + DisplayName + "\" - " + EntityId + "\n"; // Owners // TODO: show owner names instead of playerIds result += " Owners: TODO\n"; /* * if (BigOwners != null) { * result += " Owners: " + String.Join(", ", BigOwners) + "\n"; * } * else { * Log.Error("Grid had null BigOwners", "ReceiveRevealedGridsResponse"); * } * */ // Position result += " Position: " + Position.ToRoundedString() + "\n"; // Concealability if (IsConcealable) { result += " Concealable:\n"; //return result; } else { result += " Not concealable:\n"; } //result += " Frequently Updated:\n"; if (OldEnoughForConceal) { result += " Y Not recently revealed\n"; } else { result += " N Too recently revealed\n"; } // Control if (IsControlled) { result += " N Controlled:\n"; if (IsPiloted) { result += " Piloted"; } else if (IsMoving) { result += " Moving at " + System.Math.Truncate(LinearVelocity.Length()) + " m/s"; } else if (RecentlyMoved) { result += " Recently moved until " + RecentlyMovedEnds; } result += "\n"; } else { result += " Y Not Controlled.\n"; } // Observed if (IsObserved) { result += " N Observed by:\n"; foreach (long id in EntitiesViewedBy.Keys) { result += " " + id + "\n"; } } else { result += " Y Not Observed.\n"; } // Spawn // TODO: show owner names instead of playerIds // TODO: actually implement updates to these details if (NeededForSpawn) { result += " N Needed for spawn.\n"; /* * result += " Needed as a spawn point by:\n"; * foreach (long id in SpawnablePlayers) { * result += " " + id; * } */ } else { result += " Y Not Needed for spawn.\n"; } //result += " Infrequently Updated:\n"; // Working // TODO: send block entity ids // TODO: show block types instead of entity Ids if (IsProducing) { result += " N Producing:\n"; //foreach (long id in ProductionBlocks.Keys) { // result += " " + id + "\n"; //} } else { result += " Y Not Producing.\n"; } if (IsChargingBatteries) { result += " N Charging Batteries.\n"; } else { result += " Y Not Charging Batteries.\n"; } // NearAsteroid if (IsInAsteroid) { result += " N Inside Asteroid.\n"; } else { result += " Y Not in Asteroid.\n"; } // Blocked if (IsRevealBlocked) { result += " N Entities within bounding box.\n"; } else { result += " Y No entities in bounding box.\n"; } return(result); }
/// <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; }