This update will be a fair bit shorter than usual due to being busy with Nirion's development, trying to get a polished demo done, and not having a lot of new things to show. Next month should be back to normal. This month I've mostly been working on a little more level design, reworking one of the bosses, the minimap and sound design. In this post I'll go over my approach to Nirion's minimap.

Design

The minimap in Nirion looks like this:


As you can see, it roughly shows the shapes of rooms that have been discovered, uses colours to give the player information about the room(green for save room, flashing white for current room), and shows door connections as narrow red paths. The purpose of the map in Nirion is to help the player get around the world, but without being distracting or too "useful".

Personally I dislike minimaps that are either too detailed or show precise locations of moving objects(like the player), because I tend to look at the minimap in place of the actual game world a lot of the time. At first I did try out having an indicator(red dot) for the player as they moved around, as well as revealing tiles on the map as the player explored:



I didn't really like how this was feeling while playing. Revealing the map tile by tile felt like a chore and made you feel like you had to reveal every single one. After trying a few things, I settled on revealing rooms all at once(still hiding secret areas until the player walks into them). I also removed the player indicator and then just "pulsed" the current room white instead. I think this feels a lot better, and I'm fairly happy with it as a whole.

Implementation

Implementing the minimap took me a few days. I tried out a few different ways of rendering the rooms, as well as a few different ways of storing the map reveal data. One thing I decided on pretty early(and stuck with) was storing the map data as separate chunks that could go into the asset system.

When the game map is saved(there's only one map in Nirion) the asset preprocessor analyses the world and builds a collection of minimap tiles for each world area. A minimap tile consists of minimal information such as the tile's position, flags(is it a wall, passage way, etc), and if it's a secret area. Determining if a tile is a wall or not is just done by checking it's neighbors. Since a wall is just a white block, no "wall direction" needs to be considered. Passage ways(narrow red paths) are already being determined for gameplay anyway, since any entities in a passage way needs to render at a lower layer, so if a tile is part of a passage way(and not a wall), it gets a red colour. A world area is a chunk of the world that is loaded together in Nirion. These are what world areas look like in the editor, they are outlined in purple:



These tiles are saved as their own asset and can be loaded independently of each other and the actual world data. When a minimap asset is loaded, a vertex buffer is created which just stores position, colour and room ID per tile. Room ID is needed while rendering to fade in/out hidden rooms, since the minimap chunk is rendered in a single draw call. Right now the tiles are just instanced rectangles. This seems to work well enough for now, and gives a look that I'm happy with.

Saving minimap progress was done very naively while I was still working out how I was going to approach the design. In the save game data, I would store a list of world area reveal data structures, which themselves would have lists of tile reveal data structures. When the player reveals a new tile, I would just do two linear searches over these lists to check if the tile was already recorded. If not, it would be added.

I definitely had some concerns about this, but it become a great deal easier once I removed tile based revealing. Now all that has to be stored is which world areas have been discovered, and within those which rooms and secrets have been revealed. Now all that's required(when updating map progress, and rendering each chunk) is a linear search over revealed world areas. Maybe I'll have to make this more sophisticated later on, but it works fine for now.

I tried a few different ways of rendering and storing the minimap tile data. One approach I tried was to create a smoothed concave hull around the vertices of the tiles and then triangulate the hull. I used this algorithm: https://www.researchgate.net/publ...egion_occupied_by_a_set_of_points, which I had already implemented previously for another purpose. I got this working, but it a few issues. For one, the resulting mesh was much less consistent than a tile based approach. It looked a little too smooth for the art style of the game, and also had varying behavior based on the room shape that the walls formed. Another issue was with holes:



These were completely left out(which makes sense, since it's just a concave hull and only makes one shape around the entire collection of points). The last issue was with displaying information like passage ways and walls. At the end of the process, the information about whether a tile was a wall or a passage way etc was lost, and all I had was one giant mesh to work with.

Besides the rendering of the actual map itself, some objects can be seen and displayed on the minimap as a dot. This happens with upgrades. If they're seen, they show up as a white dot on the map, and when they're collected they change to an outlined dot. An entity can simply add itself to the list of minimap objects for the world area that it's in, and this will be rendered on top of the map.



Conclusion

That's basically all there was to the minimap. It was more about trying out different designs until I got something I was happy with. Right now it's just being rendered in the top left corner of the screen, but eventually(maybe after the demo) I'll use it to make a full sized map screen that can be zoomed in/out.



Thanks for reading! Like I said, next month I should be back to doing larger updates. Right now I'm currently doing a lot of sound design, since that's been somewhat neglected for a while. Since my last blog post I have started posting on my twitter, so for more frequent and mostly visual updates, you can follow here: https://twitter.com/broscoe8

Again, let me know if you have any questions!