• entries
43
51
• views
32208

If you only read this journal, you wont be reading much at all.

## 4E6 PyGame

I've decided to try to use PyGame for my entry. I have some experience with Python and PyGame looks (and I hear is) easy to use so hopefully that will help speed up my development process.

I havent done much personal programming in a long time. Due to a number of reasons it's probably been about six months since I wrote any code for myself but inside I've been starving for a reason to code again.

Maybe 4e6 will help me out with this?

Here is my idea for a 4e6 game (I'm sort of fleshing this out as I go along):

The elements seem distinctly Old West. The basic storyline I'm planning on fleshing out is that you are an accountant at a financially-strapped, possibly not optimally managed, bank. One day the stagecoach carrying a large amount crystals from a client's account is overtaken by outlaws and the crystals stolen. Since the bank cannot afford a proper bounty-hunter to find and take back the client's crystals and since the loss of this client would mean the end of the bank, your boss assigns you the task of retrieving them. If you are successful then you get to keep your job!

The game will mostly be centered around looking for clues as to

Who stole the crystals
Where the crystals are being kept
Retrieving them from their locations

Searching for information will require the player to travel to different towns; talk to the various inhabitants; read newspapers, wanted posters, etc. Getting to different towns and hideouts will always be by pony since this is the Old West (Pony Express anyone?) and there will probably be gratuitous use of dynamite (again, Old West Bad Guys = Dynamite + Guns!). Retrieving the crystals will involve fighting or sneaking your way to the hideout and definitely defeating some sort of outlaw boss.

Here's The Catch:
I cant draw for the life of me. Not at all. Nada. My graphics skills are somewhere between nonexistent and laughable.

Here's how I'm planning on working around that:

First, I figure I can just make the game a bit comical by using stick figures. It works for Stick Soldiers, right? I can probably draw stick figures well enough to use them in a game. I can also apply this talent to draw stick homes, stick horses, sticks of dynamite, etc. This restricts the game to be a sidescroller since I cant draw stick figures from the top down.

Second, since sticks arent very colorful I need a way to mitigate that. The game is an Old West game so I figure it would be fun to make the entire thing in shades of yellow and gray - like an Old West film. Since I'm going for the film look, I might want to add some of those film artifacts (those dots and lines and such that are due to either dirt or degradation of the film itself) for fun.

Finally, another issue I had with past games that ultimately was a factor in the death of the project is sound. I need some background music for the game and some free sound effects. I've looked briefly at those Free Sound websites but have been largely disappointed at their selection. I'm hoping that since Old West is a little more attested than pirates, ninjas, and robots, that I could find some basic gunfire and explosion sound effects to suit my game. I'd also like to find some free ragtime. Even if it has the background fuzz of a poor recording - that might even work with the old film style that I'm going for.

How you can help me

Suggestions? Ideas about libraries to use (my primary language is C++)? Can you play some ragtime on the piano and would like to send me some sound files?

Help!

## Some Experimentation

Just a short bit of what I've been playing with recently.

I still work on my CMS off and on and recently I've been experimenting with REST. In my old design each module had a function called GetContent() which would be passed an array of POST variables and an array of parameters coming from the URI. The problem with this design is that I needed to do all my form processing in some large and nasty function which basically left me unsatisfied with my entire system. I also ran into some chicken-vs.-egg problems when installing modules.

This is my new system:

I've gotten rid of the GetContent() function. Instead, during installation, modules can register handlers for specific HTTP methods on given URIs. For example, my administration module registers a handler for GET on /members/*, /modules/, PUT on /widgets/, and DELETE on /members/* (among other things). GET on /members/ will get a page listing the registered members on my site. You can be more specific and GET /members/Colin%20Jeanne/ and it will get my profile. PUT on /widgets/ will change the display order of the widgets. DELETE on /members/Colin%20Jeanne/ will delete my user account.

Each URI/HTTP method pair is associated with a callback function which handles it and is passed the rest of the URI as extra parameters. For example, GET on /members/Colin%20Jeanne/ is handled by the function that handles all GETs on /members/* and "Colin Jeanne" is the parameter of the function.

I like this system by there are some kinks to work out. Firstly, I like the use of PUT and DELETE but these seem difficult to use in HTML forms - PUT especially. I would like to have the content of a PUT message be an XML fragment but HTML forms dont really allow me to specify what is sent. I could easily set it up in javascript but I'd like my site to also work for users with javascript turned off.

Hmmm... I'll definitely need to experiment more during winter break.

## 4E5

I'm going to try to create at least one game for 4E5. I think last year my project was too large artistically for my abilities and so this year I've greatly scaled back my plans for how much artwork is necessary. Hopefully this will allow me to focus on the part that I can actually do.

I have two plans and have been thinking a lot about the gameplay. One of them is a war game and the other is a game where you build up a touring company. I'll try to post about my progress although if this journal disappears for another six months dont be disappointed [grin]

## Happy Yesterday!

I almost completely forgot that yesterday was April Fools! The only reason I remembered was when I saw the Flipcode-style forums. In light of the celebration here is a very clever April Fools prank

In other news, yesterday I bought a Dell E1505 with and upgraded it to have a DVD-burner. It has more gigahertz and more RAM than the sum of all the computers I have ever owned. Yay in 3 to 5 business days!

## Another Game

I'm trying to work out the concept behind a small puzzle game. The general idea that I want to work with is this:

It's a 2D game in which the user is presented with a row of bamboo shoots of varying height. There is a panda on the bottom which can eat the shoots, one section at a time. When a section of the shoot has been eaten the shoot is reduced in height.

The thing I cant work out is where the puzzle part comes in [smile]. I know you'd have to eat the bamboo in such a way that it is configured to solve the puzzle but I'm not exactly sure what that means.

Maybe I should just go for something simpler, like that skydiving game I thought of oh so long ago and never wrote.

## Merry Christmas!

As a gift from me to you I updated a game that I originally wrote a couple of years ago. I present Herman and the Falling Rocks - now with physics!

## Hello There

I've taken quite a break from my journal and programming in general [sad]. I'm going to try to get back into the game by working on my CMS some more (I've made quite a few changes since the last time you saw it) and possibly writing a small game and submitting it as a showcase entry. Maybe some other stuff, too.

## Creating A BBCode System

I havent been coding too much lately. School just burns every desire I have to work on my own projects unfortunately. This piece of code is actually one of the last things I worked on, finishing it last month.

Creating a BBCode System In PHP
Earlier posts were about the creation of a CMS and blogging system using PHP. One of the original goals of the CMS was to output well-formed XHTML and one of the requirements for the blog was to allow user comments. Unfortunately these two ideals can come into opposition: on the one hand I want to give my visitors a way of expressing themselves in their posts by creating links, defining emphasis, etc. but on the other I need to make sure that the code that they input does not break my page's well-formedness. To rectify this problem I've decided to disable XHTML input entirely and have instead replaced it with a BBCode-like system which I have called Blog Code.

Blog Code Syntax
For the sake of familiarity I've decided that Blog Code syntax would be similar to HTML syntax. However, instead of delimiting tags with I will use [ and ] to match other BBCode systems.

Blog Code will comprise of different tags which all have zero or more attributes and some type of content. A sample tag to display an image might look like

[img alt="This is my alt text"]http://www.example.com/img.png[/img]

where 'alt' is an attribute with a value of "This is my alt text" and 'http://www.example.com/img.png' is the content of the tag.

Further, because I would like to automatically encapsulate my paragraphs in XHTML's p tag I need to define which tags can exist in a paragraph. This gives me two types of tags: inline tags, which can exist in a paragraph, and block tags, which can not exist in a paragraph.

Implementation
In order to help me manage the different types of tags that exist I've created a class, BlogCode, which will allow me to register new tags, find paragraphs, and apply all or a subset of the registered tags.

Tag Registration
When a tag is registered I simply save the name of the tag and a callback function which will handle the tag to an array within the BlogCode class.

class BlogCode {
var $taginfo = array(); // Registers a tag name with a callback to handle this tag function RegisterCode($tagname, $callback,$display = 'inline') {
// The tag name must be just alphanumeric
if (preg_match('/^\w+$/',$tagname) == false)
return false;

$this->taginfo[$tagname] = array($callback,$display);
}
}

I've restricted my tag names to be only composed of alphanumerics and before a tag can be registered its name must be validated to ensure no wacky tags make it through.

Tag Application
To actually apply the tags we must be able to search for them. I've come up with this regex to hunt down any tag

/$(\w+)( [^$]*)?\](.*)$\/\\1$/sU

This describes a tag which begins with a '[' and immediately after has one or more alphanumeric characters (the tag's name). Optionally afterward there may be a space followed by anything other than a ']' (the tag's attributes). Next there will be a ']' followed by anything and then finally ending in '[\' followed by the tag's name and ']'. The search is not greedy so it will end a tag at the first instance of its ending tag rather than the last instance of its ending tag. That is this

[em]Test test test[/em] bla bla bla test test test[/em]

Should be rendered as

Test test test bla bla bla test test test[/em]

and not as

Test test test[/em] bla bla bla test test test

In order to make a regex which will find only select tags we simply need to restrict the name of the tags. To do this I replace (\w+) with (tagname 1|tagname 2|...|).

Handling The Attributes
Notice from the above that we dont really care what is in the attributes section of each tag. However, it would be nice if we could take these attributes and convert them into a name/value pairing for easy handling. To do this we'll define a new syntax for the attributes.

Each attribute will have a name composed of only alphanumerics. The values of the attributes must all be quoted to make parsing simpler and must not contain either '"' or ']', again to make parsing simpler. This is the regex I've come up with

/(\w+)="([^"\]]+)"/

So, a valid attribute would look like

name="value"

Coding It In PHP
This is the implementation I have for tag application and attribute parsing

global $blog_code; class BlogCode { var$taginfo = array();

// Registers a tag name with a callback to handle this tag
function RegisterCode($tagname,$callback, $display = 'inline') { // The tag name must be just alphanumeric if (preg_match('/^\w+$/', $tagname) == false) return false;$this->taginfo[$tagname] = array($callback, $display); } // Apply these tags on a body of text function ApplyCodes($str) {
return preg_replace_callback("/$(\w+)( [^$]*)?\](.*)$\/\\1$/sU",
'BlogCodeCallback', $str); } // Applies only a select subset of the tags function ApplySelectCodes($str, $tags) {$namelist = array_shift($tags); foreach ($tags as $tag)$namelist .= "|$tag"; return preg_replace_callback("/$(namelist)( [^$]*)?\](.*)$\/\\1$/sU", 'BlogCodeCallback',$str);
}

// Breaks up the attribute list into an associative array where the
// attribute names are the keys and the associated values are the values
function ConvertToArray($attrs) {$attrarray = array();

preg_match_all('/(\w+)="([^"\]]+)"/', $attrs,$matches);

$keys =$matches[1];
$vals =$matches[2];

for ($i = 0;$i $attrarray[$keys[$i]] =$vals[$i]; return$attrarray;
}
}

$blog_code = new BlogCode; // Routes each match to the callback associated with it function BlogCodeCallback($matches) {
global $blog_code;$tagname = $matches[1];$attrs = $blog_code->ConvertToArray($matches[2]);
$content =$matches[3];

if (isset($blog_code->taginfo[$tagname])) {
$str = call_user_func($blog_code->taginfo[$tagname][0],$tagname,
$attrs,$content);

if ($str !== false) return$str;
}

return $matches[0]; } The new bits of code are the applicantion functions, the conversion of the attributes to an associative array, and the main tag callback. The application functions, ApplyCodes() and ApplySelectCodes() work exactly as I described above. They search for the tags or a subset of the tags within a string. When a tag is found preg_replace_callback() calls BlogCodeCallback which grabs the tagname, attributes, and content of the tag before sending those values to the callback associated with that tag. ConvertToArray() takes in an attribute string and searches for attribute/value pairs and turns them into an associative array. Finally, since BlogCode is the only entity that should manage the tags I've made a global,$blog_code, which will act as the one instance for this class. This was necessary as preg_replace_callback required that BlogCodeCallback be a non-member function.

Finding Paragraphs
By far, the most difficult part of this project was finding out where paragraphs being and end. After many different tries I came up with this:

It's easy to see paragraphs being broken up by two newlines but that cannot account for block level tags. My solution was to first split the text along block level tags and then apply the simplistic view of what separates paragraphs. Finally, I paste the different sections of text back together using the block level tags that were originally between them.

// Finds each paragraph and wraps it in tags
function BlockParagraphs($str) {$blocktags = array();

foreach ($this->taginfo as$tagname => $value) { if ($value[1] != 'inline')
array_push($blocktags,$tagname);
}

$namelist = array_shift($blocktags);

foreach ($blocktags as$blocktag)
$namelist .= "|$blocktag";

// Break up the text into array elements separated by block-level tags
$pararray = preg_split("/$(namelist)(?: [^$]*)?\].*$\/\\1$/sU",$str);

// Capture all of the block level tags (in order)
preg_match_all("/$(namelist)(?: [^$]*)?\].*$\/\\1$/sU", $str,$delims);

// Ignore the names of the tags
$delims =$delims[0];

// Wrap each paragraph in the tags with p tags
$paras = preg_replace("/(.+)(?:\n\n|\r\r|\r\n\r\n|$)/sU", "\\1 ",
$pararray); // Remove empty p tags$paras = preg_replace("/\s*/U" , '', $paras);$output = '';

// Interleave the block-level elements into the text
foreach ($paras as$para)
$output .=$para . array_shift($delims); // Put the rest of the block-level elements into the text$output .= implode('', $delims); return$output;
}

