Creating Mini Map of Isometric game world
Shri

Gio,

 

I was going to take a shot at another gui element.

A mini map for an isometric game.

This kind of thing could double as a range finder, target finder, map, etc.

So, it seems like it would have a general enough use.

Anyway, I was looking through the wade docs and don't have a good idea of where to start.

 

Init a second iso engine but draw to a different layer ?

Write code  that duplicates all the iso drawing stuff but draw to a different layer ?

Do some sort of screen capture and then shrink the image down ?

 

If you could point me in a direction, I would appreciate it.

 

thanks for any help,

Shri

Comments 1 to 15 (30 total)
Gio

Hi Shri

 

That sounds like a very good idea, I'm sure it would be extremely useful in lots of situations.

 

The best way to do it I suppose depends on whether you want to make it static or dynamic. Static is fast, dynamic is cool - I don't know which aspect is more important, on a mobile device probably being fast would be preferable, but it depends.

 

Using some sort of screen capture for the static map would be sensible - interestingly, screen capture and drawing the screen or a layer to a virtual image (that you can the use in a sprite) are features that we are adding to WADE 1.2. It's about 10 days away, so I don't know if you want to wait for that. That would be the easiest way (really just a few lines of code), but not necessarily the fastest, especially for dynamic maps.

 

A slightly more complicated but probably faster implementation (which you could do with the current version too) would be this:

 

You could call wade.getSpritesInArea(area, layer) for an area that covers the whole world (or the part that you want to show), and for the terrain layer (wade.iso.getTerrainLayerId()). This would give you an array with all the terrain sprites. For each of them, you could get its position and size, and multiply them by a scale factor of your choice, and draw them to an image using Sprite.drawToImage() - you can pass in a position and scale factor when drawing to an image.

 

You could then use this image to create a new Sprite, which is your mini map.

 

If you want a dynamic map, you do this thing again every frame (or every so often, or whenever the map changes), but you don't need to create a new minimap sprite every time (drawing to the source image of the existing sprite will update it automatically).

 

It would be very easy then to give it different shapes, using a composite_() draw function, so you could have circular minimaps for example. It would be really cool, if you want to do it I'll be happy to help with some code.

Shri

Gio,

 

Thanks for the help.

I think the dynamic version you suggested is what I had in mind.

I have started fooling around with a demo.

 

You mentioned wade.iso.getTerrainLayerId() as returning an array ? Doesn't that just return a number (the layer id) ?

I have looked through the iso documentation and I don't see anything that returns an array with all the terrain sprites ?

That would be nice, otherwise, it seems I would have to 'walk' the grid and call wade.iso.getTileData(). Then position and scale.

 

I'm also a little vague on how Sprite.drawToImage() works. Specifically the virtual path parameter.

 

Anyway, I will continue to fool around with it a let you know when I have something.

 

have a nice weekend,

 

cheers,

Shri

Gio

Sorry for the confusion, I meant:

  • wade.iso.getTerrainLayerId() returns a number, the layer id, as you said
  • wade.getSpritesInArea(area, layer) is a function of the core WADE module, not the isometric module (that's why it isn't in the isometric documentation :) )

In fact, there is no reason to limit this to isometric games only - you could do it so that you pass in one or more layer id's and a radius, and it draws a map of everything that's in those layers and within the radius.

 

Regarding drawToImage - I know it can be a bit confusing, but it's a really powerful feature. The idea is that you draw to a sprite to an image, like this:

mySprite.drawToImage('test.png')

Which will draw your sprite to 'test.png. The point is that 'test.png' isn't necessarily a file on your disk - it doesn't need to be a physical file at all. You could use any name for the image you are drawing to, it isn't actually going to physically create or write to a file - that's why it's a virtual path. But you can then use this image as if it was a real image, to create new sprites. The cool thing is that you can draw to an image multiple times without necessarily having to clear what's there. You can use a second parameter (a boolean) to tell WADE that you want to completely overwrite the image with that name (true), or just write on top of it (false).

 

