ID:1461120
 
(See the best response by DarkCampainger.)
Honestly, I've never toyed with making minimaps. I'm just now getting around to it, and I'm having issues.

I searched around and tried out the few libraries, but to no avail. I can't find anything around that really gives a good explanation on how to do it, either. I can't even find something that will give you a good, simple screenshot of the map at runtime (CauTion had something that almost worked, but when it saw houses that were bigger than 32x32, it just shrunk the house to 32x32 and put the shrunken icon everywhere the house covered).

I am trying to understand the mentality and process of creating a minimap. I'd like it to be detailed, so having a screenshot of the map would be great (But I'm not sure how to go about doing that without the tons of effort and time required to walk around the world screenshotting every few steps).

I understand that a second map should be used and I understand how to put objects on the screen (And I saw Ter13's post on using blank objects to move the screen around, but I haven't toyed with that so that concept is still a bit fuzzy), but that is about it.

Can anyone offer any insight, since all of the resources available concerning minimaps are fairly outdated?
I'd think that putting nodes for things like houses, and checking the distance between mobs and the nodes would be a step in the process. Other than that, I'm not sure. This is something that I'd like to see, as well.
Albro1 wrote:
Honestly, I've never toyed with making minimaps. I'm just now getting around to it, and I'm having issues.

I searched around and tried out the few libraries, but to no avail. I can't find anything around that really gives a good explanation on how to do it, either. I can't even find something that will give you a good, simple screenshot of the map at runtime (CauTion had something that almost worked, but when it saw houses that were bigger than 32x32, it just shrunk the house to 32x32 and put the shrunken icon everywhere the house covered).

I am trying to understand the mentality and process of creating a minimap. I'd like it to be detailed, so having a screenshot of the map would be great (But I'm not sure how to go about doing that without the tons of effort and time required to walk around the world screenshotting every few steps).

I understand that a second map should be used and I understand how to put objects on the screen (And I saw Ter13's post on using blank objects to move the screen around, but I haven't toyed with that so that concept is still a bit fuzzy), but that is about it.

Can anyone offer any insight, since all of the resources available concerning minimaps are fairly outdated?

Your best bet is to not generate a screenshot of the map at runtime, honestly. It's a lot more work than it's worth. I strongly prefer to create my own minimap images by hand and then use dynamic markers instead of actually generating a tile-perfect minimap.
Is there any resources that I can look to to learn the method of creating the minimap with at least somewhat accurate sizes for objects bigger than 32x32?
Bump.
Best response
I can't remember any. Is there any part of it that you're specifically struggling with?

There's only two catches I can think of off the top of my head. First, depending on how you loop through the world, you may need to track which objects (but not turfs) have already been drawn to the minimap (because larger objects may be contained in multiple tiles). Second, you'll need to check icon.Width() and icon.Height() when considering how much space it takes up.

If you implement those two changes in CauTi0N's code, it should work for larger icons.
I've never attempted a minimap before, so honestly I'm struggling with understanding the process of making one. If I understand the concept better, I may be able to do something.
Bump.

What is the minimap? It is a custom icon, made at runtime? If so, I haven't fiddled with anything of that sort before and that would be where my confusion lies. Right now I just don't know where one starts when constructing a minimap so I cannot figure out the parts that trouble me.
Typically, a minimap feature is handled in two parts.

First, there's the "offline" portion of generating an image (or grid of images) to represent your map at a smaller scale. I say offline as in "when you're developing the game" and not at runtime, because generating the image can be very intensive, and it's not uncommon to want to do a few manual touch-ups on the image. So you add a debug verb or something to your game that generates the image and saves it, and just run that whenever you update your map. Then you can just include the image in your resources and not worry about long start-up times.

For most BYOND games, a 1-tile to 1-pixel ratio is usually enough, and the minimap drawing is just implemented as drawing a pixel for each tile. You can see plenty of examples of this in the resources section.

If you want a minimap at a larger scale, where you actually use the icons on the map to create it instead of a solid-color, you'll have to do some extra work. You can look at my Get Flat Icon library to get an idea of how to blend together icons if you're not sure where to start.

Once you have the image generated, the second part is just a matter of putting it in a second map control or label (to effectively "crop" the large image to a smaller view of it) and positioning it relative to the player's position in the world.
Using your library, I got something working! However, if I try to use this procedure to generate anything above 127x127 tiles, I get an error with the Crop() procedure, so I guess the icon can only be so big? How should I go about generating a map of a 400x400 map?

proc
generate_minimap(z = 1, client/c)
var
icon/final = icon('\Icons/blank.dmi')
icon/current // the current icon being grabbed

_x = world.maxx
_y = world.maxy
_s = world.icon_size

// each icon will be scaled down, its width and height divided by 16. __s is the size of each icon (assuming it is world.icon_size normally and not a big icon)
// __s will basically be the distance each tile will be shifted by to make a map
__s = _s/16


x = 1 // starting coordinates for the first tile.
y = 1

