• entries
90
66
• views
73476

Serious programming of casual games in Actionscript.

## Propagation By Water, part 1

Click the image to play with this one.

This is my first go at the "Propagation" portion of the UnOfficial Four Elements Contest. Not complicated; click and drag your mouse around the bitmap and watch the particles spawn and flow downhill.

Simple mechanic: each particle sniffs each of the eight pixels around it, and goes toward the darkest one. If the darkest neighbor is the same color as the current pixel, it stops moving. I check the neighbors from upper left to lower right, so there is a bias toward the upper left in case of a tie between more two or more neighbors. Adding vector data to the particles will take care of that.

It will take a lot more work to make this usable in a game. It also gave me an idea for making a simple erosion simulator which will make the terrain much more realistic...if it works.

## Declarative Declarations

I haven't had much time to code this past week, but I have thought quite a bit about how the different parts of the game will fir together. Right now I am sorting out the logic of re-creating a biosphere from scratch, and how the elements of propagation and evolution will fit in. Research has led me in some interesting directions; I picked up a college text-book on botany, and spent a good long time browsing Wikipedia, specifically looking at Ecological Succession. I also grabbed a book called Where Our Food Comes From: Retracing Nikolay Vavilov's Quest to End Famine. Put together, these sources prompted me to change the focus of my game, from re-starting a global ecology, to something much more local - create a regional ecosystem, over the course of some decades or centuries, which will ultimately be (a) self-sustaining, and (b) be able to support a population of recently-thawed humans. Yeah, the basic story/plot is kind of weak at the moment, but the technical issues with putting such a game together are quite interesting.

Because I have no experience in ecology, biology or botany, I found myself at a loss as to where to begin. So I have started an exercise which has previously helped me make sense of information architecture problems: make a long list of simple, declarative statements, then order them, add to them, and flesh them out, until I have a design document. Here is my "ecology" list at the moment:

All plants require sunlight.
All plants more complex than algae require a solid surface for growing
All plants have chlorophyll, which reacts with sunlight to create nutrients
Algae scattered on ice will trap sunlight, and heat up enough to melt ice
Lichen can grow on bare rock
Moss can grow on bare rock and in minimal soil
Plants growing on bare rock will begin to erode the rock, creating sand.
When plants die, they mix with the sand to create soil
The more complex the plant, the more nutrients it needs to grow
The larger the plant, the stronger its root system needs to be.
Taller plants need deeper roots.
The more surface area a plant has, the more sunlight it collects.
More leaves mean the plant needs to be either wider or taller
Faster growth means faster propagation
Faster growth means shorter life
Faster growth means more fragile plant
Plants can propagate by water, wind, or mechanical means
Plants which propagate by water can only propagate downstream
Plants which propagate by air can only propagate in the direction of the wind
Plants which propagate by air can disperse to a wider area
Plants which propagate by water propagate more densely in any given area
Fitness is the likelihood that an individual will produce viable offspring
Plants need to reach a certain maturity before they can reproduce
Plant populations need to reach a certain density before they can effectively propagate
plants need to reach a level of complexity where they create fruit before they can be considered food plants
plants which contain sufficient nutrients to be worthwhile as food must get nutrients from the soil

Obviously this list is simplified to meet the needs of the game. I am sure any botanists reading this are shaking their heads.

Anyway, I consider it a good start. More updates to follow.

## 4e7-ish, or UFEC!

Wow, has it been a long time since I posted here.

The Unofficial Four Elements Contest ("UFEC") brought me out of hibernation, and has inspired me to put together a casual game.

Here are the specs, thus far:

Title: Thaw
Platforms: PC/Mac/Linux
Requirements: Flash Player 10, for web release version.
Genre: Simulation/Strategy
Type: 2d/top down
Players: 1

Story (at the moment):
You have been awakened from cryo after a cold snap which left the planet encased in ice for a great many years. Using what is left of your technology, you need to start seeding the planet with the basic necessities to re-start the global ecology, starting with the simplest of plants and working up to a self-sustaining biosphere which can support humans. Along the way you need to establish local ecologies which can flourish in a post ice age/apocalypse environment. This includes specifics like creating energy sources, melting through the ice, discovering caches of seeds and DNA remnants, engineering new species for the new climate, and finding out why things ar eso much worse than the Powers That Be expected them to be when they put you in the freezer.

