• 2D shoot 'em up
SDL2 Santa game tutorial 🎅
SDL2 Shooter 3 tutorial
The Legend of Edgar 1.36
SDL2 map editor tutorial [UPDATED]
TBFTSS: The Pandoran War - Amiga OS4 Port
— An old-school isometric game —
Having a mini map that we can consult while playing our game would be a small win, as it would allow us to more easily locate the items that we have to collect. Our mini map in this case is going to be limited to the current zone we're in, rather than the map as a whole. Even so, it will provide useful information.
Extract the archive, run cmake CMakeLists.txt, followed by make, and then use ./isometric11 to run the code. You will see a window open like the one above. Play the game as normal. Notice the mini map in the bottom right-hand corner of the screen. It shows the current zone. Blue and dark green squares represent water and ground, while grey squares show walls. The bright green square shows Purple Guy's position. White squares show items that can be collected, and yellow squares represent the exit tiles for the zone. Once you're finished, close the window to exit.
Inspecting the code
Adding in our mini map is a very simple task, as we'll see.
Let's start with defs.h:
We've added another entity flag. EF_SHOW_ON_MINI_MAP will be used to indicate that the entity should display on our mini map. We don't want all entities to show up, as things like trees will litter it, and just create unnecessary noise.
With that done, let's add the flag to the applicable entities. Starting with purpleGuy.c, and initPurpleGuy:
We're setting EF_SHOW_ON_MINI_MAP to his `flags`.
We do the same for glass.c, and initGlass:
Here, we need to ensure that we're including both EF_SHADOW and EF_SHOW_ON_MINI_MAP for the glass's `flags`.
knife.c and initKnife comes next:
EF_SHOW_ON_MINI_MAP is set it the knife's `flags`. The same is done for redbox.c, in initRedBox:
And in spill.c, in initSpill:
Now that we've added the flag to the entities we wish to affect, let's head over to hud.c, where we actually render our mini map.
We've updated drawHud by adding in a couple of new lines:
We're calling drawMiniMap and drawMiniMapEntites, two new functions that we'll look at now, starting with drawMiniMap:
It might look like there's a lot going on here, but it's actually very simple. First up, we're setting up an SDL_Rect (`rect`), that will be used to render each tile. `rect`'s width (`w`) and height (`h`) are set to MINI_MAP_SQUARE_SIZE - 1. MINI_MAP_SQUARE_SIZE is defined as 8. By setting the width and height as one pixel less, we can create a nice grid effect later on.
We then setup to for-loops, `x` and `z`, to go from 0 to MAP_RENDER_SIZE. For each iteration of the loop, we're setting two variables, `mx` and `mz`, to the values of `x` and `z`, plus the camera position. This will allow us to select the correct tile from the map, based on the camera's location. With that done, we set `rect`'s `x` and `y` coordinates. All this operation is doing is positioning our mini map in the bottom-right corner, 15 pixels away from the edges of the screen. MAP_RENDER_SIZE and MINI_MAP_SQUARE_SIZE are used in this calculation, meaning that if we change these values, our mini map will continue to render in the bottom-right of the screen, still 15 pixels from the edges. Note how we're using MINI_MAP_SQUARE_SIZE here, while our rect's width and height are one pixel less. Again, this creates the grid effect, due to the spacing.
We then test the value of the tile at `mx` and `mz`, and set the values of three variables, `r`, `g`, `b` (red, green blue), as appropriate. Empty tiles (-1) will be light grey, tiles at the edge will be yellow (to match our exit tiles), water tiles a dark blue, ground tiles a dark green, and walls are grey. Finally, we're calling drawRect (found in draw.c), passing over `rect`'s `x`, `y`, `w`, and `h`, and the `r`, `g`, `b` values that we set before.
So, in short, we're looping through all the tiles in the current zone, setting the position and dimensions of an SDL_Rect, setting some rgb values, and drawing the rectangle to screen. Once again, there is an optimisation that could happen here. We need not do this all the time, as we could render to a separate texture when the zone changes, and simply draw that simple image. Our game isn't complicated at the moment, so the performance hit in minimal.
Now onto drawMiniMapEntites:
A shorter function than drawMiniMap, but one that shows some commonalities. We're once again making use of an SDL_Rect (`rect`) to hold our size and position. This time, we're looping through all the entities in the world, and testing whether they have the EF_SHOW_ON_MINI_MAP flag set. If so, we're next testing if they're in our current zone, via a call to isWithinISOScreen, and then proceeding to draw them. For their positions, we're assigning two variables, `x` and `z`, their positions, including camera offset, and then setting the rgb values. If the current entity (`e`) is the player, we're setting the rgb to be a bright green. Otherwise, we're setting them as a light grey. Then, as with drawMiniMap, we're calling drawRect, and passing over our SDL_Rect and rgb values.
And there you go! Nice and simple. We now have a mini map that will help us to spot items that might be hidden by the world view, and also give us an overview of the current zone. Something like this would come in especially handy if our zones were much larger, allowing us to take in more of the surrounding area.
Our game is more or less done. So, in the final part we'll be popping in some sound and music, to act as the finishing touches.
The source code for all parts of this tutorial (including assets) is available for purchase:
It is also available as part of the SDL2 tutorial bundle: