Recently in Javascript Category

Quick background info, or 'what the hell is a Stylunk?'

I play Clan Lord, a multiplayer online RPG. Clan Lord provides a lot of ways for players to customize their characters' appearance, including a system for changing shirt and pants colors with an algorithmic dye and bleach system. Experimenting with dyes and bleaches in-game can be prohibitive — each application consumes in-game currency and (often rare) materials. As a result, there's a long tradition of external dye-simulation tools; the earliest was Stylus (named in the 'function-us' pattern of many Clan Lord NPCs), followed by Stylos, the OS X re-imagining of Stylus. Stylos didn't work well on Mac OS X 10.4 Tiger, so in 2005 I built the first version of Stylunk as a replacement.

Since then the number one Stylunk-related request has been for a Windows version, and the number two request is 'hey, add this new shirt color!'. Both of which were difficult enough to fill that they happened never (Windows version) and only intermittently. So I've decided to simplify cross-platform concerns and centralize updating by turning Stylunk into a web app. The beta is right here.

Stylunk Screenshot

Palettized recoloring in JavaScript or 'the actual non-background stuff about which I plan to write'

I started playing Clan Lord in 1998 and it had already been in development for a while at that point, so it shouldn't be a surprise that the tech isn't exactly modern. Images in Clan Lord are an run-length-encoded list of indices into a per-image color map, which itself contains indices into the 'Mac standard' 256 color map. That's all pretty integral to Clan Lord, because character customization is implemented as a set of 20 color overrides for the per-image colormap: indices zero and one contain the highlight and shadow colors for the character's hair, for instance.

Images for a particular icon are arranged into a single 16x3 sprite sheet, comprising the 32 standing/walking/running sprites in eight cardinal directions as well as a 'dead' sprite and fifteen 'poses' that players can activate to emote. Here's what the 'Ghorak Zo' sprite sheet looks like:

Ghorak Zo Sprite Sheet

My first stab at implementing web Stylunk was about what you'd expect: I converted each of the sprite sheets into PNG files and wrote code that draws the selected sprite into a canvas, iterates across the pixels, and replaces the 'default' colors with the mapped values calculated from the current UI selection. Then I created a smaller canvas, copied the frame I needed from the large canvas to the small canvas, and used toDataURL() to extract something that I could stick into the background-image of my buttons.

It all worked fairly well, at least at first. On my main machine (a Core i7 Mac Mini) everything was peachy. On my MacBook Air, it was sluggish. On my iPad... well, the less said the better.

My immediate response was to try some very aggressive caching, leading to the creation of a reusable JavaScript least-recently-used cache. That helped, but not as much as I'd hoped.

My next thought was: I'm doing more work than I need to: there's no point colorizing the entire sprite sheet and then only displaying a single frame of it. So I swapped things around; first extract a small canvas from the larger, then recolor only the smaller canvas. That helped too, but it was still pretty logey on the iPad.

Unfortunately there's no way to profile JavaScript in MobileSafari. But desktop Safari does have a profiler, and it showed something interesting: the slowest part of the process was reading the pixels out of the initial canvas. So I took a cue from Clan Lord and took a step back in time: instead of storing the images as PNG sprite sheets, I wrote a tool that converts each frame of the sheet into a JavaScript data structure containing a run-length encoded bunch of pixel indices. That way I can skip the 'reading from canvas' step, and jump straight to writing them. I also took the step of storing each frame as a separate JavaScript file which the main app loads on-demand via XMLHttpRequest, which simplifies the caching a lot by letting the browser do the work.

If you're curious, you can take a look at the code for a sprite here. That's my JS-encoded version of the male Ghorak Zo facing east — the top-left sprite in the image above. Yup! — despite being larger than a PNG representation or the same image, and despite needing to be parsed by the JavaScript engine, it still ends up being faster than reading data back from a canvas.

The end result is that Stylunk runs at a usable speed on my iPad (first-gen) and on my iPhone 4, which is good enough for me. There are still some minor inefficiencies as a result of the tortured path to the current architecture — if I were doing this from scratch there would also be JavaScript representations of the character color maps, which would simplify the color mapping process and also allow me to easily draw characters using the color map data from the XML data feed powering the Clan Lord Informer and iClan.

I'm actually half-tempted to do that, because it would provide a starting point for building a Socket.IO- and Node.js-powered HTML5 Clan Lord client. But that's a headache for another day.

In the course of a recent quick JavaScript side-project — post forthcoming — I needed a simple cache. Then I needed another cache within the cached objects. Then I needed another cache. It was at that point that I realized I should probably factor things out into a reusable component, and built JSLRU.

Of course then I refactored things dramatically and it's barely used at all. But if you need a JavaScript least-recently-used cache, check it out.

