Map waypoint position problem

BlitzMax Forums/BlitzMax Programming/Map waypoint position problem

GNS(Posted 2013) [#1]
In my game I have a world map screen that draws a map texture as well as several icons that indicate waypoints/'points of interest' on the map. The player can also zoom (using SetScale()) into/out of the map via the mousewheel.

My issue is that I'm having trouble adjusting the positions of the waypoint icons to account for the change in zoom level.

The effect I'm going for is similar to that of Google Maps, where zooming into the map adjusts the position of map markers such that they maintain their accurate (but relative) position on the map.

To illustrate my issue, I've thrown a quick example together:
Graphics(640, 480, 0)

Global zoomLevel:Float = 1.0

While Not KeyHit(KEY_ESCAPE) Or AppTerminate()
	Cls
	
	Local mz:Int = MouseZSpeed()
	
	If mz > 0
		zoomLevel :+ 0.1
	Else If mz < 0
		zoomLevel :- 0.1
	EndIf
	
	SetScale(zoomLevel, zoomLevel)
	SetColor(128, 255, 128)
	
	' draw 'land' map (green rect)
	DrawRect(100, 240, 330, 100)
	
	SetScale(1.0, 1.0)
	SetColor(255, 255, 255)
	
	' draw point of interest (white rect)
	DrawRect(350, 250, 8, 8)
	
	Flip
Wend


In the example, the green rect represents my world map and the white rect represents a waypoint/point of interest. You can zoom in/out via the mousewheel. As the zoom level changes, notice that the position of the waypoint no longer represents a relative position on the map (obviously, as it's hard-coded to a certain position; making the position relative is where I'm stumbling).


Cruis.In(Posted 2013) [#2]
First since I think you have a top down view. Let's say your centre of the screen is your fixed point no matter where in your world you are. Do this by setting the origin at your centre. I've left it out because it isn't needed for the example.

Then you scale everything based on the origin, and add it to your drawing coordinates.

To scale everything based on the origin (which you set as the centre of your viewing area) you take away your origins coordinates from the x and y each entity you draw your game world such as waypoints, add it back to the origin and multiply it by your zoom level. Then draw your images at the offsets.

E.G.

offsetx = origin + (rectangle1x - origin) * zoom level
offsety = origin + (rectangle1y - origin) * zoom level

Since in the end each of your different objects being different will have different draw methods, you draw at the offset. So the offset gets and keeps your screen drawing coordinates separate from the world coordinates.

In the below example I use the centre of the screen as the origin without using set origin, that's why I use the graphics width and height/2, to leave your posted code as is, so you can see your white box keeps its relative position even though you zoomed in on the green map.

So basically for my code below, I've replaced 'origin' in the above mentioned forumula to graphicswidth/2 and graphicsheight/2



Last edited 2013


Banshee(Posted 2013) [#3]
Rather than move the waypoint, only move the view - you've approached the problem backwards.

If a waypoint is always at a fixed position you dont need to reposition it... You simply adjust its position and size by the current view scale.

eg:

waypointX = 50
waypointZ = 50

mainloop
draw waypointX * scale , waypointZ * scale
scale = mousewheel
endmainloop

Then all you have to do is offset for the centre of the screen

draw ( waypointX * scale ) - ( graphicsWidth()/2 ) , ( waypointZ * scale ) - ( graphicsHeight() / 2 )


Cruis.In(Posted 2013) [#4]
the waypoint is just being drawn to accommodate the scale. The position on the map doesn't change. The real X-Y doesn't changed, it is only the drawing coordinates.

I just used graphics width to focus on the screen on the middle, but his focus for zooming should be the centre or wherever his origin, or whatever his origin is based on.


GNS(Posted 2013) [#5]
@Cruis.In - That works perfectly, thanks!

I should've been a bit clearer with my example. In my game, the world map takes up the entire screen and effectively -is- the "game screen". All player interaction occurs on the world map. The position of the waypoints on the world map is their "real" position in the world.

My next task will be zooming at the mouse position rather than at the center of the map so I'm assuming my origin point will be the point at which I'm zooming to.


Cruis.In(Posted 2013) [#6]
I am not sure what you intend can be done with the 'fake' zoom we've implemented. Since you aren't zooming in on the viewport itself. We still have to fake it.

I assume you want to do something like an RTS game where when you zoom in, it zooms to the area where your mouse cursor is at.

That should be simple, if I am correct in interpreting you.

Try that, it is going to get wonky using the rectangles etc, this should pan too as long as you are zoomed in past the 1:1 ratio.




GNS(Posted 2013) [#7]
The first few seconds of these videos show the effect I'm looking for:
http://www.youtube.com/watch?v=Rg8vRgxGpCU&t=2m23s
http://www.youtube.com/watch?v=wwMlJXrFseI&t=0m45s


GNS(Posted 2013) [#8]
Had a few minutes to tinker with this some more today. Zooming to the mouse cursor is proving to be problematic. I assumed I could simply use the 'zoom point' as my origin which would give me a draw offset for both the map and the waypoints but that doesn't seem to be the case.


Cruis.In(Posted 2013) [#9]
Yeah using the zoom point just will draw everything in relation to that :)

What about panning and then zooming? Or you don't want the view to be automatically panned?

Panning as in the map shifts around depending on where your mouse cursor is, either left right up or down. It's quite useful, well for me, to see peep an entirely different section of the adjacent game world.


Cruis.In(Posted 2013) [#10]
i have not found the perfect balance yet but im pretty sure it might be possible if you move the drawing left right up or down with setorigin, just move it by the value you are zoomig. So as you zoom, it offsets all the drawing in the opposite way creating the effect of moving to it. This is how I implemented panning.




GNS(Posted 2013) [#11]
Panning will happen if the player's mouse is at the edges of the screen and the zoomLevel > 1.0. When zoomLevel = 1.0 the entire map is visible on the screen so there's no need to pan.

Zooming in will also auto-pan to the mouse cursor I suppose. In the second video I posted above, you can see the effect.


Cruis.In(Posted 2013) [#12]
zooming into the mouse cursor has to include some form of auto panning to that direction where the mouse cursor is at yeah.


Scaremonger(Posted 2013) [#13]
This may be of interest:
http://www.blitzbasic.com/Community/posts.php?topic=80234#909091


GNS(Posted 2013) [#14]
Ah, thanks Scaremonger. That's exactly the effect I'm going for. Nifty.