Using the above code it becomes necessary to call this member on a piece of text before applying any of the tags.

The Final Code
This is my final PHP file, with some sample tag definitions at the bottom

/************************************************************************
*
* Title: BlogCode Class
* Author: Colin Jeanne (http://colinjeanne.net)
* Date: August 23, 2005
*
* Description:
* A class that represents a BBCode-like formatter
*
************************************************************************/

global $blog_code; class BlogCode { var$taginfo = array();

// Registers a tag name with a callback to handle this tag
function RegisterCode($tagname,$callback, $display = 'inline') { // The tag name must be just alphanumeric if (preg_match('/^\w+$/', $tagname) == false) return false;$this->taginfo[$tagname] = array($callback, $display); } // Finds each paragraph and wraps it in tags function BlockParagraphs($str) {
$blocktags = array(); foreach ($this->taginfo as $tagname =>$value) {
if ($value[1] != 'inline') array_push($blocktags, $tagname); } //XXX There must be a better way to do this$namelist = array_shift($blocktags); foreach ($blocktags as $blocktag)$namelist .= "|$blocktag"; // Break up the text into array elements separated by block-level tags$pararray = preg_split("/$(namelist)(?: [^$]*)?\].*$\/\\1$/sU",
$str); // Capture all of the block level tags (in order) preg_match_all("/$(namelist)(?: [^$]*)?\].*$\/\\1$/sU",$str,
$delims); // Ignore the names of the tags$delims = $delims[0]; // Wrap each paragraph in the tags with p tags$paras = preg_replace("/(.+)(?:\n\n|\r\r|\r\n\r\n|$)/sU", "\\1 ",$pararray);