I am still working out the fine points of this. I want it to be story driven as much as it is even driven, with the plot unfolding as the player makes decisions and begins to alter the environment. It might be much too big a game for a five month contest, but with appropriate use of procedurally- and user- generated content, I should be able to get something done.

This will be the third Four Elements competition for which I have started a game. I will be taking ideas from those projects, plus myriad code snippets from several years of experiments and projects, and see if I can get something together by the end of March which people will want to play.

My first step - and the only one, so far - is to set up a structure which keeps the event listeners to an absolute minimum, so I can eliminate the possibility of conflicts before the first screen is created. To that end, I have created two simple delegation methods - one which listens for timer updates and the other which listens for keyboard input. These functions receive the events, figure out the current state of the game, and forward the event to the appropriate manager. Code is here:

private function mainLoop(e:TimerEvent):void {
switch(GAME_STATE) {
case "travel":
worldManager.update();
break;
case "manage":
technologyManager.update();
break;
case "fight":
combatManager.update();
break;
case "dialogue":
storyManager.update();
break;
default:
break;
}
e.updateAfterEvent();
}

private function onKeyEvent(e:KeyboardEvent):void {
switch(GAME_STATE) {
case "travel":
break;
case "manage":
break;
case "fight":
break;
case "dialogue":
break;
default:
break;
}
}

With that simple structure in place, I don't have to worry about different parts of the game falling out of synch, or constantly turning listeners on and off in different parts of the game, depending on what the user is doing at any given moment. It is easy to expand this system as the game becomes more complex, and debugging is greatly simplified. Also, it requires a lot less code.

One caveat: I have not actually built a system like this before, so I don't know if there are any hidden traps in this approach. Time will tell.

I occasionally post screen shots in the UFEC screenshot thread, and will post updates to the progress of the game itself in its own thread. More development-specific updates will be posted here.

Well, heck. I will probably just post everything here.

## Diving Back Into This Stuff

After some self-enforced exile from the game dev world, I am diving back in. After some extremely helpful feedback over at the Kongregate community I am working on TriGaVoid 1.5, which will be more of a professional effort and include things like achievements, power-ups, and lots and lots of optimizations. I plan to post regular updates, code snippets, and links to the prototype as I make progress. We will see.

I haven't been completely lazy during the past two months; I made a generative art toy which feels to me like the seed for a much larger, more involved project. If my job goes away, as so many seem to be doing these days, I might even have time to work on it.

Quick note: I just uploaded a new tutorial to Kongregate. This one explains - with code - the formulae I used to build the Bad Guys in my game TriGaVoid.

The code I used is actually about seven years old. Back when I was first learning javascript and "Dynamic" HTML, I tried to reproduce some of the experiments from Assembler.org, which lead me to the Famous Curves Index. After a quick couple of weeks of teaching myself basic trigonometry, I had the first few up and running in a thing I called the Trigonometron. Once I started learning Actionscript, back in 2002, I quickly ported everything over to Flash, and spent from then to now looking for something to do with the code. So here it is.

All of the code is Actionscript 3, which should make it easily portable to pretty much any other language. At least, all of the actual movement algorithms should work - with syntax tweaking - in any language which supports math.

Enjoy!

## Perlin Textures in Flash Tutorial

While I am on a roll I will post a link to my first published Flash tutorial: Creating Textures using Perlin Noise and the Threshold Function in Actionscript.

Though it is in Actionscript, the ideas presented should carry over easily enough to any language. Enjoy!

## I Launched a Game!

Hello, everyone. Long time no see! Suffice to say, the final quarter of 2008 treated me very poorly in all aspects of my life.

But that is not important now: I am here to announce the launch of my first game over at Kongregate: TriGaVoid! I used many of the lessons I learned here about simple/casual game design, spent some free time over the holidays coding, and voila! Something I can be proud of.

I hope you all enjoy.

Source code here.

It took a little longer than I thought, and I am not entirely sure what specific thing I did which made things work right, but things are working right.

Now that I have the last graphic treatment in place I am going to take a few days away from this project and work on a couple of simple game ideas which came up when I was playing with the earlier Perlin Noise experiments.

## Perlin Ants

