Week 10: Post-launch fixes, app promotion, and an unrelated pixel-art self-portrait!

A pixel-art self-portrait of Levi.
Some of my friends all challenged each other to make self-portraits, so here you go!


tl;dr: Fixed broken easy mode, made levels easier, tedious app promotion, and an unrelated pixel-art self-portrait!


What happened last week?

Fixed issues after launching Inner-Tube Climber

After the public launch of Inner-Tube Climber, I received lots of great feedback on all sorts of issues that still needed ironing out! I was not expecting to put so much more time into bug fixes this week! But I'm very glad so many people helped make the app better! And for the most part, these were all pretty important things to fix. This experience made me appreciate how useful it can be to plan time for multiple incrementally larger stages with a roll-out.

  • Most notably, I fixed easy-mode, which was completely broken in the initial launch. You couldn't finish the first level, and even if you could, the logic was also broken for unlocking the next level.
  • I also made some levels easier, especially some of the early levels.
  • I also fixed a crash that was happening only on iPads.
    • This one was particularly gnarly to debug.
    • It would only repro on iPads.
    • It would only repro when I wasn't exporting a debug version of my app (“Export with debug” was unchecked in Godot's settings).
      • Apparently related to a known Godot issue: https://github.com/godotengine/godot/issues/28922
    • XCode would show no useful information in the stack trace—just register addresses and assembly calls.
    • Fortunately, I found that I could use print statement debugging to, very slowly, isolate where the issue was happening.
    • The underlying source of the crash ended up being an attempt to reference the (non-static) AutoLoad singleton Global from a static function.
    • This code branch was being triggered only on iPads because I had encoded iPad model names incorrectly in an iOS model-name table I’d created.

App promotion!

...soooooooooooo tedious.

I did some research into how to promote an indie app or game. It sounds likeunless the game is big enoughan indie dev's main options are things like online forums, subreddits, Facebook groups, and Discord servers. And ads. So I signed up for a bunch of new accounts in various forums, familiarized myself with their communities and rules, and posted about my game in a bunch of places!

I kinda suspect that most of my work on this from last week was mostly just unnoticed noise and isn't really going to "pay off" for Inner-Tube Climber... but at the very least, I'm now more familiar with the process, and will know how to handle promotion better the next time!

Here’s a list of online forums I found to post about my game in:

Stats

In case anyone's interested, here are some stats from Inner-Tube Climber's first week:

  • YouTube trailer views: 2000
  • Number of downloads:
    • Android: 216
    • iOS: 55
  • Number of ratings:
    • Android: 2
    • iOS: 0
  • Number of levels finished: 73

A screenshot showing from my Play Store Console showing KPIs for Inner-Tube Climber.
Some Play Store KPIs.

Self-portrait

Some of my friends all challenged each other to make self-portraits, so I spent a tiny bit of time last week on pixel-art instead of app-promo!

I found it very awkward to draw myself, and it's definitely a little painful to share the result, but, oh well, here it is!

I included the picture at the top of this post.

An attempt to create a reusable scaffolding framework in Godot

tl;dr: I can make a basic decoupled framework project, but it will depend heavily on string indexing in dictionaries instead of type-safety, and it will be a little clunky to configure for the client.

My goal

I wanted to create a library that I could store as a separate Git repository that I could dump a lot of reusable app infrastructure and utility logic into. I wanted to be able to put this library into the `addons/` directory of whichever other game project I was using it from. I would then have to refactor some of my logic to support cleanly decoupling the infrastructure logic from the consumer game logic, but I figured that shouldn't be a problem...

The problems

But a couple aspects of Godot and GDScript make this difficult:

  • GDScript's inheritance system doesn't support overriding variables from a parent class.
    • This makes it hard to define constants that can be referenced from multiple files, since the consumer app will often need to define/override these constants.
  • Godot doesn't support static variables—only static functions.
    • This also reduces our options for configuring and overriding things.
  • I naturally need to use Godot's global singleton system, AutoLoads, to make configuration and utilities convenient to use from within the framework and from within the consumer app.
    • But I can't configure these AutoLoads from within the framework. The consumer app needs to do so, since it defines the overall project configuration.
    • The consumer app also needs to be able override the functionality of any framework AutoLoads, which can get a little messy and difficult to do with GDScript's limitations for variable overrides.

The solution

I'm going to create a separate framework project called Godot Scaffold.

  • The client will configure the framework using a large dictionary object.
  • The client is going to need configure AutoLoads, in a specific sequence, for the framework.
  • The client will need to also create and configure somewhat redundant AutoLoads in order to provide any custom extended utilities.
  • I will need to eliminate most constant variables and static functions, and replace them with dynamic alternatives, which can be dynamically configured.

What's next?

  • There is an online GDC (Game Developers Conference) event this week, and I'll be watching some of the sessions.
  • I'm going to revisit my old Surfacer codebase (procedural 2D platformer pathfinding), and incorporate some of my new logic from Inner-Tube Climber.
  • Then I'll make a select few important quality-of-life improvements to Surfacer that I've had on my backlog for a while now.
  • Then I'll get started using Surfacer to make my next game, whatever that will be!


🎉 Cheers!

This is a simple icon representing my sabbatical.

Comments