Half-Bit Software

Lode Jogger Postmortem

I (sorta) finished another jam, this time (mostly) making Lode Jogger!

Hooboy. This one was a doozy.

What Is It?

Lode Jogger is a gameboy jam game designed to be a near-copy of Lode Runner, one of my favorite childhood games. Players must run around a level, collecting treasure and avoiding the deadly monks, before escaping through the exit.

What Went Right

Mechanics - Mostly

All of the bits of Lode Runner are here! You can run around, you fall properly, you can climb ladders and go across ropes, and the crazy monks can do all of that, too! Treasure works, digging works, everything’s there.

It’s a little bit clunky, sure, and I don’t think I got ladders totally right, but I’ll cut myself just a tiny sliver of slack. About the only thing I was missing? Monks can’t pick up treasure!

Pathfinding/AI

When it comes to jams, I usually try to avoid doing much of anything involving complicated AI. Anything risky or too intensive generally gets tossed out as unfeasable. With this, though, AI was kind of important. The monks have to try to chase you, after all!

I distilled it down into basic pathfinding: monks will try to get you. That means, of course, that I’m recalculating based on a grid. It’s pretty much just a slope field, with the bottom of the hill being wherever the player is. They’re smart enough to know that ropes might be the quickest way to get somewhere, though, which worked out nicely. For anyone curious about the technical details, it’s just a dijkstra map.

What Maybe Kinda Didn’t Go Great

Levels

I had a fine test level for making sure all of the mechanics worked sensibly - you could collect treasure, you could die by falling into a pit, ladders and ropes seemed to work okay, and monks could follow you.

The bummer is that I more or less stopped at that point. Whoopsie! I definitely should have made more levels, but I think I was just under a lot of time pressure.

Audio

I basically completely punted on audio, full stop. So. At least it couldn’t have gone worse, right? I like the idea of basic bleeps and simple bfxr boops, but in practice most of the time they’re complete earsores: too chirpy, scratchy, piercing. I’ll stick with no audio at all instead of garbage audio, and given how distracted I was by the other aspects, it’s probably good that I didn’t bother.

Graphics

I don’t hate the gameboy palette, but I also didn’t really put a whole lot of time or energy into the art of the game. 160x144 isn’t a bad resolution to work in, but my artistic abilities were not really up to the task. One of the rules of the jam was also that all assets must be made during the week: oops. I punted on that big-time, too.

Having animated tiles for digging and dying would’ve been awesome, but again, time and lack of skill were both factors. I think I was too anxious about getting some of the good parts done that I let a lot of stuff just kind of fall by the wayside. Shucks!

Final Thoughts

I’m both proud and disappointed. I poked at a few things that I haven’t really worked on before, like basic pathfinding for the monks.

At the same time, Lode Runner is one of my top-tier favorite games, so not doing it justice stung a little. It might be something I revisit later, but probably with a very different shell. The GB palette’s a little limiting, and I could do a lot better with a lot more of everything. (Sound wouldn’t be bad, either. I loved the Mad Monk’s Revenge soundtrack!)

1-Bit Clicker Jam: Clickenville

I’ve been wanting to do another jam for awhile. I like the two week cycle, but haven’t seen any themes or jams that really struck my fancy. The technical limitations ones went well in the past, so those are the ones I tend to go after.

This time, it was a 1-bit (black and white graphics) clicker (mouse only) jam. Perfect! My idea was to go after something that was a little bit like Spaceplan or a cookie clicker-esque game.

What Is It

Clickenville is a game where you try to throw money at your problems. You have a number of buildings that provide income and offer upgrade options. These buildings let you alter the world of the game how you see fit, improving things for the residents, the town, and the world as a whole.

What Went Right

This was my first experience writing a more substantial shader. The theme being a 1-bit clicker made me think, with my limited art skills, that doing a cool dithering shader would be the best way to go. That way, I could find a tileset that looked good under this visual transformation and save myself a lot of effort in the process.

It’d also kind of hearken back to some of the games I played as a kid back on a black and white computer. Atkinson dithering was pretty great back then, and doing something that resembled it sounded like a fun project.

Plus, Obra Dinn looks great with a (much better) dithering technique.

This was also a chance to poke a little bit at a different way of building up content. I knew going into it that having a whole lot of different kinds of buildings with interconnected systems and resources would be a pretty neat feature. Say, you could have a guild that trained adventurers, then send them off to explore a dungeon. Some of these adventurers might die along the way, which would leave bones for necromancers to use.

I didn’t really start out whole-hog on doing something data-driven at first, because I didn’t really understand what I wanted. Once I got a few basic classes and a really simple workflow going, though, I started pulling everything out and ended up with a little ruby script that reads a bunch of json and writes out a bunch of haxe classes for my in-game content. It worked pretty well, even if augmenting this system over time was a bit of a challenge.