I took a short break from working on the game engine to play around with a mash-up of Perlin Noise-based landscapes, and Langton's Ants.

In other news, I figured out how to apply simple shading to the landscape in the tile game, and I should be able to post something sometime this weekend.

## Tile Game Engine Update: Where Am I?

This latest update includes an event which fires every time the player moves to a new tile on the world map. Right now it returns the x and y coordinates and the elevation (based on color) of the current tile. Using that information, I will be able to set up a random-ish encounters table which takes into account environment (e.g. elevation), and factors such as distance from civilization, latitude, and the like. But for right now the deciding factor will be elevation. The system will work something like this: Each creature in the creature library has, as two of its attributes, a minimum elevation and a maximum elevation. This ensures that critters will not appear in inappropriate places - nobody wants to fight a squid on top of a mountain. It just isn't done.

This is pulled from the design document:

name="Goblin"
id="goblin"
frequency=".05"
min_encounter_time=""
max_encounter_time=""
min_encounter_date=""
max_encounter_date=""
min_terrain=""
max_terrain=""
drops="a,b,c"
base_experience="10"
base_damage="1"
/>

There are attributes for time and date, which I am not currently using. If the particular game whcih I build with this engine requires it I can add times of the day and seasons, and adjust encounters accordingly. This will make things more complicated however; right now I am looking at a single variable - elevation - to sort out the encounter. Each additional factor doubles the amount of data to sort through before the fighting begins - Day or night? Spring or winter? Close to a city? In water or on land? Full moon? You get the idea.

In my 4E5 project (unfinished) I played around with having "sources" for different raw materials - salt, iron, wheat, and the like - the distance from which determined the likelihood of coming across a random deposit, and also helped set the buy/sell cost of the material while trading. This could also be determined by elevation, if I really want to go to town on the granularity of the game.

## Another Week, Another Experiment

Click here to see the live version. (When will we be able to embed Flash movies in our posts?!?)

This is a quick update to the tile-based game engine experiments of months past. This update includes the procedural generation of individual tile textures. Each texture is the same, but I have colored them to reflect the colors of each pixel in the world view. After the initial tile is created, I clone it 256 times - one for each color in the color map - and overlay the Perlin noise with the solid color. Voila! 256 colored tiles.

All in all, I would call it a great success. The next step will be to modify the way I color the tiles in order to make them more vibrant. I am sure there is a way of doing so which will not be too processor intensive.

Right now, I think it looks just a bit like Ultima IV.

## Gyruss Clone - Against the Horde

I have just updated the Gyruss clone to make it run more consistently across a wide variety of browser/platform combinations, and also to allow for more intense action if need be. I used this technique from 8-Bit Rocket, and in my linked prototype the game runs at a consistent ~30 frames per second. If you let it run for a minute, eventually there will be 100 enemies swirling around shooting at you. One caveat: I tried playing this on an old POS Mac OSX laptop, and it crashed the browser so severely that I had to give it the 3-finger salute to the the OS back.

I took a couple of weeks off of thinking about this thing to do some playing with various cellular automata experiments. The links to these are below:

Langtons's Ant
Langtons's Ant Hexagon pattern
Langtons's Ant 3d pattern
Random 2d cellular automata

Enjoy!

## Weekly Gyruss Clone Update

Another week gone by, and a few updates have been made. Nothing too earth-shaking this time, just a graphic update: A rotating background. This was entirely too difficult to implement, or I was vastly over-thinking the problem. Probably the latter.

Because I am blitting several bitmaps together to draw the screen I needed to come up with a method to get the bitmap which comprises the background to rotate. In this instance, a simple background.rotation++ wouldn't work; I needed to do a little matrix math to rotate the actual bitmap data, rather than the bitmap which contained the bitmap data. And that caused its own issues; namely, that the original bitmap - which was simply a square with some Perlin noise applied - had subsequently been redrawn around polar coordinates, and then twisted, and expanded so that the resulting circle was as large as the diagonal of the original square, rather than the sides. And somewhere in there the origin point for the bitmap data became, well... not the center of the circle.

Obviously, I eventually got everything figured out.

But not before dealing with a couple of hours of this:

## More Spiral-ey Things

I just posted an update to the Gyruss clone. It includes one cosmetic change - the color palette of the background - and some experiments around how power-ups will work.

