Random Invaders

Random Invaders I keep running across the incorrectly named invader “fractal”. I originally saw the invader fractal on levitated, created by Jared Tarbell. Shortly after I noticed it at complexification, also Jared. There are also some sketches on openprocessing.org. It was in large part to seeing a lot of these lately that I decided to put together my own implementation.

Demo Controls

These controls will change any new invaders that are drawn.

  • Fill Ratio: How much of the invader canvas should be filled, expressed as a ratio in the range [0 (empty) ; 1 (full)]
  • Light Color: The base color to use for the light pixels
  • Dark Color: The base color to use for the dark pixels
  • Light to Dark Ratio: The amount of light vs. dark pixels, [0 (dark) ; 1 (light)]

Resetting controls

These controls will redraw the whole display, e.g. all invaders.

  • Invader Width: in pixels
  • Invader Height: in pixels
  • Scale: how much to scale the invader by
  • Gap: The gap to leave before placing the neighbouring invaders
  • Reset: Same effect as changing any of the above parameters, e.g. used primarily in conjunction with the runtime controls.

Algorithm

  1. The width of the invader should be an odd number. No check for this currently.
  2. Iterate over the first half of the pixels. Avoid the middle width, e.g. Math.ceil(width / 2)
  3. For each pixel, determine whether it is filled, given the fill ratio.
  4. Next determine the color between light and dark, given that ratio.
  5. Fill / empty the pixel with the given setting and mirror to the other side of the center width.
  6. Lastly, iterate over the center pixels using the same steps as 3 and 4 above.

Some people use an integer to seed the invader. Then use bitops to determine which pixels are set in the seed. However, that way has some limitations. This way has two main benefits over that one.

  1. There is no upper limit imposed by the total bits. An integer for instance is 32 or 64 bits and thus you limit the amount of maximum pixels in the one half to 32 or 64 pixels.
  2. The method listed above works well when there are binary colours. You would need to use a number system base 3 to seed three colours, 4 to seed four colours.

Both of the above limitations can be overcome by using a random number generator and seeding that rather. I have not used a seeded random number generator in this case, but it is not too difficult to swap out the current one.

Additional Effects

  • An randomly selected invader changes every 25ms.
  • Two randomly selected invaders scale up to double their scale and back down to their normal scale every 300ms.

The Code

package net.avdw.generate
{
	import flash.display.BitmapData;

	public function makeInvader(width:int, height:int, fillRatio:Number = .5, lightToDarkRatio:Number = .5, lightColor:uint = 0xFFCCCCCC, darkColor:uint = 0xFF333333, bmpData:BitmapData = null):BitmapData
	{
		var r:int, useColor:uint;
		if (bmpData == null)
			bmpData = new BitmapData(width, height);

		bmpData.fillRect(bmpData.rect, 0);

		var col:int = Math.floor(bmpData.width / 2);

		for (var c:int = 0; c < col; c++)
			for (r = 0; r < bmpData.height; r++)
				if (Math.random() < fillRatio)
				{
					useColor = Math.random() < lightToDarkRatio ? lightColor : darkColor;

					bmpData.setPixel32(c, r, useColor);
					bmpData.setPixel32(bmpData.width - 1 - c, r, useColor);
				}

		for (r = 0; r < bmpData.height; r++)
			if (Math.random() < fillRatio)
			{
				useColor = Math.random() < lightToDarkRatio ? lightColor : darkColor;
				bmpData.setPixel32(col, r, useColor);
			}

		return bmpData;
	}

}