// Remove empty p tags
$paras = preg_replace("/\s*/U" , '',$paras);

$output = ''; // Interleave the block-level elements into the text foreach ($paras as $para)$output .= $para . array_shift($delims);

// Put the rest of the block-level elements into the text
$output .= implode('',$delims);

return $output; } // Apply these tags on a body of text function ApplyCodes($str) {
return preg_replace_callback("/$(\w+)( [^$]*)?\](.*)$\/\\1$/sU",
'BlogCodeCallback', $str); } // Applies only a select subset of the tags function ApplySelectCodes($str, $tags) { //XXX There must be a better way to do this$namelist = array_shift($tags); foreach ($tags as $tag)$namelist .= "|$tag"; return preg_replace_callback("/$(namelist)( [^$]*)?\](.*)$\/\\1$/sU", 'BlogCodeCallback',$str);
}

// Breaks up the attribute list into an associative array where the
// attribute names are the keys and the associated values are the values
function ConvertToArray($attrs) {$attrarray = array();

preg_match_all('/(\w+)="([^"\]]+)"/', $attrs,$matches);

$keys =$matches[1];
$vals =$matches[2];

for ($i = 0;$i $attrarray[$keys[$i]] =$vals[$i]; return$attrarray;
}
}

$blog_code = new BlogCode; // Routes each match to the callback associated with it function BlogCodeCallback($matches) {
global $blog_code;$tagname = $matches[1];$attrs = $blog_code->ConvertToArray($matches[2]);
$content =$matches[3];

