A few weeks ago, I posted an introduction to the Tiny game engine, which you can read at the link below:
Since then, I’ve been sporadically working on a little game called Tiny Gardening, which is intended to be something of a re-vamp of one of my first coding projects:
When I was first learning how to code (many years ago) one of the very first programs I wrote was a text-based simulation of an orange tree, where you had to water the tree and collect the oranges regularly. I don’t know why, but there’s something about simulating plants which keeps coming back to me, so why not continue the theme with Tiny?
Though Tiny Gardening is by no means complete - or even ‘a game’ - at this point, I’ve made enough progress to warrant a quick update, so without further ado, allow me the pleasure of taking you on a tour of my digital allotment!
Where We’re At
Currently, the game has a handful of basic features which need further fleshing out:
Players can plant seeds
Players can water their plants
Plants grow as their ‘water level’ increases
Plants lose water over time - currently shrinking back down to their ‘seed’ sprites, but in the long run, they should have some kind of ‘death’ sprite.
When all your plants are dead, it’s game over.
The current season is represented by the bar along the top, with a yellow circle (actually a photorealistic representation of our glorious sun!) moving along it to represent the passage of time.
Right now, time moves very quickly. Seasons pass in the blink of an eye, and your plants will ‘die’ if left un-watered for longer than about 10 seconds - so good luck trying to manage more than a few plants for any length of time!
To get some idea of how things currently work, see the video below:
It’s a bit of a free-for-all with the placement of the plants - which I’m not too keen on. I may play around with some kind of grid-based layout, which will also help provide a nice system for more interesting rules and challenges later on.
Seasons will ultimately cause different effects, though right now they do nothing but change the colour of the ground. In summer, for example, it might be fun for plants to lose water more rapidly, or for certain types to grow more quickly. Autumn may have an increased likelihood of rainfall, but ‘summer plants’ may not grow so easily. I’d also like to introduce some pests and pollinating insects later on, but we’re a little way away from that kind of thing right now!
In the medium term, I need some kind of win condition for the player. Right now it’s just a case of surviving for as long as you can, but that’s not particularly interesting. I’d like to introduce some kind of farming-like mechanic: some plants could be vegetables you have to harvest and sell, and perhaps you need to meet a certain quota for some particular type of vegetable within the year. I’m not too hung up on that for now - there are plenty of things I want to implement just to explore what Tiny can do - so I’m holding off bothering too much with it for the time being.
Challenges
Tiny is a brand-new game engine, currently gearing up for its v1.0.0 release, so bugs and shortcomings are to be expected.
Generally speaking, the engine doesn’t offer all that much aside from the absolute basics: it’s up to you to build each system your game might require. There is no concept of 2D physics for collisions, no UI system, no entity-component system and very limited support for input and audio. In many ways, this makes it a brilliant engine for the programmer who has some idea of how to implement those kinds of things - but absolute beginners may struggle. I would say Tiny suits those who have some familiarity with other game engines, but who enjoy a challenge. Doing anything beyond the most basic of games will require some understanding of non-trivial concepts and systems, and you’ll need to work out collisions and any other physics for yourself. Thankfully, the maths involved is generally relatively simple and can be worked out in your head (or, more likely, looked up online!).
There are also bugs in the engine which require some attention. One I discovered very early on was in the engine’s implementation of math.clamp, which, for the uninitiated, is a function you can call which restricts a number so that it always resides between two other values:
This is a standard function available in virtually all math libraries - and a particularly useful function in game development. The bug, in this case, meant that values would only actually be clamped if they were greater than the upper bound:
This kind of thing can be a painful bug to come across - the nature of it means you end up with unclamped values causing things to spin out of control - and since Tiny doesn’t offer any kind of debugger, the cause of the problem can be difficult to spot - particularly if you’re controlling and constraining values in multiple different ways.
Thankfully, in this instance, I was able to spot the problem easily since its impact was obvious: I’m not sure what happens in the real world when plants have ‘negative water’, but in Tiny Gardening, they become very dead very quickly. I fixed the issue in the engine’s source code and submitted a Pull Request on GitHub - which was promptly accepted and merged into the engine’s codebase.
I’m sure I’ll find more issues as I continue - I have a sneaking suspicion there’s an issue with audio not looping correctly in builds which are exported for the web, but I need to test further to confirm.
Bootstrapping
Since Tiny is such a bare-bones game engine, it’s up to the programmer to implement systems and utilities to make the game development process more straightforward. Below, I’ll cover some of the things I’ve implemented to make further development more flexible and less time-consuming. Wherever I include a code snippet, keep in mind that I’ve probably omitted some parts of the code which aren’t strictly relevant. You can always take a look at the full source code over on GitHub if you want to see all of the nuts and bolts!
State Machinery
At the highest level, the game is broken up into three distinct states, which allows me to encapsulate the core loop and easily add or remove extra screens or switch out different implementations without too much fuss.
For those unfamiliar with the terminology, or state machines in general - for now, you can imagine that a ‘state’ corresponds to a ‘screen’ in the game.
The basic states I’m working with right now are:
Main Menu
This state represents the first screen players will see and does nothing but provide a big button to press to start the game.
Game
This is where players spend most of their time - all of the actual gameplay occurs when the program is in this state
Game Over
This is where players end up when they’ve won or lost the game. It will provide some kind of summary of how the player did and also provides a way to return to the main menu so players can start again.
Below you can see the skeleton of a State:
The State:new() function acts as a Constructor. Lua - the language Tiny games are written in - does not provide objects in quite the same way that other Object-Oriented languages do, and so some basic boilerplate code is required to give ourselves something akin to the objects and classes you may be familiar with. If you’re interested in learning more, you can read the lua documentation on the subject - but to summarise: every time I want a new State object, I can just use:
myNewState = State:new({})
From there, I can call functions on my new object instance as follows:
myNewState:update()
myNewState:draw()
Those who recall Tinkering With Tiny will remember that the engine calls an _update() and a _draw() function on every frame, so, in keeping with this pattern, there’s a corresponding update() and draw() function on virtually every custom object throughout the Tiny Gardening code.
Entities
There are some basic features which are common to pretty much everything on-screen in Tiny Gardening:
They all have a size and position
I need to know if they’ve been clicked
I need to check if they overlap with some other entity
I want some basic debugging functionality that I can easily turn on and off as I see fit.
For these reasons (and more!), it makes sense to build some kind of entity system which allows me to share these features across different kinds of objects. In Tiny Gardening, you can click on buttons and you can click on plants. What happens when you click on either is radically different, but they are both ‘clickable things’, and like any good programmer, I am incredibly lazy, so I don’t want to write ‘click detection’ code more than once if I can avoid it!
Using what passes for inheritance in lua, I can implement new object types which are based on this Entity object, meaning that every object created in this way can detect clicks.
User Interface
Tiny offers absolutely nothing in the way of a UI system. There are no buttons, sliders, text fields, or anything else that other game engines might offer. This is a little frustrating since user-interface code can be a pain even when the engine does provide something for you to use - but I’m not one to complain, so one of the first things I did was implement a Button, which features something akin to ‘click events’:
Here, the Button object is instantiated by a call to Entity:new(), which means that every Button object I create automatically benefits from click detection. The onClick property is itself a table, which can be thought of as an array, meaning I can attach multiple handlers to a single button, which are triggered whenever a click is detected. The Button:fireClickEvent function loops over those handlers and calls them one by one.
As an example of how the Button object is used in Tiny Gardening, here’s my generic ‘debug button’ which always lives at the top of the screen:
Here, you can see that the onClick handler is itself an anonymous function - meaning it has no name and can’t be called except by accessing the value of onClick. This is a nice way of handling simple functionality which should occur when a button is clicked - but is not particularly well suited to more complex behaviour. For my purposes, this system works well and means I have a nice, easy-to-use, basic button.
Of course, you rarely need just one button, so I also implemented a ButtonBar, which allows me to lay out a series of buttons either vertically or horizontally:
Tiny Gardening also utilises a variant of the base Button called ToggleButton, which allows me to implement such thrilling and revolutionary concepts as a selected toolbar:
Wrapping Up
In this post, we’ve covered some of the basic components of Tiny Gardening. Admittedly, most of what I’ve mentioned here is a far cry from ‘game stuff’ or even touches on the main theme of the game, but in an engine like Tiny, it can pay dividends to build yourself a little toolkit of reusable components and functions which form the backbone of the rest of your game. Things like buttons and entities might seem trivial at first glance, but their absence can be felt keenly when you’re trying to build anything that requires shared functionality and predictable behaviour!
In the next progress update, I’ll dive into the core mechanics of the game so far - how I track plant growth and animate the sprites, the particle system for water and seeds, and how I’m implementing seasonal effects. I’ll also talk more about the pros and cons I’ve discovered about the Tiny game engine. In the meantime, you can explore the code as-is on GitHub, and try Tiny Gardening out for yourself here!