Sunday, January 20, 2008

Display Model

The first thing I decided to code for Mirage was my display model. This is what I call how I store my tile objects internally, and how I use that model to display the tiles to the screen. I figured this would be important to decide early on, as it creates the base on which the entire game will grow.

I initially stored tiles in a two-dimensional array. This made the most sense from an initial standpoint since most if not all roguelikes appear to the user as a two-dimensional grid. Things worked fine and I soon had the hero moving around a screen of empty tiles. I realized early on that a two-dimensional grid would create a lot of problems. When the hero (or any actor for that matter) moved from one position to the other I had to change the old position's graphic back to what it was previously. The new position would have the same problem once I moved off of it. In and of itself this is a simple problem, and one that could be solved in numerous ways. I knew going on that this would create some headaches for me down the road, so I decided to take a little extra time and think about the problem.

After much internal struggle I decided that instead of a two-dimensional grid, I could move to a three-dimensional grid. I'm not sure of most other roguelike's display models, but having typed that it may seem like throwing an extra dimension at the problem was asking for even more headache.

I'll explain why I have chosen this solution. Imagine a cube of tiles. Imagine also that the terrain tiles are on the bottom layer of this cube. Somewhere on the second layer the hero is stored. If the three-dimensional grid is traversed by column, and from the top down, then the problem above disappears. Once a tile is encountered and drawn during traversal then we just go to the next column, instead of drawing any tiles underneath it. Of course I could also add some logic to each tile so that you could ask it whether we should draw tiles beneath it, instead of just assuming.

I have an enumerator that represents my layers. I can easily add to this enumerator to add more layers to the system. Since I access layers using this enumerator, adding new layers has no effect to preexisting code, neither does changing the order of the layers within the enumerator. In essence this enumerator controls completely how objects are drawn within the game.

I have an environment layer that I hope to use to implement clouds. Clouds will be on the top layer (at a reduced alpha value), and will allow drawing of tiles beneath themselves. This will give tiles below the clouds a nice bluish tint. This is just one of many ideas that could be added to this system with little trouble and consequence to existing code.

I'm anxious to hear what others think about this solution to my problem. I would also like to know how others have implemented display models in their games, in the hopes that I can make mine more robust. I think it is a simple solution that provides great flexibility.

5 comments:

Kamil said...

Hi,
Good luck with your project. RL is a nice game to write, easy at the beginning to start yet with some challenging stuff in the middle.

At the moment I'm making my second RL (you can see first at my site www.kamilt.1k.pl in mobile games section).

As for your ideas, I don't know if your game is 2D or 3D, but I don't think that clouds are good for 2D game, of course you should still implement them at some point to see how this idea work, but I think that it will distract player from the game.

Layered grid is a good way to go. In my Sigmore Mines, every cell in the grid have dynamic array of cell layers. In Sigmore Mines 2 I have separated units and items from cell's floor representation, but it's more a cosmetic change.

rsalsman said...

Thank you for the well wishes! I'll be sure to check out your RL projects.

My game is 2d, and displayed with text like a standard roguelike game. It's possible that the clouds could be distracting, but the plan is to have them almost transparent. I'll implement them and determine whether they add more than they tak away.

Arathalion said...

Out of interest, what language/platform are you working in? Are you looking to do anything novel/new/revolutionary, or have a particular theme, or will it be a good ol' generic RL?
Either way, you'll get some troll on RGRD telling you it's rubbish - I can't wait to see how badly they flame me when I announce the language I'm using in my RL ;)

Yeah, I'm working on a RL too.
For actually storing my dungeon tiles, I have a 3d array to contain some of the info, even though my display method is purely 2d. Other bits are totally separate (such as my player location is stored as 2 ints, instead of having a boolean field as part of the 3d array - it seemed unnecessary. I only have 1 player, but with a 3d array, I'd have ~1000 boolean fields!

My layers go (working upwards) floor/walls, interactables (stairs, doors, shops), treasure, traps, monsters, player, visibility, so they are like a series of 2d arrays, like you say, and I work through each layer checking whether it needs displaying.

Most of the things in the layers cover a very small amount of the dungeon (for example, there might be 10 traps on the whole level), so most of it is broken out into dedicated arrays which only have a reference to the dungeon position. Similarly, I've left a boolean tag in my 3d dungeon array so I know whether I need to look up the full details or can just skip it because it's empty - that's what I found most efficient. Otherwise you either have loads of useless, detailed but empty 3d array, or you have to search through say, all the monsters, to check whether there's one on the dungeon coordinate your code is looking at.

There was some interesting discussion on this on rgrd a few weeks ago (see http://angband.oook.cz/rgrd.php?showpost=114873 and replies)

rsalsman said...

I'm coding the game in C++, and I'm using a game making SDK that I'm extremely familiar with (Playground SDK).

I'll be explaining more in subsequent posts about the specifics of the game. It's purely a 2d display with ascii (no graphics). It's a standard fantasy setting for now, but the engine I'm building is generic enough to allow for great customization in themes and settings. All of my content will be stored in outside files. The biggest difference between my game and traditional roguelikes is the fact that it is in real-time, which is also something I'll be highlighting in future posts.

Enne Walker said...

For what it's worth, Dungeon Crawl (Stone Soup and vanilla) has "layers" for dungeon elements, items, and monsters. For elements that are less frequently used (like clouds) there are just flat arrays of these elements, rather than cooking them all out into a sparse layer.