What Didn’t Go Great

It’s funny, I always start writing my postmortems in this section. This time around, I basically pretended that audio didn’t exist. There’s neither catchy music nor bleeps, and certainly no bloops. It’s always something I neglect and something I’m not tremendously proficient with, so it’s kind of a self-fulfilling prophecy. Someday I’ll aim more for doing better audio work, but this time I was focused way more on the neat shader and the general mechanics.

A few mechanics are still missing, unfortunately. I wanted a workflow where you’d start off with really basic buildings and had to spend resources to unlock them, but it kind of fell out along the way. I didn’t have a great handle on how the UI ought to look or work, and letting people know what something cost was a bit of a challenge - both for unlocking buildings and for letting people know what a particular upgrade would cost.

Final Thoughts

Is it done? Heck no. Am I happy with it? Mostly, sorta, yeah.

Game jams are always a question of time but more buildings would be top of my list. Doing a full UI pass to make things make more sense would also be pretty important.

The big takeaway that I had was: well, I had everything interactable hardcoded. Was this necessary? Why couldn’t you plunk down a Blacksmith wherever the hell you wanted, if you had the funds?

This meant, in a broad way, that I was putting together an RTS instead of a simple clicker. Oops. Neat thought, though.

Oneshot Postmortem

I finished another jam, this time making oneshot!

What Is It

It’s a little arena-y shooter thing, I guess? 2-4 people jump around in a little room and try to shoot each other. Everyone only gets one bullet before having to scramble for another one.

What Went Right

Finished! It’s done, and playable, and doesn’t seem to blow up! Kudos, me.

Simple! I stuck to the bounds of the theme, once again bolstered by a technical, rather than creative, limitation.

What Maybe Kinda Didn’t Go Great

Music! Specifically, the lack thereof. This is usually one of the things I leave until the very end, and in this case, it bit me a little. I had a few beats going, but most of it was pretty godawful. Here, no music was far better than the noise I was making

Stages! Because of the limitations of the jam (5 assets, no more) I wanted to set up a bunch of different levels on just one Tiled map, using camera position to set whatever ‘stage’ is presently in use. That would’ve taken more UI and more smarts around picking that stage, though, so it got punted as well.

Playtesting! Man, this really didn’t happen. Turns out, making a multiplayer game is hard if you’re not throwing it at people to poke at. For all I know, this is actually pretty fun, but I haven’t found out yet.

Juice! I know, I know, this is kind of falling out of fashion, but it really could do with a bit more zazz. Maybe particles that fly out when you jump, or screenshake when you zap a fool. Something! It could use a lot more stuff filling in the cracks.

Final Thoughts

This one’s kinda tricky.

I think I liked the idea way more before I started fiddling with it. It started out as a kind of dual-stick shooter with only one stick: aiming was based on the direction of travel. I wasn’t sure that this’d be all that much fun to play, as it seemed like you’d be jousting, or something along those lines. You end up hoping to be pointed in the right direction, and that didn’t sound too fun.

Instead, you’re just kind of hoping to have a clear horizontal line of sight with an enemy when you pew pew a laser. I don’t know if that’s better, but it seems a lot simpler in terms of demands on the player. Different maps would likely help a lot in this situation, as would bigger maps. If I end up spinning more on this, it’ll be one of the first things I try, along with a lot of playtesting.

Overall, I’m pretty happy with it. Moving feels kinda goofy and fun, at least playing on a keyboard. Gamepad might be way more frustrating.

I’m glad I did it, which is probably a good sign!

LZRS Postmortem

I’ve been pretty sloppy in the past about recapping when I’ve actually managed to finish something. This is an attempt to be a bit more proactive and a bit less “oh right, I should’ve done that weeks ago” about a project. This time around: LZRS for #lowrezjam2016!

What Is It

LZRS started out due to an interest in the laser section from Mega Man 2. Yes, this whole game is basically just poking and prodding at a single mechanic. Lasers flying across the screen that the player needs to avoid to navigate an environment felt like a decent hook - I mean, clearly, given that a MM game used it!

Because I’m lazy, I tend to throw procedural generation at just about anything I come up with, so in this case, my initial idea from long ago was to make a generator for screens, or levels, or courses, or whatever. This makes total sense, because content takes time to make, but it also creates another problem: now you’ve got to make the thing that actually makes the thing, which can be more work. “Fun” is tricky to algorithmically generate.

And that, sadly, is where the idea sat until a few weeks ago.

What Went Right

  • It finished!

Bear with me, here - for someone chronically late on side projects, actually getting something semi-satisfactory done is a big deal (to me). Having two weeks instead of two days contributed heavily, as did having a general idea before I even knew about the jam. Most of the time, I try to start from the theme, but here the theme is more about a technical limitation, rather than creative. That’s an interesting distinction to me.

  • Platformer

