For this post I will be analyzing the structure and design decisions for my latest project, Arthur’s Grove (AG). Experience with previously failed projects has taught me to value simplicity above abstraction. The custom 2D engine powering AG is restricted to only producing games like AG, with the same mechanics and formatting. I’m not designing a complex beast capable to creating a wide variety of game types. Any attempt to abstract beyond my current project design, and make room for potential future projects I may want to reuse code for, always draws me away from making the actual game. So here I want to discuss what AG is designed to be and how the engine allows me to accomplish this specific goal.
As you could probably guess from my other posts, I am using SDL2 + GCC. I really like the SDL library and the c-programming language, plus it’s a combination I have a lot of experience with. There are a few variables which I need access to in the majority of my function calls. Typically, developers will design around one or two Singleton objects to house the majority of single-instance game information. This information includes things like the renderer and game window. Some of my global variables include:
- The number of sprites within my spritesheet
- The log file pointer, used to print any debug/error information to a local file
- A player input type definition
- A boolean indicating whether the game is running or should be shut down
- A SDL_Window pointer
- A SDL_Renderer pointer
- A screen surface which I use to generate a texture to be rendered
- An array of sprite surfaces drawn from the game’s spritesheet
AG is a small indie game made by one guy, and the design decisions reflect that fact. I use one single spritesheet for all game graphics. These sprites are present within memory throughout the entirety of gameplay. Although, if I every reach a point when this becomes unacceptable I can easily add one function which clears the current sprite array and populates it with the new spritesheet.
AG currently has three custom datatypes but I’m sure as features are added this number will gradually increase. The game is far from done, but the current design is pretty good at accomplishing its goal. The first datatype is a button input struct. AG uses the arrow keys and a/b keys (l-ctrl and l-alt) – keeping it simple. If I only cared about the player inputs I wouldn’t really need a datatype specifically for input, but instead all artificial intelligence is controlled via an input structure. This help to keep an organic experience for the player, as if he/she were playing against other players and not an all-knowing computer program.
The second datatype is a simple void callback function pointer. In AG, when a player attempts to walk into a grid point with a callback function attached to it a call is made to the function. All information which that function edits would need to be global – else I need to pass a void pointer to whatever information is passed and parse that pointer within the callback function – but currently a simple callback is all I need. The third datatype is a menu node. In AG, I wanted a simple and easy to modify menu system. So AG uses different menu node which house the four lines which I have available at the top of the screen to display information and dialogue. When the player isn’t within a menu node the game displays player information, inventory slots, and equipped items.
This way it is very simple to connect from node to node when traversing a menu tree and presenting the player with up to four different options to pick from. AG switches between handling menu actions and typical player actions. When working with menu options the player isn’t able to move or anything that would occur during normal gameplay. I hope to have quite a few items for the player to craft and discover but at any given time the player with be able to have a max of seven items with their inventory. This means that addition items will need to be stored within a chest or something similar.
From these images it is probably obvious that I’m a programmer posing as an artist and not the other way around. Although AG might not be appealing to a large audience I’m hoping to at lease finish this one, plus I like being able to think of an item and instantly add it to the game without describing the appearance to an artist.
Each game level within AG is made up of three 20 by 15 arrays. Two are foreground and background sprite indices. This way I can draw simple objects in the background and such like house entities in the foreground. The third array is an array of all the callback pointers for any entities present within the current level. The result is something like this ->
Which, honestly, is a bit ridiculous. Ideally, I would like to have a map/level editor which allows me to create and edit levels which are them stored within a database for when the game needs the information. I’m still considering what could be the simplest solution to representing level information. I need to really iron this out conceptually because AG will likely have many different levels. One appealing solution would be to create a map editor using Pygame which uploads the level information into a Sqlite database which I would read from when the game loads a new level. This is nice because it also allows for players to play with the level editor if they want to. The only problem is that I’m taking a relatively simple problem and answering with a relatively complicated solution, which I’m not a big fan of at this point.
Hopefully this gives you some idea of my current project. If you have any feedback feel free to comment or send me an email at “firstname.lastname@example.org”. My next post will likely address my map generation and storage problem. Till then, take care! :D