On the inside, I change how the shots move, to give them the ability to track around the center when fired at an angle. This also opened the possibility that enemies will be able to do the same thing.

I also spent a little while creating new graphics for the player ship, but almost immediately gave up in frustration, for two reasons: I am not a skilled artist, and I don't yet know what I want the overall theme of the game to be. And I felt depressed that it took me an hour and a half to come up with a BAD 48px x 24px sprite.

I have not yet done much work with optimizing the performance of the game. I will probably do something like this technique from 8-bit Rocket. Or even exactly like that. I just know that, when there are a couple of hundred shots floating around, things start to look kind of choppy.

There are a few more things I am going to work on before I add sound and significant graphics improvements:

- power-ups
- different enemy power, toughness, formation
- bosses
- indestructible objects
- start- and end- game screens
- etc...

Huh. Creating a simple game takes a long time at an hour of development time a week.

:

## An Iteration, A Combination

(click the image to play).

I suppose it was inevitable, but I combined the bitmap navigator functionality from the earlier experiments with the maze generator from a few days ago, and now I have an infinite variety of mazes which can be flown over. I haven't implemented wall/collision detection yet, but I should have it completed fairly soon. It won't be difficult; a simple color sniffer will give me pixel-level control over what is hitting what.

I also figured out how to add seeds to the maze generator, so now I can have the same mazes for everyone who plays, or each game session will now be able to be saved, without loading the game and discovering yourself in a new maze.

The code for the maze generator class is here:

