Hi,
I have a small annoying problem with my draw loop where the zoom function results in very noticeable jerking motion of all the rendered sprites. Here is the whole method and the lerp function :
protected override void Draw(GameTime gameTime)
{
int adjustedZoomLevel = 60 + ZoomLevel;
// DRAW THE DYNAMIC OBJECTS
Color spriteColor;
if (UI.DisplayUI.isFocused == false)
{
spriteColor = Color.White;
}
else
{
spriteColor = Color.Gray;
}
GraphicsDevice.Clear(Color.Green);
point vP = new point((graphics.PreferredBackBufferWidth/ adjustedZoomLevel), ((graphics.PreferredBackBufferHeight / adjustedZoomLevel)));
point vPo2 = new point(((graphics.PreferredBackBufferWidth) / ((adjustedZoomLevel) * 2) ) , (((graphics.PreferredBackBufferHeight) / ((adjustedZoomLevel) * 2)) ));
point lastViewPort =
GameZod.GameZod.Game.lastCamera - vPo2;
point viewPort =
GameZod.GameZod.Game.Camera - vPo2;
spriteBatch.Begin(samplerState: SamplerState.PointClamp);
for (int x = 0; x < vP.x; x++)
{
for (int y = 0; y < vP.y; y++)
{
point pos = new point((x + viewPort.x), (y + viewPort.y));
if (pos.x < GameZod.GameZod.Game.map.size & pos.y < GameZod.GameZod.Game.map.size & pos.x > 0 & pos.y > 0)
if (GameZod.GameZod.Game.map.Dobjects[pos.x, pos.y] != null)
{
spriteBatch.Draw(
GameZod.GameZod.Game.map.Dobjects[pos.x, pos.y].texture,
new Rectangle(
((int)(
lerp(
(GameZod.GameZod.Game.map.Dobjects[pos.x, pos.y].position.x) * adjustedZoomLevel,
(GameZod.GameZod.Game.map.Dobjects[pos.x, pos.y].lastPosition.x) * adjustedZoomLevel,
gameTimeElapsed / 500f) -
lerp(
viewPort.x * adjustedZoomLevel,
lastViewPort.x * adjustedZoomLevel,
gameTimeElapsed / 500f)
)
)
,
((int)(
lerp(
(GameZod.GameZod.Game.map.Dobjects[pos.x, pos.y].position.y) * adjustedZoomLevel,
(GameZod.GameZod.Game.map.Dobjects[pos.x, pos.y].lastPosition.y) * adjustedZoomLevel,
gameTimeElapsed / 500f) -
lerp(
viewPort.y * adjustedZoomLevel,
lastViewPort.y * adjustedZoomLevel,
gameTimeElapsed / 500f)
)
),
(int)adjustedZoomLevel, (int)adjustedZoomLevel),
new Rectangle(0, 0, 30, 30),
spriteColor);
}
}
}
//END DYNAMIC OBJECTS
//INTERFACE BEGIN
for (int i = UI.DisplayUI.UIDisplayList.Count - 1; i >= 0; i--)
{
if (UI.DisplayUI.isFocused == true & i == 0)
{
UI.DisplayUI.UIDisplayList[i].draw(spriteBatch, Color.White);
}
else
{
UI.DisplayUI.UIDisplayList[i].draw(spriteBatch, Color.Gray);
}
}
spriteBatch.Draw(UI.DisplayUI.MouseTexture,
new Rectangle(mouseState.X, mouseState.Y, 20, 20),
new Rectangle(0, 0, 30, 30),
Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
float lerp(float p1, float po, float t)
{
return (1 - t) * po + t * p1;
}
and the arguments for the Draw function is : (Texture, Destination rectangle, Origin Rectangle, Color); this is done with MonoGame (XNA)
The zoomlevel is changed in increment of +-1.
I really think the problem is contained in this method, everything is perfectly fine, but zooming shifts the position of the screen to the upper right and then clamps back to the lower right, ever shifting up until it clamp back down again.
What I've done :
- Ruled out the fact that it's tile based and may shift everytime new tiles enter the frame
- Tried to calculate the delta between the last zoom and the current zoom in terms of the rectangle's position, then subtracting it from the position
- Isolate the problem to a particular function
- 'center' the coordinate system more accurately to the center of the screen; this has no effect on the issue
I really hope it's just something really obvious I missed, spent 6h on this and made 0 progress.