It’s a platformer! Usually people tend to start with these, but not me! I’m not really very good at real-time, actiony games, likely due to lack of experience. It’s pretty exciting to have something finished that plays reasonably well. Collision happens, there’s triggers, stuff goes fwhoosh, and it all seems to behave as I’d expect. (Whether things behave as players expect is another matter entirely.)

  • Reception

People seem to like it! I haven’t woken up to any severed heads in my bed, which I consider a good sign. It’s short enough that most people should be able to finish it, and nobody’s complained about getting bored, either.

What Maybe Kinda Didn’t Go Great

Usually you go with five specifics, but to heck with that. I do what I like

I think most of what I’m unhappy with boils down to one word: incomplete. It’s a jam game, and I was pushing back and forth against what seemed like a good idea to add, and what seemed possible within the remaining time. A few hours a night is an awful lot if you’re driven with a plan, but for exploration, it ends up being a bit trickier. Experimentation is fine but it really helps if you think your new idea is going to bear fruit.

(And before I go too much farther, incomplete is from my perspective as the dude who saw everything it could have been, rather than the players going through the whole thing. Very different perspectives.)

First off, the big mechanic: lasers. Sure, they slide around, or turn themselves on and off, but from a mechanical perspective, they’re kind of lame, aren’t they? There’s no telegraphing, there aren’t any hints about whether they’re going to turn off soon, or even which kind of laser is which! It’s a little lame. They don’t move at different speeds, and they’re not even textured. Tons of work could be done here polishing and improving.

Audio’s one big area that I’m a little disappointed with, and would probably get tackled pretty soon. Just looking at the main spaceman character is a great start: sounds for footsteps, jumps, hard landings, skids - there’s plenty here that I could add to push a bit more depth and feel into things. Heck, just having multiple different sounds for the same type of event would be great for adding feel and juiciness.

This next one’s a bit tricky to explain, but the unfinished-specific umbrella is probably just ‘polish’. I’ve usually got a pretty discerning, ruthless eye about what works, what doesn’t, and what to change. Some of the tiles don’t work quite right, but more importantly, my tiles are all black with alpha. Why care? Well, I can’t really tint them, which makes me kind of bummed out. I like being able to just tweak colors a bit, and if they’re white instead of black, I can muddle with the levels as much as I’d like.

The backgrounds change as you progress through the level, after all, so why not the walls and the environment, too? This was another issue of “things work, so don’t break anything” that kept me from making too many daring changes. The hard deadline both helped and hurt me, bless its heart. Twiddling with the precise color progression for the background would likely be on my list, too, just to make sure it’s exactly what I want.

I’ve been thrilled by people posting their times and death counts and would love to have some kind of global leaderboard for scores. I don’t know that I want to do anything platform-specific, which means either picking something cross-platform or finding an acceptable third-party solution. I haven’t really gotten that far or done any thinking about it yet, but it’d be a great thing to have.

Lastly on this hate train: levels and courses. Courses feels like the right word for the sequence of, uh, ten or eleven laser-filled screens of death. I didn’t even consider it for the scope of the jam because, well, there’s no way to pick a different course on the menu. Duh! Having a bunch of courses with different themes or different mechanics would be really pretty great. Designing the levels wasn’t quite as rough as I was afraid it’d be, and making more of them might be fun.

Final Thoughts ~Brainfarts~

I’m tremendously happy with how things turned out. I’ve been itching to do Ludum Dare for ages, but the 48/72 deadlines are a bit too much for someone with a dearth of time. Having two weeks and a technical restriction made all the difference in the world, and I think going in with an easily-applicable concept helped a ton.

The game even seems pretty fun, which is always a pleasant surprise. The mechanic isn’t mine, but I can claim some of the level design, at the very least. It was a good experience and something I wouldn’t at all mind putting more time into. That alone probably makes this experiment a success.

Luxe Status Bar

Another in a long series of brief tips! If you’d like to hide the status bar on iOS (unconfirmed, so far, for Android), just set fullscreen to true in project.flow. If you want this just for mobile devices, it’s likely easiest to do in config

1
2
3
4
5
override function config(config:luxe.AppConfig) {
  #if mobile
    config.window.fullscreen = true;
  #end
}

Boom! No more status bar!

Target-Action in Luxe

There’s an incredibly common, useful design paradigm called ‘target-action’, one I first encountered on iOS. Basically, you’ve got a button that calls a function when something specific happens: maybe a touch or a drag or something. This is the basis of all of iOS’ user input.

So I thought it’d be handy to recreate something similar using the entity-component model. It’s pretty braindead-simple, but it seems to work okay for my purposes. It’s not quite as powerful as it could be, but given that I’ve already put together a game with it, I figure it’s good enough.

Here’s what the component looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import luxe.Component;
import luxe.Input;

