Jamming with OpenFL

Posted by (twitter: @wilbefast)
September 8th, 2013 12:06 pm

Time for our post-mortem :)

I won’t re-introduce the team, you can go to our “we’re in” post for that. Basically there were 3 of us and we’re pretty awesome!

So what happened?

Well, we made a time-bending tower-defence game called “10 Second Onslaught”. It’s about an onslaught you see, and the onslaught in question lasts 10 seconds:

10 second onslaught awesome

The game wasn’t really “finished” after 72 hours even though it’s completely playable. I’m actually glad we were over-ambitious though: it’s a good beginning and something I’m still working on (in a separate branch of course 😉 )

What went well?

The art pipline was probably the one thing that went particularly well. Thomas is really a 3D artist, so soon reverted back from pixel art to making models and rendering them to bitmaps. To speed things up I wrote a couple of little ImageMagick scripts to mirror and then stick these images together into sheets. Then it was just a matter of using the haxelib spritesheet to have animated characters in the game :)

What went badly?

For various reasons, mostly the technology (OpenFL) being something only I had ever used before, I ended up writing a majority of the code, which is just stupid. Next time we’re going to have to organise ourselves better.

Read on for a rather long discussion of OpenFL, including comparisons to Unity 3D and Löve 2D…


Our company NaturalPad uses Unity for most of our game projects – here we wanted to try something a bit different: “OpenFL”. There’s some degree of patriotism involved as Haxe and Motion Twin are both French. I’m not actually French myself, but that doesn’t stop me from being patriotic about croissants and stuff. Anyway you might remember OpenFL (called “NME” until very recently) from such games as Papers Please and Rymdkapsel.

I’m told OpenFL resembles Flash, but I’ve never used Flash so I wouldn’t know. Unfortunately developers seem to assume that anyone using OpenFL is already familiar with Flash, so their documentation isn’t as complete as it really should be. To be fair Joshua Granick is always on hand to reply to questions if you ask and, all told, this is my only real qualm with the framework so far. Well, that and the fact that installing it on a non-Ubuntu Linux is a serious pain…
We started off using Doom-guy and Zergling sprites

We started off using Doom-guy and Zergling sprites as place-holders.

OpenFL vs. Unity 3D

OpenFL resembles Unity 3D in some senses: its tree-like draw-list structure for instance very much resembles Unity’s transforms. As a result scenes are constructed in the same sort of way, by linking up nodes to parents to form a hierarchy. That being said Unity is a game engine while OpenFL is just a framework for cross-platform multimedia applications. There are some OpenFL-based game engines out there, HaxeFlixel for example.

While I was happy to be using something lighter and less proprietary there were certain things I missed. Notably:

These two combined in C# make it absurdly each to find scripts and objects on the fly, something that is often central to game logic. After all, I will often want to find:

  • “all the trees within 500 pixels of the player character.”
  • “the number of enemies with full health.”
  • “the ally with a bazooka with the most ammunition.”

These queries, in Unity C#, would look something like this:

root.gameObject.GetComponentsInChildren<Tree>().Where(t => Vector3.distance(t.transform.position, transform.position) < 500);
root.gameObject.GetComponentsInChildren<Enemy>().Where(e => e.health == 100);
root.gameObject.GetComponentsInChildren<Ally>().Where(a => a.gunType == GunType.Bazooka).MaxBy(a => a.ammunition);
You’ll note that I use root objects as folders and nearly always have a root object called “Root” from which all objects inherit.

In Haxe functions are first-class citizens and so can be passed to queries unlike, say, in Java. However I just couldn’t manage to get Haxe’s templates working. Thankfully I’m wise enough now to know when something isn’t working and to move on to other things, especially during a jam. Even a good few hours were wasted trying to build a nice API for game object queries.

Next up: starcraft Command Center and dancing banana sprites

At 3:00am it seemed logical to replace the Zerglings with dancing bananas. I also added some cool music for the rest of the team to wake up to.

OpenFL vs. Löve 2D

I was able to teach my team to use “Löve 2D” only a few weeks after starting to use it, and Lua, myself. That said Löve 2D is famous for being absurdly simple to use. Want to draw something for example?

love.graphics.draw(thing, 0, 0);

Even though I’d already finished one simple game using OpenFL (or rather NME) I think the framework is just a lot more complicated than Löve. You’re not telling the machine when and where to draw, rather you’re build and maintaining the elaborate draw-list tree structure. I also had a real person teaching me Löve rather than figuring it out myself, and Löve has far better documentation.

All this combined to make it very difficult for me to delegate tasks to the novice programmer on our team. I didn’t really know what I was doing myself! As a result he wasn’t able to make a particularly meaningful contribution to the project, which I’m not terribly happy about.

Most of the sprites in the game, though the colony sprite is still missing

We didn’t want to go with generic insectoid aliens for the monsters, so instead they were based on Wig-wigs… with huge eyebrows. Apparently the eyebrows were based on mine. Not sure how I feel about that.


OpenFL vs. user interfaces

Speaking of not knowing what you’re doing: it was brought home to me with this project that I haven’t done enough interface-heavy game to know how to properly structure interface code. Generally-speaking my games have been sprite-heavy with plenty of AI and collision code, but the controls have tended to be direct mappings from a keyboard or gamepad to an action in the game.

Here we wanted a game that could be ported to mobile devices, so it needed to work with an extreme economy of input:

  • touch
  • drag
  • release
Here's what the game looks like now!

Here’s what the game looks like now!

That said the player needs to be able to do a lot of things:

  • buy and place units
    • choose unit type
    • choose positions in space
    • choose position in time
  • modify previous unit placement
    • move through space
    • move through time
    • “sell” unit
  • start the onslaught
  • stop the onslaught

One of the advantages of OpenFL is that it is extremely good for exactly this kind of user interface. As mentioned before however, I wasn’t necessarily experienced enough with it to make the most of it.

Some of these interactions ended up being coded using static buttons but a lot of it was contextual menus. Because I’m not very experienced doing this kind of code the result was a bunch of tangled events and callbacks roped randomly through the code-base.

I’m not altogether sure how one “should” structure interface code for it to be “clean”, but it’s certainly not the way we structured ours!

Tags: , , , , , , , , , , , , , , , , , , , ,

One Response to “Jamming with OpenFL”

  1. ratking says:

    Thanks for the insights. I’m still thinking about using Haxe/OpenFL for a smaller project, so this was useful.

Leave a Reply

You must be logged in to post a comment.

[cache: storing page]