if (isset($blog_code->taginfo[$tagname])) {
$str = call_user_func($blog_code->taginfo[$tagname][0],$tagname,
$attrs,$content);

if ($str !== false) return$str;
}

return $matches[0]; } function inlineCallback($tagname, $attrs,$content) {
global $blog_code; return "" .$blog_code->ApplySelectCodes($content, array('strong', 'em', 'link')) . "$tagname>";
}

$blog_code->RegisterCode('strong', 'inlineCallback');$blog_code->RegisterCode('em', 'inlineCallback');

function imgCallback($tagname,$attrs, $content) { if (isset($attrs['alt']))
return '"' . $attrs['alt'] . '" src="' .$content . '" />';
else
return "$content\" />"; }$blog_code->RegisterCode('img', 'imgCallback', 'block');

function linkCallback($tagname,$attrs, $content) { global$blog_code;

if (isset($attrs['href'])) { return '"' .$attrs['href'] . '">' .
$blog_code->ApplySelectCodes($content,
array('strong', 'em', 'img')) .
'';
} else {
return "$content\">$content";
}
}

$blog_code->RegisterCode('link', 'linkCallback'); function codeCallback($tagname, $attrs,$content) {
return 'class="blog_code">' . htmlentities($content) . ''; }$blog_code->RegisterCode('code', 'codeCallback', 'block');
?>