class TargetActionComponent extends Component {
  public var mouse_up_action : Void->Void;

  public function new(?_up_action : Void->Void) {
    super( {name: "targetAction"} );
    mouse_up_action = _up_action;
  }

  override function onmouseup(e:MouseEvent) {
    if(mouse_up_action != null && cast(entity, Sprite).point_inside(e.pos)) {
      mouse_up_action();
    }
  }
}

And here’s what using it might look like:

1
2
var turkey = new Sprite({...});
turkey.add(new TargetActionComponent( function() { trace("I'm a turkey!"); } ));

The neat thing, and something I found pretty useful, is being able to rebind your target actions after creation. That ends up looking something like this:

1
t.get('targetAction').mouse_up_action = function() { trace("Gobble gobble gobble!"); };

The obvious next step is adding more triggers and actions for various input events. Touch events are a good thing to consider, as well as down-events, too - great for juicy, depressable buttons!

Another Luxe Tip

I didn’t expect to write more of these, but here I am! I wanted to document a bit of interesting behavior I found in the process of building/rebuilding a shmup.

I had this cool effect for making a sprite kind of flicker and glow a bit by adding a duplicate and making it expand and contract rapidly. I think the old way in SpriteKit used a parent/child relationship with an SKAction for the animation. In luxe, the way I’m doing it is by attaching a component to the base sprite.

This component is fairly simple. I build a sprite, attach it to its parent via the parent property (so moving it by hand is unnecessary), then add a few animations. I’ve already learned that onremoved() is the right place to do teardown, so I destroy the sprite in there and all’s well, right? Not quite.

The extra wrinkle here is that I’ve got a timer that fires after a few seconds to remove the component. Simple and straightforward - entity.remove('flicker'); - until I tried to run it. There’s a couple of annoying subtle bugs in here that made me sad.

The first is the parent-child relationship built from the sprite. The lifecycle of a sprite is this, during destroy. First, destroy yourself, then loop through and destroy your children. This means I’m double-destroying my flicker sprite! Dangit. The solution? Don’t add it as a child, and manually update position in update().

The second is that timer. See, there’s a problem there, too: what happens if you kill the parent before the timer fires? Everything gets cleaned up properly, but then you try to call entity.remove('flicker') and - boom, again! Dangit. The fix here was to save my scheduled timer and tell it to stop in onremoved(). Both reasonably simple fixes, but real head-scratchers as I was working through the issues. This isn’t even a particularly complicated situation, but making simple mistakes really bit me in the ass.

Little Luxe Tips

I’m not dead! A shock, I know, but between real-life obligations and a decline in my general state of gives-a-crap, my fun little hobby life has suffered in recent months. Shucks.

Doesn’t mean I can’t bounce back, though, right? Spring 2015-ish, I was on the hunt for something new to tinker with, and I found this rad stuff.

First off, a dumb, semi-obvious one. For anyone loading textures in config, using something like config.preload.textures.push({ id:'assets/playershot.png' }); who want nearest neighbor filtering on all of their textures, it’s important to call phoenix.Texture.default_filter = phoenix.Texture.FilterType.nearest; before you load anything. Promise - this’ll make you sad and confused otherwise. Obvious in hindsight and a real forehead-slapper once I figured it out.

Another important thing to note is that someday (soon?) phoenix is going to go away, replaced with embers. The API might look similar, and this might still be relevant, but just something to keep in mind.

I bumped into another forehead-slapper obvious issue with global events and ids. It’s super easy to just Luxe.events.listen('whatever', function() { doRadStuff(); }) - but the gotcha here was not holding onto what listen() returns. Whoopsie. That’s the thing you use later to unlisten to things, ala Luxe.events.unlisten(event_id). The worst part? This is even in the docs! Bad me.

The last tip is going to be a bit of a rambler. Luxe supports the pretty useful entity-component model of design: you’ve got your base entity, and you can lump additional behavior onto it via components, which are small little focused nuggets of goodness. I’m coming from an objc/iOS background, which means that I spotted new, init and destroy and thought, aha! That’s clearly the place to put stuff!

D’oh. Nope. See, the thing you’re attaching your component to isn’t quite ready in new - that’s just for building stuff up. Init, too, is a little early - sure, you’ll be ready, but if you want to add stuff your component after the fact (adding components to an entity returns that built component - handy for twiddling stuff immediately afterwards) - well, onadded is a better place. Teardown is similar, as onremoved happens earlier in the destruction lifecycle than ondestroy.

Slow Jam 1: Technical Postmortem

Yesterday, I posted up some of my recent thoughts and experiences on the last PIGSquad game jam. It went pretty well, and I’m pretty happy with it! This is going to be the big, ugly breakdown of how I actually put the whole thing together.

And just to repeat myself, here’s the page for the game!