Generic Accumulators in C#

|
This was written in C# 2.0; if you're using 3.0 you might want to check out my updated version

I fell down a chain of links today and wound up reading one of Paul Graham's numerous pro-Lisp essays. I responded as I typically do by attempting to implement his examples in whatever language I have handy, which today was C# 2.0.

The example Graham cites in the appendix is a function for generating accumulators:

(defun foo (n)
  (lambda (i) (incf n i)))

For those of me who always find reading Lisp akin to reading the opening chapters of the Bible (but with parentheses standing in for the voluminous 'begats'), he also helpfully provides equivalents in a few other languages, such as JavaScript:

function foo(n) { 
  return function (i) { 
		   return n += i } }

An accumulator is a function that maintains internal state; when you invoke it with a new value it adds that value to its internal state and returns the new sum. An example usage would be to initialize it to zero and invoke it with each value in an array of integers; the result of the final invocation would be the sum of the integers -- or rather, the accumulation of the values.

For instance:

var myAcc = foo(0); // Initialize to zero
myAcc(1); // 0 + 1 = 1
myAcc(10); // 0 + 1 + 10 = 11
myAcc(44); // 0 + 1 + 10 + 44 = 55

So, can we build that in C#? The answer is an enthusiastic 'kinda'!

[TestFixture]
public class AccumulatorTest
{
	private delegate int Accumulator(int inc);

	private static Accumulator MakeAccumulator(int start)
	{
		int n = start;

		return delegate(int inc)
		{
			n = n + inc;
			return n;
		};
	}

	[Test]
	public void TestAccumulator()
	{
		Accumulator acc = MakeAccumulator(0);

		Assert.AreEqual(0 + 0, acc(0));
		Assert.AreEqual(0 + 0 + 1, acc(1));
		Assert.AreEqual(0 + 0 + 1 + 10, acc(10));
		Assert.AreEqual(0 + 0 + 1 + 10 + 44, acc(44));
	}
}

It's not actually that long -- the TestAccumulator function at the bottom is a quickie NUnit test case to verify it's doing what I think it should. It's still longer than the Lisp or JavaScript version though.

But there's one other major difference from those versions -- typing. The C# version only works on integers, whereas the Lisp and JavaScript version will work on anything that can be added. But if we try to genericize the C# code we'll run into problems at the n = n + inc statement, because you can't add two objects and thus can't add two generic objects without a generic constraint guaranteeing you can. And since there's no IAddable interface that integers and floats and strings and everything implement (and since C# still doesn't have a more generalized form of where clause that would let us specify constraints as duck types rather than static types), we're basically SOL with a generic C# accumulator.

Or are we? (Bum-bum-BUM!)

What if we passed our MakeAccumulator function two parameters: a starting value, and a delegate function to use for incrementing?

[TestFixture]
public class AccumulatorTest
{
	private delegate T Accumulator<T>(T inc);

	private delegate T AccumulationDelegate<T>(T a, T b);

	private static Accumulator<T> MakeAccumulator<T>(T start, AccumulationDelegate<T> accumulationDelegate)
	{
		T n = start;

		return delegate(T inc)
		{
			n = accumulationDelegate(n, inc);
			return n;
		};
	}

	[Test]
	public void TestIntAccumulator()
	{
		Accumulator<int> acc = MakeAccumulator(0, delegate(int a, int b) { return a + b; });

		Assert.AreEqual(0 + 0, acc(0));
		Assert.AreEqual(0 + 0 + 1, acc(1));
		Assert.AreEqual(0 + 0 + 1 + 10, acc(10));
		Assert.AreEqual(0 + 0 + 1 + 10 + 44, acc(44));
	}

	[Test]
	public void TestFloatAccumulator()
	{
		Accumulator<float> acc = MakeAccumulator((float)0, delegate(float a, float b) { return a + b; });

		Assert.AreEqual(0 + 0, acc(0));
		Assert.AreEqual(0 + 0 + 1, acc(1));
		Assert.AreEqual(0 + 0 + 1 + 10, acc(10));
		Assert.AreEqual(0 + 0 + 1 + 10 + 44, acc(44));
	}

	[Test]
	public void TestStringAccumulator()
	{
		Accumulator<string> acc = MakeAccumulator("", delegate(string a, string b) { return a + b; });

		Assert.AreEqual("" + "", acc(""));
		Assert.AreEqual("" + "" + "marklar", acc("marklar"));
		Assert.AreEqual("" + "" + "marklar" + "smurf", acc("smurf"));
		Assert.AreEqual("" + "" + "marklar" + "smurf" + "foo", acc("foo"));
	}
}

Yay!

So what is it good for? Absolutely nothing! But it sure was fun!

Pages