## Yay!

Way back in June I applied for a web designer job at UC Berkeley. After more than a month without reply I figured that they had forgotten about me [sad] But about two weeks ago I got an email acknowledging my application and asking me for an interview!

My interview was on Friday and they asked me to bring a portfolio but since I hadnt had any designer work in the past I could only show them personal websites. Oh well. I fixed up and old design to show along with my current website. I put them online and I also copied the necessary files to my trusty USB jump drive just in case.

OH GOD! The scariest thing EVAR happened during my interview! It was time for me to show them my two designs and so I navigated Safari to my site and my host was having some weird problem. I couldnt get to my site to show my stuff! OHNO OHNO OHNO!! Lucky for me I thought about that just in case kind of time and copied everything I needed to that jump drive. USB drives are my savior.

I found out today that I got the job [smile]

Yay!

## RASSEN FRASSEN! Grmblegrble

So I have this old Compaq Presario 4712 that I wanted to donate. I've tried to use it as a Linuxbox for learning but its 166MHz P1, 40MB RAM, and 2.1 GB HD were too limiting especially when I got to use an HP Pavillion 8565C for that instead. I figured I'd do a good deed and put Win95 back on the machine and donate it to someplace that wants it since it still works perfectly.

Compaq, however, has other plans.

I popped in the Quick Restore boot disk and its associated CD, went through a few "bla bla bla, all your documents will be destroyed, bla bla bla" messages until I was asked for my computer's serial number. No problem! So I type it in. Then Quick Restore scoffs, "HA! That's not a Compaq serial number! Try again you filthy pirate!" So I think, "Hmm, maybe that thing I though was a zero is actually the letter 'O'" and I try again. "HA! That's not a Compaq serial number! YOU'LL NEVER GET IN YOU FILTHY PIRATE!" So I try different combinations of the serial number with upper-case, lower-case, changing that '1' to a lower-case 'L', etc. but each time Quick Restore tells me it's invalid.

Sure enough, my Quick Restore boot disk is 242569-001. So I try the solution on the page and type in

A:\ uiabomwr 028

and the computer reboots. I get back to the serial number screen and try typing in the serial number. "HA! You thought you could beat me! WRONG AGAIN!" So I try a bunch of variations like I did before and try using the solution on the above page many times. "BWAHAHAHAHA! YUO AER TEH LOSE!!!!!!111 COMPAQ STRIKES AGAIN!"

Now I want to shoot somebody in the face. I've also decided that instead of donating this computer it's going to die a terrible death in the scrap heap.

## Humph

I've become really unmotivated recently so I think I'm going to take a break from programming. Hopefully I'll still be able to produce a 4E4 entry but I dont think it will have all the features that I've described.

## Stupid Humans!

The latest system I have is an N64 (well, if you exclude my DS) and generally I'm pretty satisfied with not having anything newer but every time I see that commercial for Destroy All Humans I cant help but want a new console so that I can play it. According to evolutional it has the voice of Zim!

*sigh*
Somebody buy me a PS2 or an XBOX! I'll be your friend forever.

## Many Yays!

Yay #1: Today was my birthday. Last year I gave all of you ASCII Pie but since I gave you ASCII Pie not too many entries ago as well I wanted to give you something cooler.

Some time ago I broke my ASCII-Art editor program which brings me to Yay #2:

Yay #2: I have a better version of my website which I invite you to use. And, if you happen to break anything I also invite you to tell me [wink]

Yay #3: I can finally say that I have developed a web application and now I can focus more of my efforts on my 4E4 project!

Yay #4: I'm making progress on my 4E4 project [grin]

