I like writing about bugs in Airships. I don't want to present myself as some infallible rock-star Indie developer, because I'm anything but. Airships is a game for builders and tinkerers, and I have seen again and again that you like reading about its creation, warts and all.
So today we delve into The Mystery of HMS Longcat.
If you've been following me for a long time, you know that before Airships, I was working on another project called Space Exploration: Serpens Sector. It was a space RPG that started out as a clone of the original Strange Adventures in Infinite Space, and ended up being something like Sunless Sea in space with less florid writing and a bigger focus on crew management.
After a series of bug fix releases for dev 8, I am now making headway on dev 9 and its menagerie of monsters. In a previous post, I showed you the tentacle movement I implemented for the game. Now I want to show you how these tentacles are actually used by the Sky Kraken.
With Airships dev 8 complete, it's time to start creating monsters.
Monsters and pirates is what dev 9 is going to be all about. What sets monsters apart from normal airships is that they can have abilities that are a little more out there, that would be hard to give to players for reasons of balance or user interface.
One of these things is tentacles. Giant aerial kraken will descend from the skies and begin snacking on your crew as you attempt to fend them off. Now, Airships' graphics may not be the fanciest, but they do pay attention to detail. A fixed tentacle graphic swinging by would be boring: how about properly animated ones? I wanted to try, at least.
#webdesign question: do you use ­?— David Stark (@zarkonnen_com) January 1, 2016
I did a Twitter poll the other day, and given the results, you might find the following post interesting.
In Zurich, there's a regular gamedev get-together called Gamespace usually hosted by my friend Dragica. And the most common format is a micro-game-jam, where we pick a theme in some fashion and then spend three hours alone or in small teams putting something together. Having so little time does wonders for focusing the mind.
With dev 7 and its revisions complete, I am now fully engaged in working on the next major version of Airships. This time, the big addition is going to be monsters, and to make that happen I'm doing a lot of cleaning-up and restructuring.
All units, including the upcoming monsters - dragons, fleshcrackers, suspendium bees - are handled in-game as "a kind of airship" or "a kind of crew member". Obviously, buildings are just airships without lift and propulsion, and landships ones with an alternative propulsion system. I can reuse the code for handling a lot of stuff - movement, collision, shooting, targeting - for creatures as well. A fleshcracker is just a funny-looking small landship, an aerial kraken is just an airship with no crew and a special tentacle attack.
So what distinguishes the two kinds of units?
In between major releases of Airships, I like to work on things that don't require deep changes to the game's code but make the whole experience better. For version 7.2, I want to make the combat feel more visceral, which of course mainly means one thing: better explosions.
I have an ambivalent relationship with Unity, the super-popular game development platform. In the local Zurich gamedev scene I'm pretty much "the guy that doesn't use Unity". Still, it's a good platform, and a rapidly improving one with good support and an active community, which means I will almost certainly use it to write my next major game after Airships.
Right now, though, I want to write about a worry I have about Unity: that it might be the cause of a "lost generation" of games that will be very hard to keep running on future platforms. In service of this claim I have an anecdote:
I previously wrote a post about a game jam format where you refine your game by re-making it repeatedly, halving the time allotted each time. People rightly pointed out that this would probably be horribly stressful. So here's an improved version, more of a prototyping technique than a jam format this time.
Modern graphics cards are complicated beasts. Treat them right and they're extremely powerful, but use them badly and you produce a lot of heat to no great effect. They like to do things in big batches: give them thousands of polygons in one go, and they're fast, but send them information piecemeal and they'll spend most of their time on overhead.
So why do computers that can run Skyrim on high settings struggle with big fights in Airships, a mere 2D game? The problem is that there's so many small things to draw: each module, each tile, each individually rotated limb of a crew member. Until recently, the game did this in an utterly inefficient way.
Developing Airships, I've been bumping up against an old problem a lot recently. There's a lot of looping over entities and sub-entities, and a lot of context that the entities need at each level, which makes for some truly unwieldy method signatures, such as this monstrosity:
public void draw(MyDraw d, double cropX, double cropY, double cropW, double cropH, Image light, float lightStrength, float ambient, Clr soilTint)
And every time I introduce some new value like the ambient light strength, I have to go all over the code, threading that value into each function call. So I was discussing this with David, who agreed that the fix was a context object passed down the invocation chain of entities and sub-entities.
I worried about context objects becoming an unholy mess of variables in various states, or having to instantiate a specific object for each invocation. But after a bit of thought, I realized that the type system could fix this:
I've been hard at work on Airships dev 6, and have now fixed upon a release date for it, and for Airships on Steam: February 25. So unless anything goes majorly wrong in the next two weeks, that's when you get the fancy new version of the game.
Speaking of fanciness, I did a short video of the new heraldry that's now in, with a whole bunch more layout and symbol options:
I got asked to list my pain points with it, so here we are. Note that I'm not exactly an expert: I've used it for two game jams. So it's possible that there's fixes, but note that experienced Unity developers may have simply got used to these problems.
Over the last weekend, I again got to participate in the Global Game Jam. It's a pretty big event here in Zurich, with about 80 participants each year, held in one big ex-factory hall.
Like last year, I worked together with Kaspar Manz, though Kristina Balanc, who did the art for Art Critic, couldn't make it. What made this year different was that we were joined by Jan Graber, a local journalist who wanted to experience the jam from the inside. He would both work on the game and report on it, and if you read German, I recommend his rather more expert coverage. This post, as a postmortem, is going to focus on the good old "what went right, what went wrong" side of things.
Today brings both the release of Airships 5.3 and the start of the Steam closed beta for the game.
When programming game AI, a common pattern is to look at each possible action and assign them a numerical score to figure out which to take. This may be done explicitly, with each possible action actually considered, or implicitly. A lot of thought may go into calculating the best action scores, taking all available information into account and also projecting play forwards in time. Or it may be as simple as "there's an enemy in front of you, shooting it would be a great idea".
A problem can arise when the AI always picks the action with the best score. This sounds odd - after all, the best-scoring action is the best action, right? But unless you did a very good job at calculating scores, a particular type of action can end up constantly scoring best. The AI gets locked into repetitive actions that become easy to predict and outmanoeuvre, and may fail to take care of secondary or long-term goals.
(This post is partly inspired by Vi Hart and Nicky Case's Parable of the Polygons in that it has a bunch of interactive toys to hopefully illustrate its points. It's not nearly as pretty as the polygons stuff, mind you.)
The next major version of Airships, EA6, will have support for multiple languages. Right now, English and German are supported, and I hope to also include French and Spanish. I have fairly limited resources, so I may not be able to afford professional translation to many languages. So if you want, you can help out by providing or verifying translations through this spreadsheet.
One of the nifty features of Airships is that you can create your own coat of arms. You can do this for your single-player empires, selecting a symbol (a charge) to give you a particular bonus. And you can design and register a coat of arms for your unique use in multiplayer. The system hasn't really changed since the initial release with the exception of a few added charges, but with dev 6 - the update of prettiness - I want to improve on what's there.
I recently received some queries about my OCR project, Longan, so I thought I'd write up the current state of it. I tried doing this before, and it quickly mutated into a book-length project, so I'll try to keep this one brief.
I started writing Longan because I needed a good OCR engine for another (now defunct) project I was working on. The only freely available OCR system that anything near worked was Tesseract / Ocropus. My experiences with Ocropus were pretty dire: it was hard to set up, hard to use, and very brittle in its output quality. So I decided I could totally write my own, better OCR system. Because of hubris.
At the start of 2014, I'd been working on Airships for a few months, and the major components were beginning to take shape: ship design, combat, heraldry, even a simple strategic map and multiplayer. I'd been blogging about the game on my site and IndieDB right from the start, and the very positive response was a major source of motivation. Still, the game lacked much of a user interface, and the computer's ships just hung in the sky and fired, with no tactical AI to drive them.
When you start upgrading the visuals of your game, some parts start sticking out like a sore thumb. In this case, I'm really unhappy with the way damaged armour looks, so I'm going to outline a way to make it look better. This is a bit involved, but there is a really cool picture at the end...
In the first post on lighting, I got as far as adding unidirectional light sources to the game. The next step was to make the light directional, so things facing a light source would be lit up more strongly. To do this, the game needed to keep track of the direction of light, and not just its intensity.
Over the past few days, I've spent a lot of time going over Airships and improving it in terms of AI, speed, and bugs. The major highlight is that the strategic game should be more balanced now: AI empires make much better decisions in terms of what to build and who to invade. Also, I've eliminated inefficient code for crew shouts and firing angle calculations that were taking up a solid two thirds of CPU time - remember to profile, kids!
On top of that, there's lots of other improvements:
This week, I started working on dynamic lighting, which is one of the major planned features in the next release. The idea is that explosions, fires, etc. light up their surroundings. I also want to take into account light direction, so surfaces that are angled towards the light source are lit up more strongly. Like in real life!