log #9: Assets and Many Improvements
Time interval: 2023-09-28/2024-02-11
A long time has passed from the day I published the last post here. In this time I managed to fix many bugs, add many improvements and most importantly, finally add proper assets to the game. But we will get to the assets later in this post. First I will quickly run through some notable changes.
Removed Telegraphing
As mentioned in the last post, I removed the telegraphing feature. I decided it’s not actually needed to play the game and that it’s just there to annoy the player with bureaucracy. However now the game is a bit harder, because you need to manualy keep track of incoming trains. However in reality, this isn’t that much of an issue.
Pocket Watch Rework
The pocket watch is the oldest item in the game. It’s used by the player to keep track of time, however it also has a hidden ability - fast forward time. This is crucial to the gameplay of the game. You don’t want to wait hours for the trains to arrive. In the past, to fast forward time, you just held down the spacebar. This worked, but it had some problems:
- the need to simulate the world at faster speeds
- it was very simple to overshoot (even with some extra features that stopped the clock at the right time)
- the game shifted to mouse oriented controls
For these reasons I decided to rewrite the watch from scratch. It now comes with two buttons. One forwards the time by a minute and the other one skips the time until a train arrives.
Command Shell
One day while debugging, I thought is would be nice to have the ability to just give myself the log book in the middle of the day, instead of waiting for the day to end. In the past I might have done this by adding a special key handler just for this testing, but I decided I should invest some time into my debug tooling. And that was the birth of my debug shell.
It’s a game window, which allows the user to run commands and see their output, just like a terminal emulator on your PC. Game modules can easily add their own commands to the shell like this:
cmdwin.addCommand("spawn", |this| {
if len(args) != 1 {
cmdwin.setStatus("usage: spawn <entity>")
return
}
this.w.spawn(worldload.ents[args[0]], this.w.player.e.pos.add({ 10, 10 }))
cmdwin.setStatus("OK")
})
I’m adding commands as I need them. At this time the shell is already quite
capable, especially with my favorite command var
, which allows you to control
various game variables.
Command Line Interface
When debugging something in the game, I realised I had to do a lot of manual. Edit the code, launch the game, select a save, run all the shell commands I needed for testing and then I could see if my fix did something. To simplify my life a bit, I added these command line flags:
-save
- specify a save name to load after the game starts-script
- specify path to a script file, which will be launched after a save is loaded
The implementation of the script flag is a case for why I like using signals so much:
f := std.fopen(script, "r")
if f == null {
logs.err(TAG, "Script not found\n")
window.quit()
}
dat := str([]char(io.mkFile(f).read()))
std.fclose(f)
gmgr.smgr.loadWorld.register(|dat| {
lines := strings.split(dat, "\n")
for i,cmd in lines {
logs.dbg(TAG, "+ {}", cmd)
cmdwin.runCommand(cmd)
}
})
New Assets
And now we finally get to the most exciting part. The new assets. This whole operation of changing all the assets started somewhat randomly. I was browsing the internet and stumbled upon Kenny’s Asset Forge. I thought that this program would be great for someone like me, who isn’t well versed in digital art of any kind. I bought a copy and made a simple locomotive.
Then became the issue of how to put it into the game. Now I don’t just have a
single image to draw, I have to choose an image based on the angle of the
entity. I solved this by adding an abstraction over tophat images called
textures. Textures are automatically loaded by my res.um
module. If the
image has a JSON file associated with it, it is loaded and used to provide
extra info during the texture creation.
Then there was the issue of exporting the model from Asset Forge. The program has the ability to automatically render the image at various angles. Sadly, it outputs multiple images instead of a single atlas. Additionaly, the model has a quite large amount of empty space around this. I fixed this by hacking together a simple (but very slow) python script. This was enough to allow me to rotate my images in game.
After that, I made textures for a few more entities, but then I got to signals. The might seem simple at first, but they require one crucial feature: animations.
Animations
This is where Asset Forge failed me. Theoretically I could implement animations using Lua scripting, but there isn’t a way to automatically run Lua scripts from the command line anyways, so it would all require too much manual work. I turned to Blender for help. Blender has two main advantages: it has out of the box support for animations and it can be very well automated using python scripts. So I imported my Asset Forge models into Blender and made another python script.
Then I edited my first script to support not only rotation, but also animations. The resulting files are now 2 dimensional atlases. The rotations are on the X axis and animation frames on the Y axis. Maybe I will need to implement a 3D bitmap format in the future :).
What’s more, Blender can be launched in headles mode, preloaded with a python script. This allowed me to write a Makefile, which builds all my assets when needed.
Switches
The switches are currently created using a bezier curve in Blender. They don’t look that bad in the game, but I’m unhappy with multiple things.
- no animations, the switches don’t make sense
- trains going over the switches are rotated linearly, not according to the curve
- I can only have one switch variant
- the whole switch implementation is not very nice
Switches are one of the bigger features I will focus more in the future.
Asset Browser
I implemented a simple asset browser, which helps me preview the assets at
different orientations and play their animations. It is available by running
asset_browser
from the debug shell.
If you are interesting in finding out more about the development of my game, or want to try playing a demo, you can visit our discord server.