Long story short: which do you prefer, a hierarchical representation of a discussion (like the comments on LiveJournal) or a single-threaded modal (like the Gamedev forums)?

Long story long:
I'm finishing up comments in the blog part of my CMS software but I'm not sure what type of thread style the comments should have. Right now I've got a hierarchical setup like flipCode's forum and LiveJournal but it's proving to be somewhat of a pain. You see, I am determined to have pretty URLs and with the hierarchical modal it is necessary to reference individual comments because comments might be nested too deep to show with proper indentation (see the LJ and flipCode links for what I mean). I dont, however, know how to uniquely ID each comment in a pretty way. These are a couple the methods I have thought of

1. By timestamp
Pros - Easy to implement
Cons - It is possible that two users could comment at the exact same time, this could be resolved by using timestamp + user ID but in either case timestamps arent very pretty and are difficult to remember.

2. By the order that the comment was post
Pros - Easy to remember
Cons - Unintuitive since comments may be posted in multiple threads in a non-linear order one thread's comments might have numbers 1, 8, 12, 13, 42. Also unless I want to add a new field to my database I'll have to calculate this on the fly.

Do either of these sound good to you? Do you have any others?

I was browsing around various blogs to see how they implemented this. What I found was that the blogs that had pretty URLs also used a single-thread modal like Gamedev's forums. This would be much easier to implement but I'm afraid that I will lose some of the structure of the dialog. What do you think?

## 4E4 Progress

To be honest I've lacked a lot of motivation to work on this project [depressed]. I usually code a little something every couple of days but there hasnt been any major progress. I think I'm at one of those "so now what do I do?" points, you know what I mean? There's a lot I know I can do but I think part of the problem is I dont know which to start on and so it makes everything else look daunting.

On the other hand, I have invented a way to keep myself at least a little on track using my LiveJournal. I'm planning on doing a weekly sort of diary for my game and next week's entry is supposed to have something to show. I'll still be using this space, however, since my LJ posts arent supposed to be too technical and I get to rant about problems here [smile]

## Do You Like Pancakes?

Yeah, I like pancakes!

## So Long MySQL

Thus far I've been using MySQL 4 for my CMS but it doesnt support sequences and I need them. Fortunately my host also supports Postgres SQL 7.4 which does have sequences. Yay!

I need sequences because I've made a change to my blog's database schema: an entry and a comment are now the same thing. Each has a unique ID and references the ID of a their parent. Top level entries are their own parents while comments may have a comment as a parent or an entry. I decided to combine the tables since they were almost the same table. The only difference was that the comment table originally had two extra fields: ParentID and ParentType. ParentType was an enum that would determin if ParentID referenced the entry table or the comment table. This sucked because I couldnt use ON DELETE CASCADE with that.

The reason I need a sequence is that in order to create a parent that references itself I need to get its ID before I insert it into the table which means I can use MySQL's ability to get the last value from AUTO_INCREMENT because it would be worthless.

Hopefully this wont be a hard change. I've abstracted the database enough that I should only have to change the class and then possibly a couple of my queries. The only ones I'm worried about are my paging queries because they use LIMIT. Of course I'll have to change my table to no longer use AUTO_INCREMENT as well.

## A Change of Plans

A long long time ago (maybe summer of 2003?) there was a lounge minicontest involving ASCII animation. I participated and began what would later become ConsoleLib: a Win32 console wrapper/utility package. The other day I wanted to update an old VB6 gravity simulator to include electromagnetism but VB.NET 2003 could not upgrade Form.Circle and I dont know how to draw circles in VB.NET so I thought, 'Hey! Let's use ConsoleLib for no other reason than because!' And so I did.

It was a very easy thing to do.

In fact, ConsoleLib can do a great many things easily especially since I wrote a number of classes to help with animations, collections of animations (ie - sprites), static objects, various text utilities, a pretty good input system, particles, etc. Hell, with it I made this:

But back to 4E4. I decided that maybe I started a little bit too fast with the artwork and that maybe I should start with simple stick figures. That worked out ok. I dont think I'll be able to progress further than that. That wouldnt be too bad because then I could change the game so that it's all being played on a piece of binder paper like Doodle Invaders. I always wanted to make one of those types of games.

However, this morning I had an even better idea - I could use stick figures... but using ConsoleLib. I already have editors to draw my animations/sprites/static objects that I know mostly work (a few small bugs), I know that the drawing and input system works perfectly, and I can mask properly utilize my complete lack of artistic skill unique artistic talents!

