I'm slowing getting to the core game mechanics of The Alchemist, but there are still many things I need to implement in the KorGE game engine. In the game, the player must collect and process various raw ingredients, transforming them into either an intermediate ingredient, or a final product such as a potion. Most of this processing will take place in a Machine
- which could be a simple mortar-and-pestle, but it could be a centrifuge or a furnace or who knows what else.
I'm at the stage where I need to present a basic interface for a Machine
, and display a sprite of it on the tiled map. I haven't finalised all the details, but when opening a machine the player need to select a recipe such as Minor Healing Potion, which may need two ingredients - maybe crushed dandelion seed and eye of newt. The player would then drag the ingredients into the slots presented on the machine, and click an appropriate button.
Different recipes and different machines may require a different number of input slots, and some recipes may have multiple outputs. I'm defining the recipes in a JSON file, so my game needs to be able to dynamically build the UI for a machine based on the machine type and the selected recipe. For this, I've been working on a custom KorGE component which can display a neatly-aligned group of item slots. I've called it a FlowContainer
and in use it would work a little like this:
fixedSizeContainer(width = 120.0, height = 160.0) {
flowContainer(maxWidth = 100.0, maxHeight = 100.0,
layout = FLowContainer.Layout.Horizontal,
alignment = FlowContainer.Alignment.Center)
{
recipe.inputs.forEach { ingredient ->
slotItem(ingredient) {
//...
}
}
}
}
This approach leverages the DSL-based scene layout functions within KorGE (and is common in Kotlin code).
flowContainer
is a function which creates a FlowContainer
object and adds it to the parent KorGE container (the fixedSizeContainer
in the sample above). The function then automatically calls the layout()
function, which calculates the x and y coordinates for each of the children in the container - in this case, for each of the slotItem
objects defined in the given recipe
. It's also possible to call the layout()
function to change the layout, for instance after adding new child views, or switching to a different alignment.
In building this I started with a test project - which is available on github - and slowly build out the functionality. I'm not very good at maths or abstract thinking, so it took me over a week to finally get it working. Though in fairness, I can only grab an hour or two in an evening to work on The Alchemist, and not always even that.
The FlowContainer can have a Vertical or Horizontal layout (horizontal was easiest). Then the elements can be aligned to the Left, Center or the Right (Center was harder, and Vertical Center was the hardest of all). There is also an optional crop
parameter - which cuts off and hides any child elements which don't fit in the container. I'm not sure how useful that is, and I might just drop that feature.
Once I had it working, I transferred the code into The Alchemist, where I quickly found that the code needed some refinement in a "real world" game. Still, it's been a useful learning experience. I shared a demo of it with the KorGE discord, and it has been suggested that I merge it into KorGE's existing UI framework. FlowContainer
is not ready for that, but it was a bit of a psychological boost to get from the lead KorGE developer.