You can the pass a few additional parameters to this function, if you want to customize the drawing process: you can change the scale and position, rotation, skew and blend mode. In your case, you only care about the scale and position.

 

So something along the lines of this:

var generateMap = function(layerId, radius){	// create a transparent sprite that's as big as the map	var transparent = new Sprite();	transparent.setDrawFunction(function() {}); // set a draw function that does nothing, it's a transparent sprite	transparent.setSize(miniMapSize.x, miniMapSize.y);		// draw the transparent sprite to our target image, overwriting anything that's there	// the true parameter implies taht the 'miniMap' image, if it exists, will be destroyed and re-created.	transparent.drawToImage('miniMap', true);		// define an area around the camera        var cameraPosition = wade.getCameraPosition();        var area = {minX: cameraPosition.x - radius, minY: cameraPosition.y - radius);		// get an array of sprites in the area        var sprites = wade.getSpritesInArea(area, layerId);		// draw all the sprites to the miniMap image (without recreating the 'miniMap' image)	for (var i=0; i<sprites.length; i++)	{	    // work out position and size and draw to the image            ......            sprites[i].drawToImage('miniMap', false, ...... )	}	}

After generating the map, when you want to use it, you simply do:

var mapSprite = new Sprite('miniMap');

This is just an example, but in reality it would be nice to have the option to use an array of layerId's, and be able to customize the map as much as possible (different width and height, but also different shapes)

Shri

Gio,

 

Thanks for the clarification and the code. After reading your email carefully, and fixing a couple of boneheaded programming errors, I was finally able to get something up and running.

 

I'm not sure what I am doing wrong on the transforms and offsets ?

Also, there is some wierdness going on when you resize or move the map ?

I have attached the zipped file of what I have so far.

 

cheers,

Shri

Gio

Hi Shri

 

I have tried your code, and it seems that there is a bug in Sprite.drawImage - sorry about that. It will be fixed in the next release, but in the meantime you can include this patch file I have attached (patch.js) just after loading wade.js

Elliot

Hey

 

I have spent some time playing with it, and noticed that even after applying Gio's patch (which made things better), the sprites didn't end up in the right position.

 

So I've changed one or two things. It took me a while to do all the math, but it seems correct now.

 

Gio, I have included wade and wade.iso in the zip file, is that a problem? If so, feel free to delete my attachment and I'll post it again without the engine files.

Gio

Elliot, thanks for your contribution.

 

Having wade and wade iso in the zip isn't a problem at all. In fact, it makes things easier for people who want to download the zip and try it, so please keep it that way.

Shri

Elliot,

 

Thanks for pitching in.

I downloaded your zip and tried and it looks excellent !

 

I didn't get anything done on it today because I started a slider control the other day while I was waiting to hear back from Gio.

I posted that and will have a look at improving the mini map tomorrow.

 

 

cheers

Shri

All,

 

I have been working on the minimap

- works with multiple layers, added some iso objects and they are on the map

- made the map configurable through a json file similar to the other gui stuff I have done

- map updates through a timeout loop

- general code cleanup and commenting

 

Between the engine patch and Elliot's help it was pretty easy to make progress.

 

I will continue to work on it, regarding the composite functions and some other stuff I think will make it better.

 

see post below for zip file

 

cheers

 

 

hermes

Nice!

 

I'd like to contribute too, but it's already really cool.

 

The new version is great for a fully dynamic map, but if you want a static (faster) map that doesn't need redrawing so often, you could draw a big map once, and then redraw the single map sprite every frame... having an option to do that would be brill, making it more useful for mobile games

Shri

All,

 

You can now set the shape of the mini map

Look at the composite field in the json file. Setting this to  "none" will give you a standard rectangular shaped map.

If you set the composite field to any other value, ex: "true", then you have to define a draw function for your transparent

sprite in the setGuiShape function. Then when the map sprites are drawn to your image buffer, the "souce-atop" composite

string will draw your map into your shape.

 

If that sounded like rambling nonsense, then just check out the the miniMap.js and  miniMapData.json files in the zip below.

When you run the demo, the minimap should have a circular shape and be in the bottom left corner.

 

I also added an effects field in the json file. If I have time, I will try to integrate image effects into this.

 

Hermes - you're more than welcome to contribute, but I didn't exactly follow what you meant in your post.

I suggest you simply download the zip, make changes with comments like  /* Hermes was here */ and then we can figure out how to reintegrate later.

 

cheers

hermes

OK, I realize my explanation above was somewhat confusing... I've downloaded the latest version and will now try adding the option I was talking about.

Shri

All,

 

Added the ability to apply image effects to the map.

Actually, it was so easy I didn't really have to do anything.

1. include the ifx plugin / library

2. modify the html test file to load the ifx plugin

3. add 3 lines of code to the miniMapTest file in the updataMiniMap function.

 

Gio, I figured it would be ok to add the ifx plugin because you were ok with the iso stuff.

If you run the demo now, the map appears in grayScale.

I have deleted the zip above and included it here.

 

cheers

Gio

OK, I downloaded it and had a quick go at changing a couple of things.

 

First of all, I wanted to say: great job! :) It's a really nice and useful thing.

 

