# Server-side real time position calculation based on destination position - C#

What I want to achieve is to calculate the real object position based on its speed and a destination position. In my server, I have a MapInstance that have a list of MapLayer that have MapRegions.

To resume we have:

• 1 MapInstance
• N MapLayers
• X MapRegions

Each MapInstance will update in an asynchronous task all his map layers and the common object such as NPCs and the MapLayer will update his regions of entities (monsters/items).

On the client side, when I click somewhere on the map, it sends a packet to the server with the destination position. Then, on the server-side I receive the position and set the entity.Movable.DestinationPosition property.

As I said earlier, each map instance are updated in an asynchronous task and updates the map layers and common entities. My problem is, my realtime position calculation formula is wrong somewhere, and I can't find where.

To understand the problem, there is some inputs:

• Entity speed: 0.08 (8%)
• Position and DestinationPosition are Vector3 (class) instance, where X, Y and Z are properties.

This is my code:

public void StartUpdateTask(int delay)
{
{
const double FrameRatePerSeconds = 0.66666f;
double previousTime = Environment.TickCount;

while (true)
{
if (this._cancellationToken.IsCancellationRequested)
break;

double currentTime = Environment.TickCount;
double deltaTime = currentTime - previousTime;
previousTime = currentTime;

this.GameTime = (deltaTime * FrameRatePerSeconds) / 1000f;

lock (SyncRoot)
{
foreach (var entity in this.Entities)
Walk(entity);

foreach (var mapLayer in this._layers)
mapLayer.Update();
}

}
}, this._cancellationToken);
}


mapLayer.Update() method:

public override void Update()
{
this.GameTime = this.Parent.GameTime;

foreach (var entity in this.Entities)
Walk(entity);

foreach (var region in this._regions)
{
if (region.IsActive && region is IMapRespawnRegion respawnRegion)
{
foreach (var entity in respawnRegion.Entities)
{
Walk(entity);
}
}
}
}


And the calculation formula:

private void Walk(IMovableEntity entity)
{
if (entity.MovableComponent.DestinationPosition.IsZero())
return;

if (entity.MovableComponent.DestinationPosition.IsInCircle(entity.Object.Position, 0.1f))
{
entity.MovableComponent.HasArrived = true;
entity.MovableComponent.DestinationPosition.Reset();
}
else
{
entity.MovableComponent.HasArrived = false;
double entitySpeed = entity.MovableComponent.Speed * entity.MovableComponent.SpeedFactor;
double speed = ((entitySpeed * 100f) * entity.Context.GameTime);
float distanceX = entity.MovableComponent.DestinationPosition.X - entity.Object.Position.X;
float distanceZ = entity.MovableComponent.DestinationPosition.Z - entity.Object.Position.Z;
double distance = Math.Sqrt(distanceX * distanceX + distanceZ * distanceZ);

// Normalize
double deltaX = distanceX / distance;
double deltaZ = distanceZ / distance;
double offsetX = deltaX * speed;
double offsetZ = deltaZ * speed;

if (Math.Abs(offsetX) > Math.Abs(distanceX))
offsetX = distanceX;
if (Math.Abs(offsetZ) > Math.Abs(distanceZ))
offsetZ = distanceZ;

entity.Object.Position.X += (float)offsetX;
entity.Object.Position.Z += (float)offsetZ;
}
}


With this current formula, my players and monsters arrive to destination between 1-2 seconds sooner on the server side compared to the client-side... Do you have any idea what I'm doing wrong ? Appriciate if someone could guide me and explain me how to solve my problem. :-)

Thank you

• So if I understand correctly, I need to defined my FrameRatePerSeconds to 60 and then substract the tick delta in order to have a fixed timestep right? but what if the substraction is negative? like: 60fps - 73ticks this will give me -13 and my delay will not work. Should I use a Math.Abs on the result or i'm missing something on my calculation? – Eastrall Jan 15 '19 at 19:27
• I see, it makes sense thought. But now, since we've touched the GameTime property, the speed is now wrong. I had double speed = ((entitySpeed * 100f) * entity.Context.GameTime);where entitySpeed is 0.08. Should I change the formula, or i forgot something on the GameTime calculation ? – Eastrall Jan 16 '19 at 7:38