Friday, April 9, 2021

Getting started with HaxeFlixel in 2021

Warning: this is a fairly technical game developer-y post. If you came here for gay sex, I'm sorry.

For an upcoming project commission, I'm making a 2D game with crowd simulation and simple controls that works well on mobile browsers. (Reminder: for iOS, that means WebGL 1.0 and no WASM.) The engine should be able to render and simulate 200+ lightweight game objects -- frame-animated sprites with simple collision, no fancy physics or shaders.

Which game engine should I use to maximize ease of learning and compatibility, and manage hundreds of simple objects on-screen? Here was my thought process:

  • Unity WebGL: way too heavy and slow for mobile browsers, and maybe overkill for a no-physics 2D game anyway. (Although the Lil Nas X 3D twerking game runs surprisingly well on iOS's WebGL 1.0, I wonder how much they had to optimize?)
  • Unity Project Tiny: as far as I can tell, Project Tiny and its DOTS dependency is still in early development. The random caveats and various in-dev inconsistencies with regular Unity would also be frustrating. And as with many other Unity side projects, its long term future feels really hazy.
  • Construct: seems ok, and I think I could've gotten used to the visual block scripting, but overall the pricing and licensing feels weirdly restrictive. I have to pay to use more than 2 JS files? I have to pay to use more than 1 font, or make an animation more than 5 seconds long? These are some really bizarre artificial resource limits.
  • Phaser: seems popular enough with decent TypeScript support, but I want the option of building out to a native executable without a weird Electron wrapper or something. Their monetization model (free open source base but you pay for "premium plugins" and tools) is one of the more generous ways to go about this, I get it, but it still feels weird to me and reminds me of Construct.
  • Godot: I've wanted to try Godot for ages, but in the end I felt like I didn't have a good sense of what its HTML5 Web export could do + learning enough of the "Godot way" and GDScript would've taken a while. It's also in the middle of a big break between v3.0 and v4.0, and ideally I'd like to wait until like v4.2 to commit to learning it.
  • Heaps: promising and some people get great results with it, but maybe still too early in public lifecycle for a total newbie like me, with not enough samples / docs / robust official tutorials to learn from yet. If or when I do try out Heaps, I'll probably try using Deepnight's gameBase project template.

In the end, I chose to build this particular project with HaxeFlixel. This post details my early impressions, thoughts, confusion, advice, etc. with learning it.

Haxe has a very mature and stable multiplatform stack of libraries (OpenFL, Lime) with good support for HTML5 / WebGL as well as native executables, and the Flixel framework design has already been time-tested from its years as an AS3 Flash library with lots of documentation and samples. 

I also liked how Haxe has decent autocompletion support in VS Code, which reduces (but doesn't quite eliminate) all the documentation hunting. There's a decent debugger overlay with dev console too, for those who use those things.

This post is some info, advice, and useful links from my experience learning HaxeFlixel in 2021.

  • WEIGHT: if Unity and Unreal are big heavy fully featured game engines with tightly coupled game editor tools, then HaxeFlixel is a barebones "framework" game engine with very little default structure or required tools.
  • CURRENT DEV STATE: HaxeFlixel feels like it's currently in maintenance mode, having finished the bulk of its development in the mid 2010s. Most updates within the last year have been small bug fixes, and momentum for big future features has stalled. Mind you, this is still much better than a totally dead project, or a chaotic constantly-shifting live project.
  • WHERE TO GET HELP: Most Google searches will point you to the defunct Google Groups or the now dormant forums. For live help, your best chance is to ask in the Flixel channel on the Haxe discord.
  • HOW TO START: The official introductory tutorial is still mostly up-to-date in 2021, and will show you the typical code patterns and workflows to use. After you complete the tutorial, make sure you read through the Cheat Sheet which has dozens of short code snippets for common game features. Then as you come across more complicated problems, you'll want to browse the very helpful Demos, each with a link to its full source code on GitHub.
  • HAXE VS UNITY C#: Coming from Unity, Haxe syntax and HaxeFlixel's overall class architecture were fine. Instead of MonoBehaviour, most of your scripts inherit from FlxSprite (or FlxNestedSprite if you need to parent sprites to each other) instead. Coding-wise, I'd say my biggest pain point was...
  • VECTORS IN HAXEFLIXEL: HaxeFlixel encourages heavy use of chaining function calls and pooling variables, especially with vectors, which differs greatly from how Unity C# does it. HaxeFlixel stores vectors as FlxPoint reference types which must be manually get / put from a pool. So in Unity, I would lazily code something like var vector += new Vector2(1, 2) * 3; but in HaxeFlixel that looks more like var vector = FlxPoint.get().addPoint(FlxPoint.weak(1,2)).scale(3); which feels unnecessarily verbose to me. Also, most vector-related functions are actually on the FlxVector type that inherits from FlxPoint, so you constantly have to cast the base FlxSprite's class member FlxPoints into FlxVectors in order to do any vector math beyond arithmetic and scaling. 
  • BUILDING TO HTML5 / WEB: These days, this is HaxeFlixel's default build platform and it just works right out of the box. A basic Hello World build is ~4 mb uncompressed and ~1 mb compressed, with most of that space taken up by the 3.8mb .JS file.
    • Performance tests on iOS browsers have been great. I can easily throw ~200 sprites (that all share the same spritesheet) on the screen with basic overlap / collision tests at 720p resolution at a steady 30 FPS. My old iPhone 4 is running the crowd simulation (typical boid flocking thing with an underlying flow field) just fine.
    • I have a great push pipeline with itch.io -- I installed their command line tool Butler and setup the Butler auth, then I added a VS Code workflow task to easily push new HTML5 builds to itch.io. Here's what my /.vscode/tasks.json file looks like:
      {
          "version""2.0.0",
          "tasks": [
              {
                  "type""lime",
                  "command""test",
                  "group": {
                      "kind""build",
                      "isDefault"true
                  }
              },
              {
                  "label""itch butler push",
                  "type""shell",
                  "command""butler push export/html5/bin [ITCH-USERNAME]/[ITCH-PROJECT]:html5"
              }
          ]
      }
  • BUILDING TO WINDOWS FROM WINDOWS: Building out to Windows via C++ requires you to download and install C++ build tools included with Visual Studio Community (this is NOT the same thing as VS Code) and make sure you enable the checkbox for C++ support... Or if you don't want VS Community, then you can also download the Build Tools installer separately -- but make sure you don't uncheck any of the boxes because they're all necessary for the Haxe Windows build target; yes I know it's like 6 GB of nonsense but you need it all anyway, sorry.
* * *

Overall, my experience with HaxeFlixel has been fairly good so far. However, it has been designed for a fairly specific use case: tile-based pixel art platformers. The further you diverge from that original purpose, the less suitable HaxeFlixel will feel for your project.

Here are some use cases where the project would be doable but I would expect some friction / difficulty with HaxeFlixel:
  • physics simulation beyond simple platformer physics: there's a FlxNape integration of the Nape physics engine, and it seems like it has good support with examples... but the main Nape repo itself hasn't been updated at all for 5+ years, which makes me wonder whether it's compatible with the latest Haxe updates. I didn't try to find out.
  • lots of asset management: HaxeFlixel has a really basic asset management system where you load sprites, one by one, by file path. This simplicity might be appealing if you have less than a dozen sprite sheets to manage. But imagine a game with hundreds of different texture files, which all need to be packaged at different resolutions for different platforms! Tools like Unity and Unreal can package / resize / recompress your assets automatically when you build out. Maybe there's a way to hand-roll your equivalent in Haxe / OpenFL? I wouldn't know how that works though.
Here are some use cases where I probably wouldn't use HaxeFlixel:
  • bone-based 2D animation / complex sprite atlasing: there's support for the free Spine-like tool DragonBones and TexturePacker, but I don't know how mature or solid that integration or workflow is. And really, you'll want something like Godot or Unity that has a visual editor to help preview / debug how the animation and game will come together.
  • UI-heavy projects: same deal as bone-based animation, where in theory there's a decent flixel-ui library with robust demo code and XML-based layout files... but the workflow here is really unclear to me. Am I supposed to handcode the XML for all these menu screens? flixel-ui probably needs a visual UI designer tool, which will likely never happen. It's much easier to visually design these UIs in UE4, Unity, or Godot.