Map Zoom Issue

BlitzMax Forums/BlitzMax Programming/Map Zoom Issue

therevills(Posted 2015) [#1]
I am trying to display a map that I can move around and zoom in. I've got most of it working, but when I zoom it is zooming based on the top left corner and I want it either where the mouse is or in the center of the screen.



Image: https://dl.dropboxusercontent.com/u/35103024/mx/bmx/map/map.zip

I know I need to either offset the mapX/mapY variables or change them when zooming, but I cant work out the math...


Brucey(Posted 2015) [#2]
This seems to work :
	Method UpdateZoom(delta:Float, mx:Float, my:Float)

		Local oldZoom:Float = zoom

		' coords relative to map
		Local mpx:Float = (mx - mapX) / zoom
		Local mpy:Float = (my - mapY) / zoom

		zoom :+ delta
		
		Local minScale:Float = SCREEN_WIDTH / MAP_SIZE

		If zoom < minScale Then zoom = minScale
		If zoom > 2 Then zoom = 2

		Local realDelta:Float = zoom - oldZoom

		mapX :- (mpx * realDelta)
		mapY :- (mpy * realDelta)

		rightBorder = -MAP_SIZE
		rightBorder :* zoom
		rightBorder :+ SCREEN_WIDTH

		bottomBorder = -MAP_SIZE
		bottomBorder :* zoom
		bottomBorder :+ SCREEN_HEIGHT
		
	EndMethod

Where mx and my are MouseX() and MosuseY()

.. but ...

... only if you comment out the lines :
mapX = Int(mapX)
...
mapY = Int(mapY)

in MoveMap().
Either that, or you'd have to introduce more variables to keep track of the real offsets.


Bobysait(Posted 2015) [#3]
Also, you should check your border tests position in your "movemap" method.
Not sure of that, but you seems to test borders before the updatezoom (where you actually update the borders)


therevills(Posted 2015) [#4]
Thanks a lot Brucey!! I did at one stage have something similar to the realDelta but didnt think of doing the offset on how you did it!

And thanks Boby, I've moved the UpdateZoom to the top of MoveMap.

Full updated code (with mouse over):



Kryzon(Posted 2015) [#5]
I'd suggest that you abstract that zoom and moving code into a "game viewport" concept.
Your function MoveMap is, conceptually, controlling the player's viewport.

- The game has a scene. A collection\tree of objects, each with their own properties -- the map, the tiles, the characters, the items.
- The game also has a view. The view is a class responsible for using the data and state stored in the scene to display all that to the user in some particular way (like rendering the tiles of the map, the characters etc.). It uses the application window for this.

The scene and the view are separate classes: you can change the view and how it displays the scene (zoom, screen ratio, rotation, offset etc.), and the scene will remain unchanged. You're not changing characters or tiles, just how the view will display these.
When the scene changes -- a character changes state, objects are created or destroyed etc. -- the view updates the game screen to reflect the latest changes (in a game you're usually always updating the screen anyway).

- - - - -

The way this works is that you can have multiple views onto the same scene. In an RTS game, for example, you have one view which used for the main screen. You also have a second view, that tiny radar \ minimap in the corner. They are both valid views that are displaying the same scene and interpreting the data stored in the scene in their own particular way.


Scaremonger(Posted 2015) [#6]
There was a similar post a few years back which might be of some interest:

Zoom-To-Cursor