/*
* For the benefit of novice programmers, I've listed
* the various bitmasks used to the best of my ability
* (I don't use Java, I'm assuming it uses standard coordinates where 0,0 is the top left)
* I've commented on the drawing code as well
*
* 1: Wall above
* 2: Wall below
* 4: Wall left
* 8: Wall right
* 16: queued to be added
* 32: "in" the maze
*
* - quin/10-24-06
* - translated to Actionscript 3 by John Winkelman, 2008.08.25
*/
package {
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;

public class MazeConstructor {
private var mazeBitmapData:BitmapData;
private var cellsX:Number;
private var cellsY:Number;
private var cellWidth:Number;
private var cellHeight:Number;
private var isRandom:Boolean = false;
private var seed:Number;
private var wallThickness:Number;
private var hasExits:Boolean;

private var maze:Array;
private var mx:Number = 0;
private var my:Number = 0;
private var nextCell:Number = 0;
private var d:Number = 0;
private var dx:Array = [ 0, 0, -1, 1 ];
private var dy:Array = [ -1, 1, 0, 0 ];
private var todo:Array = [];
private var todonum:Number = 0;

public function MazeConstructor() {}
public function initMaze($mazeBitmapData:BitmapData,$cellsX:Number,$cellsY:Number,$cellWidth:Number,$cellHeight:Number,$wallThickness:Number=1,$seed:Number=0,$hasExits:Boolean=false):void {
mazeBitmapData = $mazeBitmapData; cellsX =$cellsX;
cellsY = $cellsY; cellWidth =$cellWidth;
cellHeight = $cellHeight; wallThickness =$wallThickness;
seed = $seed; hasExits =$hasExits;
if(seed==0) isRandom = true;
createMaze();
}
private function createMaze():void {
mx = 0;
my = 0;
nextCell = 0;
d = 0;
dx = [ 0, 0, -1, 1 ];
dy = [ -1, 1, 0, 0 ];
todo = [];
todonum = 0;

/* We want to create a maze on a grid. */
maze = [];

for(mx = 0; mx maze[mx] = [];
for(my = 0; my if(mx == 0 || mx == cellsX-1 || my == 0 || my == cellsY-1) {
maze[mx][my] = 32;
} else {
maze[mx][my] = 63;
}
}
}

/* RANDOM CHECK */
if(isRandom==true) { // start at a random cell
mx = (Math.floor(Math.random() * (cellsX-2)))+1;
my = (Math.floor(Math.random() * (cellsY-2)))+1;
} else { // start at the center-most cell
mx = Math.floor(cellsX/2);
my = Math.floor(cellsY/2);
}
/* RANDOM CHECK */

/* Mark this square as connected to the maze. */
maze[mx][my] &= ~48;

/* Remember the surrounding squares, as we will */
for(d = 0; d 4; d++) {
if((maze[mx + dx[d]][my + dy[d]] & 16) != 0) {
todo[todonum++] = ((mx + dx[d]) 16) | (my + dy[d]);
maze[mx + dx[d]][my + dy[d]] &= ~16;
}
}

// We won't be finished until all is connected.
while(todonum > 0) {// We select one of the squares next to the completed parts of the maze.

/* RANDOM CHECK */
if(isRandom==true) {
nextCell = (Math.floor(Math.random() * todonum));
} else {
seed++;
nextCell = seed % todonum;
}
/* RANDOM CHECK */

mx = todo[nextCell] >> 16; // the top 2 bytes of the data
my = todo[nextCell] & 65535; // the bottom 2 bytes of the data
// We will connect it, so remove it from the queue.
todo[nextCell] = todo[--todonum];
// Select a direction, which leads to the maze.
do{
/* RANDOM CHECK */
if(isRandom==true) {
d = Math.floor(Math.random()*4);
} else {
seed++;
d = seed%4;
}
/* RANDOM CHECK */
} while((maze[mx + dx[d]][my + dy[d]] & 32) != 0);

// Connect this square to the maze.
maze[mx][my] &= ~((1 32);
maze[mx + dx[d]][my + dy[d]] &= ~(1 1));

// Remember the surrounding squares, which aren't
for(d = 0; d 4; d++) {
if((maze[mx + dx[d]][my + dy[d]] & 16) != 0) {
// connected to the maze, and aren't yet queued to be.
todo[todonum++] = ((mx + dx[d]) 16) | (my + dy[d]);
maze[mx + dx[d]][my + dy[d]] &= ~16;
}
}
// Repeat until finished.
}

/* One may want to add an entrance and exit. */
if(hasExits==true) {
maze[1][1] &= ~1;
maze[cellsX-2][cellsY-2] &= ~2;
}

renderMaze();
}

private function renderMaze():void {
var i:int;
var j:int;

for(i = 1; i 1; i++) {
for(j = 1; j 1; j++) {
if((maze[j] & 1) != 0) {/* This cell has a top wall */
mazeBitmapData.fillRect (new Rectangle(i * cellWidth, j * cellHeight, cellWidth+wallThickness, wallThickness),0xff000000);
}
if((maze[j] & 2) != 0) {/* This cell has a bottom wall */
mazeBitmapData.fillRect(new Rectangle(i * cellWidth, j * cellHeight + cellHeight, cellWidth+wallThickness, wallThickness),0xff000000);
}
if((maze[j] & 4) != 0) {/* This cell has a left wall */
mazeBitmapData.fillRect(new Rectangle(i * cellWidth, j * cellHeight, wallThickness, cellHeight+wallThickness),0xff000000);
}
if((maze[j] & 8) != 0) {/* This cell has a right wall */
mazeBitmapData.fillRect(new Rectangle(i * cellWidth+cellWidth, j * cellHeight, wallThickness, cellHeight+wallThickness),0xff000000);
}
}
}
}
}
}

Looking at this, it occurred to me that it wouldn't be too difficult to modify this so that it can draw hex mazes. Really, it is just two more walls, and modify the positioning of the cells. The bitwise/boolean operators will work just as well, I think. But this is a project for when the weather is ugly, and the girlfriend is out of town.

Also: I discovered a port of Telengard (Windows) which has had me in a big ol' nostalgia kick for the past several days. It holds up surprisingly well for a game I first played on my Commodore 64, back in 1984.

## Passages, All Alike

(click the screen-shot play)

In my research into procedurally/randomly/runtime generating assets for Flash, I discovered the vast world of maze generator algorithms. And lo and behold, the Wikipedia had some example code, written in Java. It took me about three hours to translate it into Actionscript 3; a good chunk of that time was spent trying to figure out whether the Java random() call was equivalent to Math.ceil(Math.random()), Math.round(Math.random()), or Math.floor(Math.random()). Now things are running smoothly. Since I have this licked, pretty much, there are a couple of things I can do with the code:

1. make the maze generation seeded instead of random, so I can get repeatable mazes. Already took a stab at this and crashed my browser several times. Once this is solved, Telengard, here I come!