As an added bonus, I'll finally have a project to showcase ConsoleLib [grin]

## How Depressing

So, I tried to draw some of the graphics I'll need for my game but that just ended in disaster. I guess I'm ok at drawing things from directly above or directly across but once I try to add in a little perspective my drawing goes from bad to worse. [sad]

I think I need an artist for my game or at least some tutorials on learning how to draw on the computer. Maybe something like 'Draw Like Salsa In 3 Easy Steps!'

Actually, I probably need 'Drawing For Blind People Who Were Dropped On Their Heads As Babies'.

## 4E4

I've started working on my 4E4 game. This is the final storyline (at least this is what I plan on being the final storyline [smile])

You're a programmer who has just finished creating your very own humanoid robot. Since you've been working all day on it, you hit the hay after you put the finishing touches on it. Sortly after you slip into dreamland somebody break into your house and steal your robot waking you up in the process but too late for you to stop them! You decide to go out into the night and track down this thief but you discover a piece of your robot on your front lawn - it has been broken!

To top things off, it seems like there are an abnormal amount of zombies wandering around your city and they seem bent on preventing you from recovering your masterpiece. Fortunately for you, you are well versed in the martial arts.

That's it! Ninjas, robots, and zombies with the possibility of a few references to pirates (most likely of the software kind). There will be a number of levels in which you will need to find parts of your robot although you will not need all of the parts to complete the game (but there will be a bonus if you do manage to get all of them). There will, however, be five parts that you DO need to get in order to progress:

Robot Feet - allow you to jump very high/far
Robot Arm - to be used as a grappling hook
Robot Eyes - allow you to see things you cannot normally see (doorways, level exits, etc)
Robot Breastplate - reduces the damage done to you
Robot Skin - highly reflective!

To aquire these items you will need to
1) collect a certain number of robot parts from the levels
2) defeat a boss / solve a hard puzzle

Within the next few days I'm going to storyboard the entire city and at least a few of the levels. I'll either scan and post them or if I happen to make them using something like Paint.NET I'll just post them.

I think the hardest part about this game will be the actual artwork. I suck at drawing in real life and it's even worse on computers. [sad]

## CMS Progress

I have a basic version of the CMS up. If you decide to play with something and find out a way to break it please email me.

I'm also going to start using Smarty since I found out my host has it. This will allow me to remove the ugly HTML that currently lives in the PHP files and place it elsewhere. This will also motivate me to improve the existing user interface a lot!

Finally, I'm playing with an idea for the CMS - I would like to give each module the ability to provide widgets to go in the main menu of the site. This would be for things like the little registration box (which is hacked into the main template right now) or perhaps a list of categories for the blog, etc. The administrator would be able to select which widgets are shown and the modules will just have to provide a list of widgets they implement.

I might put that off for a bit since I also really need to make some progress on my 4E4 entry.

## 4E4!

I have a storyline now. The game will be about a programmer who has been taught in the martial arts who will be searching his city for the parts of his stolen robot. The city will be infested with zombies because, well, what else are you going to fight? Pirates? Let's be realistic here, pirates dont attack people in urban settings at night.

The interface of the game will be set up like in Mario 3 or in Super Mario World where you have a top-down view of the world when you choose levels and a side view when you actually play the levels.

## First Blog Milestone

At this point I can administer the categories, owners, and entries of the blog. Privacy levels seem to work right now (although I did squash a few bugs where they wouldnt take effect). InnoDB is a lifesaver with its foreign keys and cascading deletion! I havent yet implemented the comments because right now I think there is more of a need for testing.

I'm also planning on implementing a more sophisticated template system so that I dont have all these ugly print statements to output my HTML.

## Blog Progress

It looks like the administration of the blog is nearly complete. I just need to add in the creation/modification/deletion of entries and I should be done with that. Hopefully that will happen tonight.

Next I have to write the part that generates content for normal uses, that is the area to add/modify/delete comments, browse for past entries, etc. That shouldnt take more than a few days.

The more I code this the more areas I realize I could restructure it to be a little bit better. When I release this I think I'm going to make it only a preliminary milestone - I want version 1.0 to be something that I think other people might actually consider using (it's no where near that state right now). Hopefully as I move towards that point my host will also upgrade to PHP 5 which will allow me to rewrite the code a little bit.