Friday, April 11, 2014

melonJS should be *All About Speed* Part 2

If you haven't already read Part 1, head over to that article for some important background information before continuing below.

Part 1 : http://blog.kodewerx.org/2014/03/melonjs-should-be-all-about-speed.html

Deep Copy

In version 0.9.11, we quietly rolled out a little feature that allows including complex objects in class descriptors for the inheritance mechanism we have been using (John Resig's Simple Inheritance). This allows, for example, creating classes with properties that instantiate other classes, or include arrays or dictionaries. It works by modifying Object.extend to do a deep copy on all of the non-function properties in the descriptor. This feature came about by ticket #307. You'll find some discussion in the ticket about why it doesn't work without deep copy, and some of the ugly prototype hacks we had to use to get it working.

Once the deep copy was all well and good, it came right back to bite us! That isn't surprising, to say the least. But it has caused one bug report so far, due to cyclic references and object pooling in #443. (Pooling is a method of reusing objects by resetting their internal state, which we will cover momentarily.)

Deep copy is unfortunately very slow. It's the process of iterating each property and determining the data type, then performing a shallow copy for simple objects like numbers and strings, or another deep copy for complex objects like arrays and dictionaries. Because the complex objects are reference types, they may create circular references, the simplest example being object A references object B, and B has a reference back to A. These object cycles are hard to deep copy, because you need to protect against copying the same object more than once. If that protection is missing, you quickly enter an infinite loop or stack depth overflow with recursion.

Even worse, this deep copy needs to be done at object instantiation time, so it will be dramatically slow to use the new keyword on any of your classes. Mix that with large classes, and your game will be in a lot of trouble!

That's why I decided not to include deep copy in Jay Inheritance. In fact, I took it even one step further and specifically made all properties immutable when added to a class. So if you define integers using the class descriptors, you'll find that you are not allowed to change the values in those properties. This should get the idea across that class descriptors are for methods only. No exceptions. And all in the name of speed.

Object Pooling

Deep copy was added as part of the object pooling revamp in 0.9.11. The idea was to simplify child object creation, by allowing child objects to be defined in the class descriptor. All children would be copied into the new object automatically as part of the Class constructor. And a bit of background on this decision: The pooling mechanism has to call the constructor to reconfigure objects when reusing them. And you don't want the constructor to create new child objects when the children already exist! That would defeat the purpose of pooling.

But now we know that was not the right way to fix child object creation with object pooling. A better approach is to embrace separation of responsibilities, allowing each part of the pooling mechanism to be responsible for one thing and one thing only. In the case of child object creation, that responsibility relies with the constructor, not the class descriptor.

We've supported pooling for quite a long time. But it has been broken, to be honest. The reason I say "broken" is due to the way the object life cycle works in melonJS. There's the init method which is the "user" constructor, and an onResetEvent method which is for resetting internal state of the object, and finally there is also a destroy method which can be used as a destructor.

  • init : Constructor, called when the object is created with new.
  • destroy : Destructor, called when the object is deactivated.
  • onResetEvent : Reset internal state, called when the object is reactivated.

Unfortunately, these methods are poorly defined within the object life cycle. For example, destroy is not called when the object is ready for garbage collection! Instead, it is called when the object is deactivated; when it is placed into the pool for later reuse. This means destroy cannot safely be used as a destructor unless onResetEvent also does constructor work, like creating child objects and event listeners. This is broken by definition; only the constructor should do constructor work.

To complicate matters, only a few classes have an onDestroyEvent callback that is called by the default destroy method. It's treated as a user-defined destructor, of sorts. But again, it is only called during object deactivation, and only very rarely used.

To fix all of these issues, we need to define the object life cycle concretely. A clear separation between construction and activation, and between deactivation and destruction is necessary to make pooling work effectively. To that end, here is my proposal for the life cycle methods, and when they are called:

  • init : Constructor, called when the object is created with new.
  • destroy : Destructor, called when the object is ready for garbage collection.
  • onResetEvent : Reset internal state, called when the object is activated/reactivated.
  • onDestroyEvent : Disable object, called when the object is deactivated.

For clarity, "deactivation" means the object is removed from the scene graph, and placed into the pool for later reuse. This is the signal to your object that it should remove any event listeners. Likewise, "activation" means placing the object into the scene graph ("reactivation" is when an object is reused from the pool). This is a signal to the object that it should reset its internal state, the internal state of its child objects, and adding any event listeners.

The constructor still needs to define all of the object's properties, and set values on them. This also means creating new child objects and setting their default internal state.

Finally, the destructor will make sure to remove any kind of "global state" changes that it has made, like event listeners, loaded resources, timers, tweens, etc.

The life cycle of an object without pooling then looks like this:

  1. init
  2. onResetEvent
  3. onDestroyEvent
  4. destroy

And as you might imagine, the life cycle of an object in the pool might look more like this:

  1. init
  2. onResetEvent
  3. onDestroyEvent
  4. onResetEvent
  5. onDestroyEvent
  6. ...

Without ever calling destroy. It will just continually be deactivated and reactivated as needed.

This API can make object pooling faster by being very strict about where in the object life cycle child objects can be created. For example, a shape object needs a vector for positioning. As long as this vector is only created in init, there will be no garbage collection thrashing when the shape object is pooled. Worst case, the position vector only gets reset (x and y properties updated) each time the object is reactivated with onResetEvent.

One final note here is that I want to establish these method names as the de facto object lifetime methods within the entire game engine. Not just for objects which get added to the scene graph, but for everything; even me.ScreenObject has had an onResetEvent callback implemented forever. It's slightly different though, called just after the registered state has been switched to. And onDestroyEvent is called when the state is switched away. But still very fitting.

Resetting Object Internal State

Now would be a good time to also touch on how I expect the object internal state to be set initially in the constructor. The answer is simply "don't care!" I cannot recommend having init call onResetEvent, due to inheritance rules; It would be a bad idea because both methods must call the overridden method on the super class. You would then have onResetEvent getting called multiple times at constructor-time! That would be slow and dumb. The right way to set initial state is to do so in the constructor only if you have to. Otherwise do all of the configuration when the object is added to the scene (handled by onResetEvent).

Here's some example code to help illustrate the concept:

var x = Math.random() * me.video.getWidth();
var y = Math.random() * me.video.getHeight();
var z = 9;
var particle = me.pool.pull("Particle", x, y, { "image" : "flame" });
me.game.world.addChild(particle, z);

This code will fetch an object from the pool that was registered with the class name "Particle", and pass some constructor/reset parameters. In the case that the "Particle" pool is empty, a new object will be instantiated, and the parameters are passed straight to the constructor. In the case that a "Particle" object is reused from the pool, it's constructor will not be called. Finally, the particle is added to the scene graph, and its z-index is set properly.

And this is where we need to make some big decisions! The pooling mechanism today actually does call the constructor in the latter case, which is very bad because the constructor should never have to worry about whether a child object already exists... In my mind, the child objects will never exist when the constructor is called, so it is only responsible for instantiating the children.

I would like this reuse path to rely on onResetEvent being called by me.game.world.addChild(), which will pass along the "object state" configuration parameters, probably even removing these parameters from the constructor entirely. In other words, the example code needs to be changed to this:

var x = Math.random() * me.video.getWidth();
var y = Math.random() * me.video.getHeight();
var z = 9;
var particle = me.pool.pull("Particle");
me.game.world.addChild(particle, x, y, z, { "image" : "flame" });

You will also notice the z parameter when adding the object to the scene graph. This has always been there! And it feels quite nice to finally put all of the coordinates together in the same place. The point to take away from this is that creating the object is not enough to actually use it, so why configure its internal state at constructor time? Especially if the constructor may not even be called because the object is just getting reused!

Simplified: create an unconfigured object, add it to the scene with configuration. The same pattern works equally well without pooling, just replace the me.pool.pull() call with the new keyword:

var x = Math.random() * me.video.getWidth();
var y = Math.random() * me.video.getHeight();
var z = 9;
var particle = new Particle();
me.game.world.addChild(particle, x, y, z, { "image" : "flame" });

Configuring Objects Without the Scene Graph

This is another good point to cover before I wrap up pooling changes! There are some objects which can be reused that never get added directly to the scene graph, or rather they discretely add themselves to the scene graph without the user's knowledge. me.Tween comes to mind immediately! This class uses the scene graph to ensure it updates object properties at the right time, and it adds itself to the scene graph when its start method is called. For this specific object though, I think it will be enough to reset internal state in onDestroyEvent, when it is removed from the scene. That will set it up for reuse later, without an extra reset step anywhere else.

For other objects like me.Color and me.Vector2d, my first thought is making the configuration step explicit, by calling onResetEvent directly. But that seems kind of silly, especially for people used to passing configuration parameters to the constructor in classical Object-Oriented Programming. But maybe it really is that easy? If you want to use pooling, call the object's onResetEvent to configure the object after it is retrieved from the pool. If you don't need pooling, pass configuration to the constructor!

// Object without pooling
var v1 = new me.Vector2d(10, 50);

// Object with pooling
var v2 = me.pool.pull("me.Vector2d").onResetEvent(10, 50);

These kinds of classes need to duplicate configuration code, because as mentioned earlier it's not a good idea to call onResetEvent from the constructor. Hopefully these classes will all be simple enough that the possibility of double-configuration (constructor directly followed by onResetEvent) will not be a large burden. Though we can be smart about it by counting arguments passed to the constructor, if necessary.

Conclusion

With that, we should be on our way to a very streamlined, GC-friendly game engine! Next time I'll talk about optimal array management; speeding up node addition/removal in the scene graph and object pool.

Saturday, March 22, 2014

melonJS should be *All About Speed*

I've been working on melonJS since I first used it in July 2012. It's now over 1.5 years later, and we've learned a lot as a team. One particular area of melonJS that I have focused a lot of time is performance. And in this article, I will try to describe current pain points and what we are doing to make them better.

TL;DR: A super fast prototypal inheritance microlib for the modern web. https://github.com/parasyte/jay-extend

Simple Inheritance

melonJS has always used John Resig's Simple Inheritance pattern, like many of the HTML5 game engines available. While looking for things to optimize, I stumbled upon some funny code with regular expressions in the Object.extend helper function. If you've never looked at the source, you can head over to John's original article where he introduced it. The RegExp is a hack to determine if the browser can coalesce functions into a string; in other words, it is a test to determine if the browser is capable of decompiling functions. But why on earth would it need to decompile functions? Well, for syntactic sugar, of course! To save the programmer from typing prototype so often.

To see how that regular expression got there, we first have to do some code archeology. One of the best ways to illustrate is to reinvent it. All the code I will be showing here was run using jsfiddle with my browser's web console open.

Let's start with prototypal inheritance; the concept of creating a function in a prototype form (a class), then instantiating objects from that class. Here is a very simple example of a class which shows a constructor and an accessor method:

function Foobar() {
    this.num = 123;
}

Foobar.prototype.setNum = function (num) {
    return this.num = (typeof(num) === "number") ? num : this.num;
};

In this example, the function named Foobar is the class, and its body is the constructor. Then the class prototype is modified to include an accessor method. Let's instantiate an object with this class and try it out:

console.clear();

var f = new Foobar();
console.log("Expect 123:", f.num);
console.log("Expect 9000:", f.setNum(9000));
console.log("Expect 9000:", f.setNum("abc"));

If you run the code, you'll see that it does work as intended! This is the classic example of prototypal inheritance in JavaScript, and you will see it used in tons of libraries today. But as you start to add more and more methods to your class, you will be typing prototype quite a lot. A little syntactic sugar can hide prototype by iterating over a descriptor which defines the methods you want added to the prototype.

Object.prototype.extend = function (Class, descriptor) {
    for (var method in descriptor) {
        Class.prototype[method] = descriptor[method];
    }
}

function Foobar() {
    this.num = 123;
    this.str = "xyz";
}

Object.extend(Foobar, {
    "setNum" : function (num) {
        return this.num = (typeof(num) === "number") ? num : this.num;
    },
    "setStr" : function (str) {
        return this.str = (typeof(str) === "string") ? str : this.str;
    }
});

I've added a second accessor method to our Foobar class, and also created a new function called Object.extend (same name as used in Simple Inheritance, by the way) which provides the syntactic sugar we were looking for. Hooray! No more prototype in our class definitions. And here's another quick test to prove that it works:

console.clear();

var f = new Foobar();
console.log("Expect 123:", f.num);
console.log("Expect 9000:", f.setNum(9000));
console.log("Expect 9000:", f.setNum("abc"));
console.log("Expect xyz:", f.str);
console.log("Expect abc:", f.setStr("abc"));
console.log("Expect abc:", f.setStr(9000));

Now what about inheritance? In JavaScript, you can do single inheritance quite simply by replacing the class prototype with a copy of the prototype from another class. There's a function built into the language for doing exactly that: Object.create.

(Side note: Object.create is a relatively recent addition to the JavaScript language, and Simple Inheritance pre-dates its inclusion. So Simple Inheritance uses a trick involving the instantiation of the object itself with a little hack to prevent the constructor from running during the prototype creation phase. See John's article for more details on that little catch.)

In order to create the inheritance chain, we need to modify Object.extend to return an empty class whose prototype is given a copy of the base class (thanks to Object.create). Because the empty class has its own constructor, we need a way to run the user's constructor. Again, following the Simple Inheritance API, we'll adopt init as the name of the user's constructor, and simply call that if it exists.

Object.prototype.extend = function (descriptor) {
    function Class() {
        if (this.init) {
            this.init.apply(this, arguments);
        }
        return this;
    }

    Class.prototype = Object.create(this.prototype);

    for (var method in descriptor) {
        Class.prototype[method] = descriptor[method];
    }

    return Class;
}

We'll use this updated Object.extend to recreate our base class Foobar, then create a Duck class that inherits from Foobar.

var Foobar = Object.extend({
    "init" : function () {
        this.num = 123;
        this.str = "xyz";
    },
    "setNum" : function (num) {
        return this.num = (typeof(num) === "number") ? num : this.num;
    },
    "setStr" : function (str) {
        return this.str = (typeof(str) === "string") ? str : this.str;
    }
});

var Duck = Foobar.extend({
    "speak" : function () {
        return "quack";
    }
});

And then we'll write a simple test to verify it all works as I claim:

console.clear();

var d = new Duck();
console.log("Expect 123:", d.num);
console.log("Expect 9000:", d.setNum(9000));
console.log("Expect 9000:", d.setNum("abc"));
console.log("Expect xyz:", d.str);
console.log("Expect abc:", d.setStr("abc"));
console.log("Expect abc:", d.setStr(9000));
console.log("Expect quack:", d.speak());

There you go! The reinvention of Simple Inheritance is complete. Well, almost! What happens if you want to override a method, instead of just adding new ones? You can do that with the above code, sure, but you probably want to run the overridden method, as well. This is done by going back to the prototype chain, again! Let's modify Duck to append "quack" to every string set:

var Duck = Foobar.extend({
    "speak" : function () {
        return "quack";
    },
    "setStr" : function (str) {
        return Foobar.prototype.setStr.call(this, str + " quack");
    }
});

This prototype mess is how we call a method on the super class in JavaScript! Yes, it's normal. Yes, it's ugly. Yes, that's why Simple Inheritance adds more sugar in the form of this._super! The problem to recognize is that binding the instantiated object reference (this) to a method on the prototype chain is hard to do in a generic way. John's solution is creating a proxy method called _super which redirects method invocations to the same method name on the super constructor. It manages this via a series of closures to retain scope in the prototype chain.

In order to create each proxy method, Simple Inheritance adds checks to the descriptor iteration to find methods (functions). For each method found, a RegExp test (!) is run to determine whether a proxy should be added. This, at long last, answers our original question, "why does Simple Inheritance need to decompile functions?" Frankly, it doesn't need to decompile anything! But as an optimization, it won't add the proxy to methods that don't need it. And it determines which methods need the proxy by decompiling the function; looking for a string that matches _super. So if _super is ever used in the method, it gets a proxy that adds the _super property!

"But isn't decompiling functions slow?" ... Yeah, probably!

"And isn't running a regular expression over a long function-as-a-string also slow?" ... I would say so!

*sigh*

And so began my adventure to make Simple Inheritance fast! Actually, I did so much of my own work here to reinvent Simple Inheritance that I'm just going to release it on its own, with a nod to John Resig for the inspiration.

I made _super fast by adding the proxy within the Class constructor, rather than during prototype creation time. This means that none of the methods get proxied automatically; instead, _super is the proxy. After going through multiple failed tests, I found the best interface for _super is actually closer to Python than Simple Inheritance. Notice that the Python super() function takes two arguments; a reference to the super class, and a reference to the instantiated object.

All that means is _super in Jay Inheritance looks like this:

var B = A.extend({
    "foo" : function (arg1, arg2) {
        this._super(A, "foo");
        this._super(B, "bar", [ arg1, arg2 ]);
    },
    "bar" : function (arg1, arg2) {
        // ...
    }
}

Quite a bit different from Simple Inheritance! And there is also a big difference between my final implementation and Python's super() function, which returns a proxy to the super class. If I were to do that, it would require another iteration, which I'm not willing to do, for the sake of raw performance. So instead, my _super interface accepts a reference to the super class, and a method name, followed by an array of arguments that will be proxied to the super class method.

Requiring a reference to the super class also allows calling sibling methods on the class, without going through the normal prototype chain. This is useful for base classes where you don't want to call overridden methods. Simple Inheritance does not have this functionality in syntactic sugar form; you'll have to use the ugly prototype mess for that.

As an added bonus, I also include mixin support, which allows adopting methods from a class without inheriting its prototype.

Finally, I've wrapped all of this knowledge into a single project called Jay Inheritance, named after yours truly. Here is the official gist: https://gist.github.com/parasyte/9712366 and I also have the same code on jsfiddle, where the tests can be run directly: http://jsfiddle.net/Qb7e8/6/ (Update, July 2015: the project has been release as jay-extend: https://github.com/parasyte/jay-extend and is available through dependency managers npm and bower.)


Jay Inheritance is as screaming fast as classical inheritance patterns can get in JavaScript. From here, we need to refactor melonJS classes to use it, and also to make the classes much smaller! Objects with too many properties are hard for JavaScript engines to optimize. For example, the V8 engine in Chrome switches to slow-mode when an object has about 30 properties. Source: http://youtu.be/XAqIpGU8ZZk?t=25m07s Property access also uses type-specialized optimizations, so we should not be changing the data type stored in any properties, nor adding or removing properties outside of the constructor.

In the next article, I'll talk about some modifications that were recently made to Simple Inheritance in melonJS, and why this was a bad idea from a performance perspective. I'll also go over some ideas that we can use to improve the situation in the future with the inheritance pattern.

Thursday, December 12, 2013

Ludum Dare #28; "I'm in!"

I've posted about LD48 on other forums, but I want to write a quick note about it here on the blog, as well. Maybe it will help catch a bit more attention, too. Every little bit helps! ;)

Ludum Dare #28 is starting this weekend! I will be participating, and streaming my progress live on Twitch for the full 48-hour duration. Everyone is invited to join and get involved! I'll be accepting suggestions and ideas live. (I cannot accept any resources like graphics, code, music, or sound effects, as that is against the compo rules.)

I will be making an HTML5 game using melonJS, which I will be semi-frequently publishing to github. This means you will be able to load the game and give it a try as I'm making it. I'll get instant feedback and play testing, and you might get to see your suggestions added in minutes! That's pretty awesome.

You can catch the live stream on Twitch starting Friday evening at 6:00pm Pacific (GTM -0800). The link is:

http://www.twitch.tv/kodewerx

Also, be sure to follow me on Twitter, so you can keep up-to-date on any project news and streaming announcements: @kodewerx

I have my streaming setup tested and ready to go! No telling what I will make yet. It will probably be something totally random, based on whatever theme is chosen. In any case, thanks to everyone who has said they will drop in! I'm really excited about this. It will be my first Ludum Dare, and first live stream event. I'm thinking it will be full of unintentional hilarity!

See you Friday!

Monday, December 2, 2013

A Walk in the Park Turbo: #1GAM November and #CharityGameJam II Turbo

A Walk in the Park Turbo

(Clicky for Make Big)

It's been a looooooong time since my last #1GAM entry. This time around, I started making a classic text adventure; a project I've been wanting to do for at least month. I was heavily inspired by a documentary called Get Lamp.

The game is called "A Walk in the Park Turbo", as it lovingly shares the moniker for #CharityGameJam II Turbo. The Charity Button (visible in the animation) points the player directly to the donation page for Child's Play Charity. Don't forget to make a contribution!


About the Game

"A Walk in the Park Turbo" follows in the footsteps of the earliest video games, which can be classified under the genre "interactive fiction". If you've ever read a "choose your own adventure" book, you know exactly how these games play; the player is thrown into a scenario, and left to her own devices to discover the correct actions to claim victory.

The classic text adventures are remarkably minimalistic, but can be surprisingly deep. AWITPT was made in just two days. And though there is not a whole lot to actually do, the biggest parts of the game were made near the end of that two-day sprint. Most of the development time went into building the core foundation. Which is a shockingly simple JSON data structure that the game dynamically modifies as you make your way through the puzzles.

How to Play

Text adventures are notorious for being difficult to get a grasp on. Especially for beginners. Because the user interface is all about typing commands, you'll find yourself stuck often until you can figure out which commands the programmer expects you to type ... and sometimes even in the proper order!

The general recommendation to get started is to try typing different words, and see what happens. In AWITPT, the commands are almost always verbs (but they can be shortened in some cases). There are movement commands, like "go" or "walk" which also expect a direction. Or you might be able to shorten it to just the direction. Another common command is "look" or "search" to look at your surroundings, and at items that may be available in your current location. You can also take items, and use items, check your bag (inventory), and inspect or use items in your bag. Items in your bag can also be used on some of the stuff you see in the area.

Puzzles

Text adventures are all about puzzles; How to find the right items, and use them correctly to unlock new paths. AWITPT is no different! To date, there are only 6 available areas, with most of them serving a purpose of gaining one or more items. Getting into two of those area requires using one of the items you can collect. ;)

Music and Sound Effects

I composed the music many years ago, originally as a soundtrack for a short film idea I had, called "Milksharks". The concept was a bit absurd and comedic; tiny sharks that swim around in your cereal bowl. The film never got started, but I was inspired enough to create a short music track for it. It's a calm tune that starts with an upbeat cello, and evolves over to other instruments.

The soundtrack is available on Soundcloud.

All of the sound effects (the punches and kicks on the logo) were sourced from CC0 (public domain) sounds made available on freesound.org.

The Future of A Walk in the Park Turbo

Like I mentioned at the beginning of the article, this genre is one I've really wanted to try my hand at. So I'm glad I've finally got the basis for it worked out. I'm sure I'll come back to this one to add more areas and stuff to do. I don't actually have any story elements planned for it. I want to just let it evolve naturally. In a very silly, almost dream-like game world. The best part about making a text adventure is that anything I can imagine can be put into the game. As realistic or as fantastic as I like. This game is truly a medium for artistic expression.

Apart from adding the more areas to explore, I also want to add some pretty visual effects. The game is written with a 2D canvas, so why not use it! Audio is another thing I want to highlight. Both of these enhancements will feel very much out of place in an old school text adventure. But that's really what I'm going for, here! Bringing a classic genre up to modern standards. The addition of the "Turbo" subtitle kind of sets that stage, both in name and in its very introduction on the title screen.

Make Games ...

Play online : http://blipjoy.github.io/awitp/public/index.html
Source code : https://github.com/blipjoy/awitp
#CharityGameJam : http://www.charitygamejam.com/
#1GAM : http://www.onegameamonth.com/kodewerx
Twitter : @kodewerx

With that, I will leave you with my traditional closing statement;

Make Games, Support Charity!

Wednesday, May 1, 2013

1GAM April: Postmortem

Sprung Fever

(Clicky for Make Big)

The game is officially complete! I just added the last remaining bits (item sprites, courtesy Matwek!) and I also released the game earlier today on #1GAM.

And now it's postmortem time! YAY!

Development Process

melonJS 0.9.7 is a real pleasure to work with! This game ships with a build that is about as close to final 0.9.7 release as possible (there may be a patch or two that gets committed between now and release, but it's effectively the same). The new features that I made extensive use of this time were:

  • TexturePacker support
  • JSON TMX map support
  • me.Renderable
  • me.sys.isMobile
  • me.Viewport.shake
  • TMX settings JSON parsing
During development, plenty of bugs were discovered and fixed, which is nice for the melonJS community! I'm super pleased with how melonJS 0.9.7 has turned out!


What Went Right

Wow! What can I say? Both artists did great on the assets they were able to deliver, and it all works together as a cohesive whole! Great job and a huge thanks to both Matwek and Burcag!

On the coding side, everything went rather smooth... There's lots of fancy stuff happening behind the scenes and on screen, so keep a look out for it! The fullscreen overlays worked really well, and they were incredibly easy to build. Girl AI is basic, but it gets the job done. The particle emitters are flawless. Mobile control works well (if a bit lacking in tactile response). And the sound effects make me really happy.

My favorite of all sound effects is the heartbeat. But it's so bassy, you can only hear it with good headphones or a subwoofer. That's actually a plus, as well, since playing the game with a good sound system is PHENOMENAL. And even though the music is completely auto-generated (with some tweaks) it's still catchy enough to get stuck in my head.

The gameplay also turned out to be incredibly fun. A coworker asked if she could play it last week, so she became the first play tester in the office. Her reaction was priceless. That's when I really knew it was a good game. It's definitely the most fun of all my projects so far.


What Went Wrong

Even though I have been working with two artists this time, I still feel like getting art assets has been troublesome. The girl in the blue dress was never animated for up/down movement, and the environments feel a bit repetitive/on a grid. (If you've played Neverwell Moor, you'll see what I'm talking about; that game hides the grid quite well, and it's all thanks to the art assets!)

Music was VERY difficult. I spent a lot of time just screwing around until I had something that I liked. If I had more patience with it, I would teach myself to make chiptune-sounding music in GarageBand. Or else I get music that sounds pretty nice, but doesn't fit the old-school theme. :(

This project sounds pretty simple on paper, but in reality it was a lot of work! There are just so many variables, like player control, collectable items, game stats (HUD), enemy AI, etc. But the biggest time consumer for me was probably mapping. Definitely not my favorite thing in the world... And it's frustrating to be working on a map and realize half way into it that you're missing a rather vital tile. You might notice some funny looking shadows on the left and right side of the grocery map! Well, that's because there isn't a tile for left and right walls that also don't have the shadow. Just a single example of many...

And finally, I started this project later than I should have, giving us only 3 weeks to work on it.

What To Do Next Time

Too many cooks in the kitchen! I'll have to work with just a single artist on my next project. I ended up doing about 1/4 of the graphics myself. I would like to get to the point where I do 0% of the graphics. Just like the artist would expect to do 0% of the coding. It just makes sense...

And I still need a musician. :)

1GAM April: Day 23 (Finale)

As of tonight, I am done with the 1GAM April project, Sprung Fever. Regretfully, it is identical to last night's build. I got caught up with other things tonight, and the artists working on the project were unable to complete the last remaining assets for the last day of the month.

However, this is only the end of the initial development cycle! And as new assets come in, and new ideas come up, they may very well find their way into Sprung Fever.

I'll have a full postmortem for the project in the coming days. In the meantime, enjoy the game! And I'll be starting a new project within the week. As well, I'll pick up where I left off with the new collision detection system for melonJS. That should be completed for 0.9.8 in about two months! And 0.9.7 is coming literally any day now... Things are really looking great so far!

That's it for now! See you in a few days!!