With the newest version of macOS, Apple has made mandatory some requirements for applications that were previously recommended: 64-bit executables, signing, and notarization. Applications that don't satisfy these requirements will no longer run.
This is intended to make the experience safer for end-users and prevent the spread of malicious programs, but it does also make things more complicated, especially for people who aren't primarily Mac developers but would like to support or keep supporting Macs.
It's also especially relevant for game developers deploying Mac games on Steam. Until now, games launched from Steam didn't have to be signed or notarized, but now, they have to obey the same rules as everything else.
I just went through figuring out how to comply with this for my game, Airships: Conquer the Skies. Airships runs in Java and hence also has to bundle a JVM, but the rest of what I learned should be applicable in general.
So here's what I learned about signing and notarization a Mac app that wasn't directly compiled by Xcode. Please note that this is cobbled-together research to make things work for me and may not be 100% accurate. Questions and corrections are very welcome.
I'm embarking on an attempt to make multiplayer strategic conquest work in Airships.
First off, to be clear, this may well not work. I wrote the strategic conquest code without thought to making it multiplayer, which means I now need to try and refit it for this purpose. It's entirely possible that I can't get it to work consistently, or that performance or UX problems make the experience a terrible one.
Still, lots and lots of people insisted they really wanted this feature, especially cooperative strategic multiplayer, so I'm giving it a try. If, after a few weeks of work, things are still a complete mess, I will shelve the attempt.
I started working on this about three days ago, having formulated an approximate plan:
At around 1 AM, with a solid two hours to go before the jam deadline, I uploaded and published Dryad, my 3rd Ludum Dare entry.
It's a platformer about a forest creature wishing to become human, and, uh, killing a whole bunch of humans in the process. As you become more human, your magical powers wane, and you become slower, weaker, less perceptive, making each successive level harder. You can choose the order in which you lose your powers, and some orders are easier than others.
In Annulus, you guide a stone-age tribe living on a ring-shaped space station. Apart from hunting and gathering, there are strange technological artefacts to study, and on occasion, there's an opportunity to shape the culture of your tribe.
The next version of Airships will focus on improvements to troops. In this post, I'm going to write about the performance and pathfinding problems that large numbers of boarding troops face, and how they have been resolved for the next version.
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.