Hello and welcome to the wonderful beginning of posts about how I am making my summer project: The Epic of Sadko the Street Performer. In these posts, I intend to get right down into the nuts and bolts of the game, and explain some design decisions as I come to them. This first post is going to be about the map system I have devised (on paper so far). I appreciate feedback. I’m always learning, and if you think I’m going about this the wrong way, please tell me! I don’t have the strongest grasp of design principles or conventions. This is precisely why I am doing this project. It is a learning and confidence inducing project for me. That’s why I don’t care if people see how I intend to implement things.
So I’m going to talk about my map system, today, but let me first explain what I’m using to make The Epic of Sadko. The language I know the strongest is C++, so I am making The Epic of Sadko in C++.
I am also using the Allegro game library to handle graphics, sound and input (plus whatever extra things it has like timers and fonts). I’ve used Allegro before in a plethora of test projects. It changes a bit every time I use it, but it is, overall, very easy to use and to understand the object models and functions. I chose to use Allegro because it is generally free of restrictions, it is familiar, and I am not well versed at the super low level programming skills required to make a graphics engine from scratch. Two years ago, I was following along with a book that described how to put an engine together for 2D games by encapsulating DirectX. I never finished with it because I kept wondering why I wouldn’t just use Allegro, which had done this instead, better, and for multiple platforms (Allegro works in XCode and Linux, with a few tweaks, if the wiki pages are to be believed).
So that’s what I’m using. This is what I am doing. My map system is going to consist of layers. I’m using six layers. The layers are drawn in the following order:
- Layer 1: Tiles
- Layer 2: Shadows
- Layer 3: Static Objects
- Layer 4: Dynamic Objects
- Layer 5: Effects
- Layer 6: GUI
Each of these layers will be classes that inherit a base class. That base class contains an STL vector of generic objects (which will be overridden with derived objects, depending on the layer). I chose a vector because Layer 3 and 4 may grow and shrink in size, so I wasn’t excited about using a regular array. I think STL adds a lot of overhead, from what I’ve heard, so I might need to simplify things. The layers also have some simple information such as a link to the layer above and layer(s) immediately below (I don’t think there will be more than one layer just below in this game, but I have planned for it just in case), as well as some offset information for drawing. The base class’s draw, update and input processors are pure virtual, so those are implemented at the derived class level. Next I’ll get into each layer and describe what I’m thinking of for each one.
The tile layer simply draws tiles at the appropriate place on the screen based on an offset. The layer consists of an 18×18 grid of top-down tiles (the maximum size of one room). I’ll have to figure out a viewport system for this eventually, in case people are using resolutions of less than 800×600. The objects just have references to tile bitmap data and an indication of where the tile should be drawn. The tiles also contain information important to the game: x and y location, and the tile’s height. The tile will be tinted darker if it is lower than the maximum height. I may decide to just have darker colored tiles, as I think that loading a larger tileset and copying from that would probably be faster than alpha blending the tiles, and I wouldn’t need to worry too much about overhead in the memory for the simple tilesets I’m likely to use.
The game is entirely top down, yet, as mentioned in the last layer, each tile has a height. The tinting is not likely to be enough to be able to tell that the height is physically different in the game world. The shadows are used to convey this information. The longer and darker the shadows, the greater the distance between levels. I know that I am breaking physics to have the shadows on all four sides of the tile at the same time, but I chose pure top-down so that I didn’t have to draw tiles that conveyed depth. After I decided on to-down, I decided that the main character would have the ability to climb and jump acrobatically, which meant there was going to be height.
Static Objects Layer
The static objects are those that obstruct but do not move. I should be able to animate them, but I don’t want to spend a lot of time drawing them if I don’t have to. The objects layers were the reason I moved to vectors instead of two-dimensional arrays for the layers. There will be far fewer objects on screen than there are tiles. If anyone thinks that the 2D array is faster, please let me know! Objects on the Static layer are impassible.
Dynamic Objects Layer
The Dynamic Objects Layer is where anything that moves around is drawn. The most common objects that will be drawn here are Sadko, the other characters, and enemies. Dynamic objects are impassible, because I can’t be certain of the drawing order for these objects. While it may make sense that, for example, a bird flies over Sadko’s head, I don’t know if Sadko will be drawn first or second, and so I’d rather just not allow this as an opportunity. This kind of thing can be done on the next layer.
The effects layer is for anything that I want to draw above the dynamic objects. Many of these will be effects, like weapon attacks, spells and overlays (maybe for trees). Many of these are intended to be on screen for just a short amount of time before destroying itself. The effects layer is completely passable. If an impassible effect needs to be made, it would be better done at a lower layer (perhaps an enemy summons a static object, for example).
Perhaps the simplest of the layers to describe. This is the overlay interface which takes up the sides of the screen, as well as any menus that may pop up, and the text box to convey messages. This layer will be the one that probably handles the most amount of input, though any layer can request input to check. I may disseminate the movement controls to the dynamic objects layer, as much of the data for movement will be found there and in parent layers.
So that’s my layer model. I would have a nice diagram for you, but my paint skills are rather bad. You will just have to imagine it. If you have any ideas of where I am going wrong with this, feel free to leave me a comment. I am highly receptive to criticism, provided that it points out why you think something is a problem (and perhaps what you would do differently).