final.Crop(1, 1, 128*32,128*32) // resize the final icon to fit everything
for(var/___x = 1 to 127)

x = 1 + ((___x -1)*__s)

for(var/___y = 1 to 127)

y = 1 + ((___y-1)*__s)
var/turf/t = locate(___x, ___y, z)
current = icon('\Icons/blank.dmi')
current = getFlatIcon(t)
current.Scale(__s, __s)
final.Blend(current, ICON_OVERLAY, x, y)

for(var/atom/a in t)
if(ismob(a)) continue
if(!a.icon) continue
if(a.icon == '\Icons/Turfs/Grass_.dmi') continue
if(a.icon == '\Icons/Turfs/flowers ect.dmi') continue
var/icon/k = icon('\Icons/blank.dmi')
k = icon(a.icon, a.icon_state)
var/w = k.Width(), h=k.Height()
k.Scale(w/16, h/16)
final.Blend(k, ICON_OVERLAY, a.x*__s, a.y*__s)


if(c) c << browse(final)

Instead of using Crop, wouldn't scale be more suited?
In response to Ss4toby
Ss4toby wrote:
Instead of using Crop, wouldn't scale be more suited?

Scale seems to have the same 4096 limitation, so why waste time scaling a blank icon?

@Albro1
If you plan to have very large maps, you can break your minimap into multiple images and dynamically load the pieces at runtime. If you just need to fit a little more, you can generate them in pieces but then stitch them together outside of BYOND. Kozuma3 has also reported being able to use animated frames to get past this limit (and then presumably renaming the icon to PNG), although you may not have control over the placement of the tiles that way. This thread has some more info:
http://www.byond.com/forum/?post=1462838

If you have any oversized turfs, you may want to scale the turf icons based on current's width and height instead of __s. Also, for oversized icons in general, you should iterate through your world in top-right to bottom-left order, so that icons larger than one tile aren't drawn over by later turfs (it looks like your trees are a little cut up?).
In response to DarkCampainger
The trees are actually perfect. They have a shadow underneath them, which is why they look funny.

As for my turfs, I have no turfs over 32x32. Only objects are bigger.
In response to DarkCampainger
Alright! Using this code, I was able to generate my minimap, one 100x100 section at a time, and just place them together in Photoshop. Strangely, one section of the map caused problems and I cannot figure out why, but I split that one section into 4 separately generated sections, and it ended up generating in a way that I could work with. Also, I find it funny that the icon can be resized to any size you want, it can just only contain so much inside it. The way this procedure is set up, all of the pieces of the map were placed as if they were taken straight out of the map, not in the lower left corner.

var/list/minimaps = list()
proc
generate_minimap(z = 1, client/c, sx=1, sy=1, ex=100, ey=100)
c << "Generating minimap for Z level [z] from tiles [sx],[sy] to [ex],[ey]..."
var
icon/final = icon('\Icons/blank.dmi')
icon/current // the current icon being grabbed

start_x = sx
start_y = sy
_x = ex
_y = ey
_s = world.icon_size

// each icon will be scaled down, its width and height divided by 16. __s is the size of each icon (assuming it is world.icon_size normally and not a big icon)
// __s will basically be the distance each tile will be shifted by to make a map
__s = _s/16


x = 1 // starting coordinates for the first tile.
y = 1
c << "Variables generated..."

final.Crop((start_x-1)*32, (start_y-1)*32, (_x+1)*32,(_y+1)*32) // resize the final icon to fit everything
c << "Icon file resized..."
c << "Starting looping..."
for(var/___x = start_x to _x)

x = 1 + ((___x -1)*__s)

for(var/___y = start_y to _y)

y = 1 + ((___y-1)*__s)
var/turf/t = locate(___x, ___y, z)
current = icon('\Icons/blank.dmi')
current = getFlatIcon(t)
current.Scale(__s, __s)
final.Blend(current, ICON_OVERLAY, x, y)

for(var/atom/a in t)
if(ismob(a)) continue
if(!a.icon) continue
if(a.icon == '\Icons/Turfs/Grass_.dmi') continue
if(a.icon == '\Icons/Turfs/flowers ect.dmi') continue
var/icon/k = icon('\Icons/blank.dmi')
k = icon(a.icon, a.icon_state)
var/w = k.Width(), h=k.Height()
k.Scale(w/16, h/16)
final.Blend(k, ICON_OVERLAY, a.x*__s, a.y*__s)
c << "Finished looping and blending..."

minimaps += final

c << "Icon added to minimaps list."


mob
verb
generate_Minimap(x1 as num, y1 as num, x2 as num, y2 as num)
generate_minimap(1, usr.client, x1, y1, x2, y2)

minimaps()
usr << minimaps.len

save_minimap(index = 1 as num)
var/icon/i = minimaps[index]
usr << ftp(i)


In response to Albro1
Albro1 wrote:
[code]

Looks equivalent to mine to a degree. xD