2. add collision detection so I can make any number of variations on maze games, from Berzerk to the most aggravatingly complex of dungeon crawls.

Oh: And here is the new AS3 class.

/*
* For the benefit of novice programmers, I've listed
* the various bitmasks used to the best of my ability
* (I don't use Java, I'm assuming it uses standard coordinates where 0,0 is the top left)
* I've commented on the drawing code as well
*
* 1: Wall above
* 2: Wall below
* 4: Wall left
* 8: Wall right
* 16: queued to be added
* 32: "in" the maze
*
* - quin/10-24-06
*/
package {
import flash.display.*;
import flash.geom.*;
import flash.events.*;
[SWF(backgroundColor="0xffffff",width="400",height="400",frameRate="10")]

public class Maze extends Sprite {
private var maze:Array;
private var mazeBitmapData:BitmapData;
private var mazeBitmap:Bitmap;
private var cellsX:Number = 50
private var cellsY:Number = 50;
private var cellWidth:Number = 8;
private var cellHeight:Number = 8;
private var debugPane:TextField;
public function Maze() {
}
private function init(e:Event):void {
if(!stage) return;
removeEventListener(Event.ENTER_FRAME,init);
var mx:Number = 0;
var my:Number = 0;
var n:Number = 0;
var d:Number = 0;
var dx:Array = [ 0, 0, -1, 1 ];
var dy:Array = [ -1, 1, 0, 0 ];
var todo:Array = [];
var todonum:Number = 0;

/* We want to create a maze on a grid. */
maze = [];

for(mx = 0; mx maze[mx] = [];
for(my = 0; my if(mx == 0 || mx == cellsX-1 || my == 0 || my == cellsY-1) {
maze[mx][my] = 32;
} else {
maze[mx][my] = 63;
}
}
}
mx = (Math.floor(Math.random() * (cellsX-2)))+1;
my = (Math.floor(Math.random() * (cellsY-2)))+1;

/* Mark this square as connected to the maze. */
maze[mx][my] &= ~48;

/* Remember the surrounding squares, as we will */
for(d = 0; d 4; d++) {
if((maze[mx + dx[d]][my + dy[d]] & 16) != 0) {
todo[todonum++] = ((mx + dx[d]) 16) | (my + dy[d]);
maze[mx + dx[d]][my + dy[d]] &= ~16;
}
}

// We won't be finished until all is connected.
while(todonum > 0) {
// We select one of the squares next to the maze.
n = (Math.floor(Math.random() * todonum));
mx = todo[n] >> 16; // the top 2 bytes of the data
my = todo[n] & 65535; // the bottom 2 bytes of the data
// We will connect it, so remove it from the queue.
todo[n] = todo[--todonum];
// Select a direction, which leads to the maze.
do{
d = Math.floor(Math.random() * 4);
} while((maze[mx + dx[d]][my + dy[d]] & 32) != 0);

// Connect this square to the maze.
maze[mx][my] &= ~((1 32);
maze[mx + dx[d]][my + dy[d]] &= ~(1 1));
// Remember the surrounding squares, which aren't
for(d = 0; d 4; d++) {
if((maze[mx + dx[d]][my + dy[d]] & 16) != 0) {
// connected to the maze, and aren't yet queued to be.
todo[todonum++] = ((mx + dx[d]) 16) | (my + dy[d]);
maze[mx + dx[d]][my + dy[d]] &= ~16;
}
}
// Repeat until finished.
}

/* One may want to add an entrance and exit. */
//maze[1][1] &= ~1;
//maze[cellsX-2][cellsY-2] &= ~2;

mazeBitmapData = new BitmapData(400,400);
paint(mazeBitmapData);
}

public function paint(g:BitmapData):void {
var mx:int;
var my:int;

for(mx = 1; mx 1; mx++) {
for(my = 1; my 1; my++) {
if((maze[mx][my] & 1) != 0) {/* This cell has a top wall */
g.fillRect (new Rectangle(mx * cellWidth, my * cellHeight, cellWidth+1, 1),0xff000000);
}
if((maze[mx][my] & 2) != 0) {/* This cell has a bottom wall */
g.fillRect(new Rectangle(mx * cellWidth, my * cellHeight + cellHeight, cellWidth+1, 1),0xff000000);
}
if((maze[mx][my] & 4) != 0) {/* This cell has a left wall */
g.fillRect(new Rectangle(mx * cellWidth, my * cellHeight, 1, cellHeight+1),0xff000000);
}
if((maze[mx][my] & 8) != 0) {/* This cell has a right wall */
g.fillRect(new Rectangle(mx * cellWidth+cellWidth, my * cellHeight, 1, cellHeight+1),0xff000000);
}
}
}
mazeBitmap = new Bitmap(mazeBitmapData);
}
}
}

