What Went Right
1. Haxe/NME with HaxePunk
I really enjoyed Haxe as a programming language. It’s got some gotchas (like iterators are automatically created variables that only exist in loop scope and loop ranges are exclusive not inclusive) but overall it was a charm to work with. I’m also glad I got to use NME. This meant I could target mac, pc, mobile devices, and swf all from the same source. There were a few cross-platform few issues, but not as many as I expected.
HaxePunk is a game library built on top of Haxe/NME (based on FlashPunk) and that worked out pretty well. I bumped heads with the API a few times, but ultimately it was a time saver. Without it, I would have spent too much time working on my own game tools instead of working on my game.
2. Using Texture Packer and Tiled Map Editor
Texture Packer (TP) is a great tool for assembling all your graphics in one place. Tiled Map Editor (TME) is a decent (and free) tool for drawing level maps. TME needs a “packed” image to work properly. That’s the image below on the left. Although TME needs packed images, it doesn’t read the associated XML files that TP produces. So when you add new images to the folder TP is monitoring, TP annoyingly moves images around to make room. So the images get shuffled around and then TME’s map gets all messed up, carpet showing where grass should be, walls turning into desks, etc. The solution I used was to number my images (04_carpet.png) and tell TP to sort by name and use a short fixed output width. It was still a pain to remove images using this process, so I just didn’t. Bear witness to the first two tiles in the first image below, which were placeholder graphics.
I also separated sprites going straight into the game without TME. To better work with HaxePunk spritemaps, I make several spritesheets based on the image size. Mostly I worked with 64 x 64. But I also found it easier to deal with larger sprites as whole images, rather than breaking them down into 64 pixel tiles. This isn’t optimal, but it worked. Hopefully by time for my next game Spritemap will be updated to work with texture packer images rather than fixed tile grids. If it isn’t, I’ll make my own class. Below from left to right are the TME map tiles, 64×64 sprites, and 256×256 sprites.
3. Dynamic object creation
This worked out really well. I used Matt Tuttle’s Tiled Map Editor code (not currently part of HaxePunk) to read the TME file and create a scrollable map. This code and TME both also support the ability to add generic “objects” to the map. Generic objects can be given a name, type, and (most awesomely) properties. Here I’ve got a worker, an effect, and a zone. The zone is used to detect when you’re close enough to interact with the worker (and therefore the spacebar is active). The quest effect (smoke) is searched for when you complete the quest. The worker uses facing to determine which direction to face, has all of his speaking lines in one place, including the line he uses when you complete the quest. Color is an old prototype property I never bothered removing.
In my main game world, after loading the TMX map (that’s the extension for a TME file), I process all the objects I can find on the “items” layer.
var group = map.map.objectGroups.get("items");
for(i in group.objects)
var clazzName = ENTITY_PREFIX + i.type;
var clazz = Type.resolveClass(clazzName);
if(clazz != null)
var obj = Type.createInstance(clazz, [i, i.custom]);
var zone:Zone = cast(obj, Zone);
else trace("Unknown object class found: " + i.type + " with name:" + i.name);
So when it finds “Worker” in the Type field, it creates a Worker game entity dynamically, and passes it the properties I defined on the object. It uses those properties to bootstrap itself. This was very cool and has a lot of potential. Also I started messing with the HSL signaling library for cross communication. In this case, I’m binding the playerSignal() method to each zone, so the game world can know a zone is entered or exited, and can display the “press space to inspire!” message.
I started putting together a cascading notification system, where an object can receive a message (the only message I care about is “the quest just completed”) and can also pass on that message to other objects. In response to a message, the object can show, hide, or remove itself. So for example in the stolen lunch quest, two workers are arguing over stolen lunch. When the riddle is solved, the main worker is notified. The main worker has a property “notifies” that contains “arguingCoworker,lunchBags”. In response to being notified, the worker notifies the other worker (who speaks his “success” line), and notifies the lunch bags (which specifies “show” for its “onNotify” property, so the lunch bags suddenly appear). I’ll be doing more stuff in this direction.
What Went Wrong
To some extent, these “wrongs” were also successes. But I suppose that’s just because failure is just an opportunity for improvement.
1. Tried to move to HaxePunk 2.x.
Mid project HaxePunk 2.x was released and I tried applying it. Everything broke instantly. For the most part I did a good job of suppressing my natural tendencies to fixate on a problem, but I wasted a couple of days trying to get 2.x working properly before I came to my senses and rolled back to 1.72a. That’s just time you don’t have to spare during a jam, even a two week jam, not if you’ve picked a project plan with no slack in it. It’s a hard lesson to learn, especially for an aging dog like me, but I have to pick my battles. It’s my Achille’s heel. This was such a unwinnable battle that, in fact, a week or so later 2.x still doesn’t work with my post-compo build. The good news though is HaxePunk 2.x is adding support for hardware accelerated blitting, so it’ll be worth the growing pains.
2. Started late, dreamed big.
I started a few days late, missing out on the initial weekend. And of course I picked new tools and game styles I’d never done before: Tiled Map Editor, Texture Packer, HaxePunk-Tiled (that’s the TMX reader), and orthogonal 2.5 perspective. This is all great learning stuff but it made it really tough to make the deadline and things had to get dropped out. I also put together 10 puzzles, plus a bonus puzzle and an easter egg. If you haven’t played the game (feel free, it’s here), it’s about an alien who is fascinated with a piece of old poetry, and uses that poetry to inspire his coworkers. The way that works is you go up to a coworker, hit spacebar, pick a stanza from the poem, and then see if that dramatically solved the worker’s problem. I came up with the puzzles first, and then worked backwards to make the poem. That was a challenge, and probably not the best way to approach it.
It was a race to the deadline, which shifted on me. I thought it was 10PM GMT-5 on Friday and they extended it to Sunday. So I busted my backside to get as much as I could in there literally down to the last moment, and then I noticed the submission was still editable. In retrospect, this probably helped me, because I was able to slow down over the next two days and address some glaring issues that I couldn’t get in by what I thought was the deadline.
Still, there wasn’t enough time to do everything. I wanted to add an end game cinematic, where after stealing from the guy who was stuck in the elevator you have a change of heart and learn from Hrothmok’s mistake. A FIRE-O-METER got dropped; this would have filled every moment you weren’t at a desk (tap tap tap!). The meter would fill rapidly if you gave a wrong quote and the boss would try to find you if the meter went red. The plants were originally a place you could hide from the boss. Now they’re just silly. Using aliens instead of humans was a time constraint compromise. Human animation was harder. I started messing with Spriter and would have loved to get some neat animation in there but there was just no time. And finally I needed a lot more art. The place was barren.
3. Three votes
For those who gave me feedback, thank you so much! I was very happy to receive it. I was unhappy with the lack of voting from the members. There were only 12 submissions. I voted for 8 of the 11 other folks, holding back from two who had voted for no games and one who had voted for one but also received some votes. I knew that Mini LDs had less participation than the regular compo, but I expected more than 3 folks to rate my game. The lack of feedback is disappointing given the amount of work I put into it. How do you get better if you don’t get critiqued? I kept checking to see if someone else would rate my game. I didn’t know when the voting was going to end, I couldn’t find that information anywhere. They also didn’t announce the rankings (here) although maybe I’m being impatient. I made it to the top two, if you consider 3 votes statistically significant.
At this point I’m a tiny bit soured on Mini LDs. I’d rather come in last place and get lots of great feedback. I do see that other Mini LDs have gotten more participation. I guess I was surprised to see the ratio between compos and minis to be so extreme (1327 vs 12). But it was a good experience overall and I’m looking forward to entering the LD#26 jam in April. I hope that the lesson “pick your battles” sticks because I’m going to need it to stay focused for 48 hours.
If anyone is curious, Hrothmok – the protagonist of the poem – is a portmanteau of Hrothgar (of Beowulf fame) and Darmok (from the ST:TNG episode).