# XNA 2D Tile Map zooming to arbitrary point [duplicate]

I'm working on a game in XNA with a 2D tilemap as the playfield. I'm using a spritebatch with a transformation matrix to provide movement and scaling of the playfield. I'm trying to add a zoom function, so the player can click anywhere on the screen and it will zoom in to that point. The issue is that when I increase or decrease the scale, the "focus" of the zoom is always at the top-left hand corner of the screen.

So unzoomed:

And when zoomed in (note the position of the chequered tile):

What I'd like to happen when the player zooms is that it zooms into the centre of the screen, like so: (I achieved this by moving the playfield around after zooming)

I realise that the way to do this is probably to add or subtract from the X/Y co-ordinates that get fed into the transformation matrix, and probably at a fraction of the scale, but I can't figure this out. Everything I try tends to result in crazy effects while zooming.

Ideally I'd like to be able to set any arbitrary point on the screen, and zoom to that point. Can you help?

The code of the Draw function:

   protected override void Draw(GameTime gameTime)
{
Matrix transformMatrix =
Matrix.CreateTranslation(-baseX, -baseY, 0) *
Matrix.CreateScale(baseR, baseR, 1) ;

GraphicsDevice.Clear(Color.CornflowerBlue);

// "World" spritebatch. Scaling applied.
spriteBatch.Begin(SpriteSortMode.FrontToBack, null, SamplerState.PointClamp, null, null, null, transformMatrix);

foreach (Vector3 Square in Squares)
spriteBatch.Draw(Textures[(int)Square.Z], new Vector2(Square.X, Square.Y), null, Color.White, 0, new Vector2(0, 0), 1, SpriteEffects.None, 0.82f);

base.Draw(gameTime);

spriteBatch.End();

// "UI" spritebatch. No scaling applied.
spriteBatch.Begin(SpriteSortMode.FrontToBack, null, SamplerState.PointClamp, null, null);
spriteBatch.Draw(Textures[0], new Vector2(ScreenMidX, ScreenMidY), null, Color.White, 0, new Vector2(0, 0), 1, SpriteEffects.None, 1f);

spriteBatch.DrawString(aFnt, "" + baseX, new Vector2(5, 0), Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.None, 1f);
spriteBatch.DrawString(aFnt, "" + baseY, new Vector2(100, 0), Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.None, 1f);
spriteBatch.End();
}


Full code available here: https://www.dropbox.com/s/zft5b20st8o7jv7/ZoomTest3.zip

Thanks for any help!

• This might help: gamedev.stackexchange.com/questions/29686/… Mar 5, 2014 at 14:28
• Try translating EVERYTHING by -mapWidth / 2 and -mapHeight / 2 before you scale.
– Ben
Mar 5, 2014 at 14:54
• @OriginalDaemon That looks very promising, I'll try that! Mar 5, 2014 at 15:30
• @OriginalDaemon that worked perfectly; if you post that link as an answer I'll accept Mar 5, 2014 at 23:39
• I think this counts as a duplicate of my question. However, you have described the problem better than me. So maybe we should vote to close this as a duplicate and you can edit my question to make it clearer. Mar 6, 2014 at 10:10