## The Work Proceedeth Apace

(click the image to play)

Encouraging improvements! I debugged a couple of things, removed a lot of extraneous code, and added the beginnings of keeping score.

I think I will go for an underwater theme for this game - more of a vortex than a space warp feel. I see much work learning how to make pixel graphics in my near future.

## From one project to another

My work on the tile games led me to do some experimenting, and now I have the background for my Gyruss Clone. Click the image to see it in action

I was playing around with the Perlin Noise generation functionality in Flash, and co-incidentally came across a polar distortion class at BIT-101. I took it, played with it a bit, and figured out how to go from Polar Distortion to Twirl, with the addition of one very short line of code. Voila! I had the thing you see above. The addition of a simple gradient provides the depth.

## Tile Game Engine, Iteration III: Color Substitutio

Click the image to see it in action.

So: What is going on here? To create the terrain, I am doing the following:

- using Perlin Noise to create a grayscale terrain map, 150px by 150px.
- using the Gradient tool in Flash to create a palette map, 256px by 1px
- going through the terrain map, one color at a time - 0x000000, 0x010101, 0x020202 ... 0xffffff - and swapping out each of the 256 grayscale colors with a color from the palette map

Voila! a groovy world map which looks like a lava lamp!

"Yes," you say, "but what is it good for?"

I'm glad you asked! Right now, other than looking interesting, not much. But I will soon restrict the palette to, say, 16 colors, and each color will then be mapped to a specific bitmap tile, which will then be drawn onto the zoomed-in map, where right now each tile is a solid color. And once I have the palette restricted I can do color-based collision detection, to allow for variable movement across different types of terrain.

On a side note, while I was getting this iteration up and running, I accidentally created something I have been calling, for lack of a better phrase, an Agate generator. Here are some screenshots:

I can see this turning into a separate Generative Art project.

## Tile Engine, part II

I have just posted the second iteration of my tile engine experiment. Click the image to see it in action.

I kind of like where this is headed; the "world" bitmap is 150px x 150px. Each tile in the local bitmap is 40px x 40px. Since the player moves within the local area, but by pixels, that means the player has a world which is 6000px square. That is a pretty decent sized world to play around in during a casual game. It would be easy enough to make the world larger, simply by increasing the size of the world, or the size of the individual tiles. A world 100,000px2 is not at all out of the question.

The next step will be swapping out specific colors within the map for different tiles. One color means, say, bare ground. Another color means grass. Another means water. And so on.

## Trying again, again

In the absence of a game contest to enter and not complete, I am working on a tile engine in AS3, which hopefully can serve as the base for any games I actually get into creating, and thus saving me the effort of having to build a game engine in addition to building a game. The first iteration can be found here.

Now, off to a cabin in the woods which comes with a complete lack of the rest of the human race, which I am in dire need of at the moment.

## Laters Build

The latest build of the game is here. Click here to open the game in your browser.

The pixellated, blobby thing in the middle of the screen is the intersection of two Perlin bitmaps.

One contains information for the amount of salt available on a given chunk of land. The brighter the pixel, the more salt can be harvested from that coordinate.

The other is a height-map of sorts. When I generate this bitmap, I perform a threshold operation to see if a given supply of salt is "exposed", e.g. the salt can be harvested without any intermediary steps being performed. Each black square represents an area where the salt is underground, and must be exposed before it can be harvested. This is where the alchemist NPC (creator of explosions) comes in. In order for the miners to be able to get the salt the alchemist must come in and blow a big hole in the ground.

Once all the salt in an area is harvested that area can be used for farming.

Farming can only happen on a black square. That square can either be an area that has been cleared of salt, or an area which has not yet been blown up by an alchemist.

