ID:151929
 
Suppose I have a 50x50 map, but the player is viewing it through a 15x15 screen. The player needs to be able to move around to any part of the map without using the arrow keys (NOTE: The player in this scenario is simply the client's eye, not an actual mob).

Also note that at any given time certain tiles are invisible, which unfortunately means they can't be interacted with, and that sort of inhibits the idea of right-clicking to center the player's view on a tile. There doesn't seem to be any way to know which coordinates the player clicked on when clicking on an area or a screen object background.

So I'm looking for some other ideas on how to allow the player to navigate the large map through their small window without it being a pain in the butt to do. Ideally I'd like to use sliders just as the DM Map Editor uses, but that isn't supported right now, and a minimap would require far more trouble that I'm willing to put into this.
Instead of making the tiles completely invisible, you could just cover them with an object represented by a black square. You get the same effect, but you can click on it.

As for sliders, you could implement that yourself. Put a couple slider objects on the client's screen and program them to slide your view around when you drag them.
obj/slider
var
const
VERTICAL = 1
HORIZONTAL = 2
// direction = either VERTICAL or HORIZONTAL
direction
New(client/C, direction)
if(C) C.screen += src
src.direction = direction
proc/slide(x,y)
switch(direction)
if(VERTICAL)
// reaction to slide
if(HORIZONTAL)
// reaction to slide
MouseDrop(atom/overObject)
var
// the following gives (x,y) pair relative to eye
x = overObject.x - usr.client.eye.x
y = overObject.y - usr.client.eye.y

// you might want to manipulate x and y here to get them into whatever format you want

slide(x,y)

Something along those lines anyway. And if you want them to see the slider sliding as it's dragged and not just when it's dropped, you can override MouseDrag() as well.

The minimap shouldn't be too bad either. You just have 1 pixel represent 1 tile, and you can represent it by a 2x2 icon grid. Just loop through the world, and draw a pixel on the grid to represent the turf.
minimap
var
obj/base = new
list/images[2][2]

New()
images[1][1] = icon('blank.dmi')
images[1][2] = icon('blank.dmi')
images[2][1] = icon('blank.dmi')
images[2][2] = icon('blank.dmi')

proc/plotPixel(rgb, x, y)
var
icon/I
imageX; imageY
if(x > 32)
x -= 32
imageX = 2
else imageX = 1
if(y > 32)
y -= 32
imageY = 2
else imageY = 1

I = images[imageX][imageY]
I.DrawBox(rgb, x, y)

proc/setupImage(screen_loc)
var/image/I

I = image(images[1][1])
I.pixel_x = -16; I.pixel_y = -16
base.overlays += I

I = image(images[1][2])
I.pixel_x = -16; I.pixel_y = 16
base.overlays += I

I = image(images[2][1])
I.pixel_x = 16; I.pixel_y = -16
base.overlays += I

I = image(images[2][2])
I.pixel_x = 16; I.pixel_y = 16
base.overlays += I

base.screen_loc = screen_loc

Unless I'm forgetting something, that should be about all you need to represent the minimap. That's not the best implementation, but it's only required to be 2x2 for you, so it's good enough. It would probably be better if it were scalable, which wouldn't be too difficult a modification.

Either way, you could then set up the map's representation with a function.
var/minimap/minimap = new
var/list/turf2rgb = list(\
/turf/grass = rgb(0,255,0),\
/turf/water = rgb(0,0,255))

proc/setupMinimap()
var
T1 = locate(1,1,1)
T2 = locate(world.maxx, world.maxy, 1)

for(var/turf/T in block(T1, T2))
minimap.plotPixel(turf2rgb[T.type], T.x, T.y)
minimap.setupImage("2,2")

client/proc/displayMinimap()
screen += minimap.base

Detecting where the minimap is clicked and moving to the appropriate place is the easy part, so I won't bother with that.
You could make your own slider.
Use BYOND's built-in mouse procs.
You would need 102 objects though (2 sliders + 100 slider drop-zones).
In response to Jemai1
Jemai1 wrote:
You would need 102 objects though (2 sliders + 100 slider drop-zones).

You can just use the objects present on the map to determine drop location. Just compare the location of the object under the mouse to the eye to find where it is from the center of your view and therefor where it would be on the screen_loc coordinates.
In response to Loduwijk
I bet the slider is not 32x32 pixels in size. Scaling should be considered. Drag and Drop effects won't be handled easily especially if the map/eye updates at real time.
In response to Jemai1
Jemai1 wrote:
I bet the slider is not 32x32 pixels in size. Scaling should be considered. Drag and Drop effects won't be handled easily especially if the map/eye updates at real time.

True enough, but this comes to the point where you either do what you want and live with the problems or you move to a different system. I have gotten to the point where I don't feel like settling for less, nor do I want to spend a week doing something that takes ten minutes with a different language.

Either way, yes, I had overlooked what you mentioned.