public void NewLerp(PositionUpdateData data) { var vel = new Vector2(data.XVel, data.YVel); var pos = new Vector2(data.XPos, data.YPos); var currentState = new PositionState(AttachedShip.AngularVelocity, AttachedShip.Rotation, AttachedShip.LinearVelocity, AttachedShip.Position); var nextState = new PositionState(data.AngularVelocity, data.Rotation, vel, pos); var newState = LerpState(currentState, nextState); AttachedShip.AngularVelocity = newState.AngularVelocity; AttachedShip.Rotation = newState.Rotation; AttachedShip.LinearVelocity = newState.LinearVelocity; AttachedShip.Position = newState.Position; }
public PositionLerpState LerpPosition(PositionState current, PositionState next) { var currentPosition = current.Position; var incomingPosition = next.Position; var incomingVelocity = next.LinearVelocity; var incomingSpeed = incomingVelocity.Length(); // Prevent divide by zero. var speed = incomingSpeed == 0f ? 0.00001f : incomingSpeed; // Our algorithm looks a half second into the future as it's target. var distanceToSeekIntoFuture = 0.5f; var distanceInTimespan = speed * distanceToSeekIntoFuture; var velocityAngle = GetAngleFromVector(incomingVelocity); // Where the server's client will be in a half second. var serverFutureX = incomingPosition.X + (distanceInTimespan * (float)Math.Sin(velocityAngle)); var serverFutureY = incomingPosition.Y + (distanceInTimespan * (float)Math.Cos(velocityAngle)); // Where we will be in a half second. var ourFutureX = currentPosition.X + (distanceInTimespan * (float)Math.Sin(velocityAngle)); var ourFutureY = currentPosition.Y + (distanceInTimespan * (float)Math.Cos(velocityAngle)); var serverFuture = new Vector2(serverFutureX, serverFutureY); var ourFuture = new Vector2(ourFutureX, ourFutureY); // How far our ship is from where the server's client will be. var distanceFromServerFuture = Vector2.Distance(currentPosition, serverFuture) + 0.0001f; var distanceFromOurFuture = Vector2.Distance(currentPosition, ourFuture) + 0.0001f; // Grab the different between our target and the server's, then shift us to point at that. var angleDifference = FindAngle(currentPosition, serverFuture, ourFuture); var desiredAngle = velocityAngle - angleDifference; var desiredFutureX = currentPosition.X + (distanceFromServerFuture * (float)Math.Sin(desiredAngle)); var desiredFutureY = currentPosition.Y + (distanceFromServerFuture * (float)Math.Cos(desiredAngle)); var desiredFuture = new Vector2(desiredFutureX, desiredFutureY); // Adjust the speed based on how far we are from the desired future position. var speedAdjustmentFactor = Vector2.Distance(currentPosition, desiredFuture) / distanceFromOurFuture; // Keep things relative to half a second. var desiredSpeed = speed * speedAdjustmentFactor; // Nudge velocity angle to point at destination point. var desiredVelocityX = desiredSpeed * (float)Math.Sin(desiredAngle); var desiredVelocityY = desiredSpeed * (float)Math.Cos(desiredAngle); // Number of seconds until lag distance is covered var timeToMeet = distanceFromServerFuture / speed; // Snap if we're too de-synced. if (timeToMeet >= 1f) { var distanceBetweenPositions = Vector2.Distance(currentPosition, incomingPosition) * 2f + 0.0001f; if (distanceBetweenPositions > distanceFromServerFuture) { velocityAngle = GetAngleFromVector(incomingPosition - currentPosition); desiredVelocityX = distanceBetweenPositions * (float)Math.Sin(velocityAngle); desiredVelocityY = distanceBetweenPositions * (float)Math.Cos(velocityAngle); } else { currentPosition = incomingPosition; desiredVelocityX = incomingVelocity.X; desiredVelocityY = incomingVelocity.Y; } } return(new PositionLerpState(new Vector2(desiredVelocityX, desiredVelocityY), currentPosition)); }
public PositionState LerpState(PositionState current, PositionState next) { var newLerpPosition = LerpPosition(current, next); return(new PositionState(next.AngularVelocity, next.Rotation, newLerpPosition.Velocity, newLerpPosition.Position)); }