An area which is being farmed cannot be mined for salt at any point in the future. Inevitably, squares which might be mined are lost to the needs of farming.

As the game progresses there will inevitable be a point where all of the available salt is mined, and the land is nothing but farms.

There is a trader NPC, which I am hoping to have up and running soon, which will be able to trade excess salt and food for gold, and will thus ensure the stability of the town.

Note that most of these interactions have not yet been implemented.

The data for the bitmaps is contained in the file called "config.xml", which looks like this:

A Dry Harvest
"xml/instructions.xml"/>
"images/4e6_sheet.png" info_url="xml/spritesheet.xml"/>
"xml/story.xml"/>
"xml/tech_tree.xml"/>

5

32
32
374566
2275
0x00400000
15

My studies in economics lead me to believe that a closed system will inevitably collapse. Hopefully the game will end before this happens.

## Got Me a Music

I took a little time last night to explore the world of Creative Commons music, and found the Wikimedia Commons, wherein there is much to be had.

At the moment (though I will most likely change my mind), this is the score to my game.

One small sticking point, easily overcome: Flash cannot do anything with Ogg Vorbis files, which is the format - along with MIDI - most everything is in on the Commons. This led me to discover Audacity, which, among other things, easily converts sound files between different formats.

And life goes on.

## Startup Costs

Debugging a small problem led me to have to institute a new feature.

Each round in my game, a certain number of resources are used for upkeep of the current populace of the hovel/hamlet/village. The game starts at the "end" of round 0, which means that at the end of Round 1, the upkeep costs for Round 1 are removed from inventory before the profits from Round 1 are tallied. The idea behind this is that you cannot use the profits on the same round that they are created. This means that, since there are no profits extant from round 0, at the end of round 1 the village is already in the hole, economically speaking.

Two ways out of this: Make round 1 "special" in that there are no costs for round 1, or start with a certain amount of profit already in the "bank". Well, as a programmer I hate Hate HATE exceptions to rules, so I decided to front-load the inventory. Now there are a few rounds of leeway to get the village up and running before the death toll from starvation and over-work kicks in.

In other news, I am reading a couple of books which go hand-in-hand quite well: The System of the World by Neal Stephenson, and Basic Economics by Thomas Sowell. The first is the third book in a trilogy about (among other things) the creation of the modern system of economics, and the second is an introductory economics textbook geared toward people who have no real understanding of the topic. Between the two I am learning a great deal about how value works, and I realize that even the most complex economic sim I have ever played barely scratches the surface of the real world.

I am also watching the Century of the Self, about how Freud's nephew Edward Bernays almost single-handedly turned us into a society of consumers. If I can wrap my head completely around the ideas in these three sources I will soon take over the world.

## Why, howdy, everyone!

..and boy, are my arms tired!

It seems I live in Interesting Times. The several hour a week I had hoped to devote to my 4E6 entry since the holidays seem to have dried up and blown away. Or more accurately, been crushed under a huge pile of ice and darkness. Here in West Michigan we have seen the sun five times since the beginning of the year. My good intentions fell victim to some profound seasonally-affected depression, which manifested as lethargy and ennui.

On the couple of days which were actually nice, I went outside and walked around, trying to rid myself of CRT poisoning and the perpetual fluorescent light-induced headache. If you want to drive yourself insane, be in a room with an old fluorescent light and an old CRT monitor. Notice how things look a little... strange? That is because the refresh rate of the monitor and the refresh rate of the fluorescent light differ, and the oddness is the millisecond flashes of energy going in and out of phase with each other.

Needless to say, my head has not been in a build-a-game space.

I have made progress, however, and the latest build (including code, notes graphics, compiled project, and HTML page wrapper) can be grabbed here. I occasionally throw a new build in that directory. Mostly I just zip a day's work and email it to my Gmail account, as a sort of back-up.

During my not-building-a-game time, I have been working on my Grand Rapids Crime Map and taking photos of the Grand River.

Fortunately, like Superman, exposure to the sun has revitalized me, and I am back at work on the game. Good progress is being made. I am not sure if I will have a complete version done by the end of 4E6, but I will have something at least marginally playable. Even if I don't finish, I have learned more about flash, and game design, and information systems, in the past five months than at any time before. So I have that going for me.