
Hexpenditure
Hexpenditure is a casual strategy game inspired by Civilization, Anno and Islanders. On a hex grid, extract resources, produce some more, and SELL SELL SELL to maximise your profits and survive as long as you can!
This was a individual student project about developing a game from concepting all the way to release. I worked on every aspect of the project, from planning to concepting, technical implementation, documentation, QA and more. Over the course of the project I created several modular feature sets focused on flexibility and developer usability with the intention of possibly expanding on the game in the future, being able to use these feature sets to easily create new content.
Solo
~14 Weeks
Casual Strategy
Unreal Engine 5
PC (itch.io)
University Project
Project Planning
To facilitate a smooth course of the project, I employed production and planning frameworks such as Scrum. I planned splrints and tasks using velocity, priorities, sprint goals and more, held retrospectives and generally remained agile to serve the ever changing needs of the project.
Design & Implementation
I was inspired by my enjoyment of the early game of strategy games such as Civilization and wanted to create that fully encapsulates that experience in an accessible form. I verified this design with a paper prototype before delving into implementation, where I developed several modular featuresets making use of Unreal Engine’s visual scripting.
Throughout the course of the project, I made sure to keep up design and production relevant documentation at all times, with a special focus on QA with things such as a Conditions of Satisfaction document, a bug reporting pipeline and regular build reviews.
Documentation & QA
Project Planning
At the beginning of the project, I created a project plan outlining the major phases, sprints and milestones until the project deadline. This outline helped me structure and prioritise my work, and was a constant asset in evaluating my progress. As the project went on, in oder to stay agile, I iterate on my project plan based on changed priorities, progress and other relevant factors.
The sprints, which were themselves linked to project phases, milestones and deliverables, were facilitated using a Scrum board in Trello. This board consisted of individual lists for the project backlog, planned tasks for the current sprint, in progress tasks, tasks to be reviewed and finished tasks. These lists were filled with cards representing the tasks, which themselves consisted of a user story, definitions of done, a priority, story points and sub tasks. When planning a sprint, I would use the previous sprint’s velocity based on the number of story points reached and the next sprint’s duration to calculate the number of available story points. I would then create a list of sprint goals based on the milestones and deadlines from the project plan, which formed the basis of which tasks would be added to the sprint. The highest priority tasks that were needed to achieve the goals were added to the sprint backlog until the sprint’s scope of story points was reached.
At the end of each sprint, I performed both a build review and sprint retrospective. During the sprint retrospective I would analyse the burndown chart of the previous sprint and calculate the available story points for the coming sprint in preparation for planning. I also reflected on the progress and process of the previous sprint. I noted the completion of the sprint goals and any leftover tasks and compiled a list of things that went well, things that didn’t go well and finally created a list of action points emerging from the retrospective. In retrospectives other than the first one I would also evaluate my progress on the action points from the previous retrospective, keeping the active if necessary. I also took this as an opportunity to add any tasks to the project backlog if my findings from the retrospective necessitated it.
Concepting
Early versions of the game’s concept initially resembled a mixture between the round structure and scope of Islanders and factory automation of Satisfactory. I was happy with the core structure, as the ideas of short bursts of casual strategic gameplay felt like a great fit for my personal cerative interests as well as the project’s scope, but after additional refernce research the concept moved more towards the core gamplay of games such as Civilization. In order to verify my ideas before commiting anything to code, I created a paper prototype which consisted of several permutations of different systems. This allowed me to investigate different aspects of the game individually, as well as different versions of several systems. As the style of the game lent itself to a paper prototype quite naturally, it was able to provide me with results that allowed me to confidently move into the next phase of the project.
Implementation
I created all of the game’s systems and features with the possibility of expanding on the game at a later point in mind. Therefore, I made sure to implement everything in ways that collected shared functionality in central points and ensured reusability and general modularity whenever possible. In the following section, I will highlight several examples from across the game’s featurescape.
The implementation of the data of the resources was done in several steps: firstly, I created an enumerator that would include every single resource from the game and would act as the reference point to a specific resource in any location in the game. This enum would then be used to access all other data related to this resource by acting as a reference to a specific row in a central data table created from a struct containing all the types of variables that would need to be saved for each resource.
All placeable buildings in my game inherited from a parent blueprint. This parent contained all variables as well as shared basic functions, such as building placement, interactions between resources and buildings, and more. This made the implementation of a new building easy and efficient, as all core functionality would already be set in place.
One of the examples I want to showcase is the implementation of building placement adjacency bonuses. Certain buildings provide gold as a bonus for each adjacent tile that fills a certain criteria. To facilitate this, I first created a map containing an enumerator of each adjacency bonus rule and a struct containing a “has rule?” boolean and an integer for the gold bonus. The struct of each entry of the adjacency bonus rules enum would be filled individually for each building, allowing me to easily determine their placement bonuses.
Whenever a building was being placed and was hovering over a valid free tile, the function seen below was called for each adjacent tile, which were accessed via an array located in the blueprint of each tile, which was filled with actor references to all adjacent tiles the moment the hex grid was spawned. In this function, every entry of the aforemention map within the bleprint of the building which is being placed is checked, and for each valid adjacency bonus, another function is called which calculates the gold bonus this rule creates. After all adjacency bonus rules have been checked, the total gold bonus of this tile is given as the function’s output variable.
This setup allowed me to easily create additional adjacency bonus rules, as I simply had to add an entry to the enumerator, then add an entry to adjacency bonus rules map in the parent building blueprint, and finally add a pin to sequence in the shown function that includes a function which calculates the adjacency bonus. In tandem with all of the other systems I had implemented, adding a new adjacency bonus rule took no longer than about 10-15 minutes.
One of the biggest UI challenges during this project was how I could give easy access to the information of the production chains of the various resources. After research into the nested tooltips of Crusader Kings 3, I settled on a design that would allow the player to manually create a tooltip showing the production chains that are related to the selected resource. The production chains that have the selected resource as their output are shown on the left, with the production chains that contain it as an input shown on the right. Clicking on one of the resources within these production chains in turn adjust the tooltip so that it shows the production chains of that resource.
To facilitate this, this tooltip is made of several nested widgets. Each of the resource button in the tooltip is a separate widget, which are part of widgets representing a singular production chain. These widgets are then placed in the correct spot of the final widget. This way I can efficiently split up data and functionality between several specialized widgets.
Whenever one of these production chain tooltips needs to be created, a function is called which fills the widget with the correct information and gives it the correct screen placement, including adjustments if the cursor is too close to the bottom or right edge of the screen. Here you can see part of this function, specifically the part that fills the right collumn of the tooltip with the correct content. For this, the row of the resource data table relating to the resource which is the basis of the tooltip is checked. Since the right collumn shows the production chains which use the specified resource as an input, both input resources of each production chain entry in the data table are checked. If the correct resource is found, a function in the tooltip widget creates a new production chain widget with the correct information and adds it to the right collumn of the tooltip.
Once one of the resources in the tooltip is clicked on, the focus of the tooltip changes to that resource. When this happens and the clicked on resource is not the same as the resource that the tooltip currently shows, the tooltip is removed and and a new widget is spawned. This in turn triggers the function mentioned above with the new resource as one of its input variables.
Testing & QA
On top of the scrum board, I also created a dedicated bug list on my Trello board. Bugs were represented in the form of Trello cards in the bug list which each included the following: bug name, epic label, priority, bug description, bug location, reproduction steps, expected result and actial result. This allowed me to easily investigatge the cause of the bug and ensure that it was properly fixed before removing it from the bug list.
I had several strategies to find and report bugs: apart from reporting a bug whenever I encountered it during development, I also made sure to actively look out for bugs during each sprints build review. Additionally, I attached a bug reporting form to the feedback form I sent out to playtesters, allowing me to catch several bugs I would have otherwise missed.
Another main part of my QA pipeline was the Conditions of Satisfaction document. In this excel sheet I broke down all planned features and functionality in order to gain an overview of the state of the current build and and the progress I am making towards the targeted polished result. I created a new copied tab for each build review and adjusted its content if changes to the project’s scope necessitated it, filling each entry with its current state of implementation, allowing me to not only create a detailed breakdown of the current build, but also compare the states of the different builds over time and gauge the speed at which I am making progress.