Here's what I've changed:

 

  • I have updated patch.js to include a couple of other bug fixes that will be released for WADE 1.2 (but with the updated patch.js you get these bug fixes now).
  • You pass an options object, slightly different to the previous version:
    - width and height in pixel
    - it contains the layer id where you want to create the map sprite
  • The behavior creates a sprite that is then added to the parent scene object. So the user controls the position of the parent scene object directly to do whatever they like with the minimap (move it around, etc).
  • The update is managed internally by the behavior (using an onUpdate event)
  • You use the "effect" parameter in the map data to say which image effect you want to use. You can also omit it. If the user doesn't have the ifx plug-in, it will be ignored.
  • You pass the layers that you want to use to the behavior together  with the rest of the data (no need to call a separate function)
  • You pass all the options through onAddToScene, no need to call an initialize function

I believe this makes the minimap more "self-contained" and overall easier to use.

 

A couple of further improvements I'd like to suggest:

  • The API for the minimap behavior could be cleaner, at the moment it's all public, but you probably want things such as this.box and this.guiSize to be hidden from the user, so I'd make the things that you don't want to show local variables, rather than member variables, and expose only the things that the user is supposed to interact with.
  • If I understand what hermes said above, I think that may be a good idea (have an optoion to redraw the map less often, not every frame... but reposition the map sprite whenever the camera moves)... is that what you meant, hermes?

Regarding the ifx plugin: it's OK to include it in the zip, like the iso plug-in.

 

It's looking great, so keep it up :)

Elliot

Hi again

 

I had some time today, so I decided to implement the features that Gio and Hermes suggested. I found it a bit difficult and, since I ran out of time, I couldn't really clean up the code, so I apologize if it's a bit messy.

 

I have added these features:

 

1) an updateInterval option: this is how many seconds you want between each minimap update. If you set it to 0, it will never update the minimap. However, the minimap is now drawn to a larger sprite, so when you move, it shows you only the relevant portion of this larger sprite. If you move "too much" (beyond the area of the minimap that has been drawn to the larger sprite), it regenerates the minimap.

2) you can have an array of object names that you want to exclude from the minimap

3) following Gio's suggestion, I changed a lot of member variables into local variables, so the interface should be tidier

4) the minimap will not be regenerated if you haven't moved since the last time it was generated. But there is an option that you can set (forceUpdate) if you want to always regenerate it.

5) all the options that you pass to the minimap behavior are optional, i.e. there are default values.

 

I think the code still needs cleaning up and commenting (sorry, I didn't have enough time). Besides that, is there anything else that is worth adding or that you would like to add?

Post a reply
Add Attachment
Submit Reply
Login to Reply