Wednesday, August 26, 2009

Decimal or Integer to Binary / AS3 Code

I had a need for this routine in Protonaut, and Ryan Madsen was gracious enough to pseudo-code this up for me. I then converted it to proper AS3 and to suit protonaut's needs.

It's modifiable easily enough, but here's the basic premise:

Input a decimal (say, the number 1) and request an array length in return (default 6 bits).

It will convert the decimal to binary, and store each bit into an array in reverse order for easy flag operation. Our example of 1 would then return [1,0,0,0,0,0].
  private function dec2bin(dec:uint, digits:Number=6):Array {
var result:Array = new Array();
for (var i:Number = 0; i <= digits-1; i++) result[i] = 0; for (var i:Number=digits-1; i >= 0; i--) {
if ((dec - Math.pow(2,i)) >= 0) {
result[i] = 1;
dec -= Math.pow(2,i);
}
}
return result; // results are in reverse order... 1 == 1,0,0,0,0,0
}

I used this code for retrieving a single ascii charcode to store the combinations of the various 6 keys you can press in the game. I googled around and couldn't find anything, so hopefully this will help someone else.

This is easily converted to outputing the Binary to String format, or reversing the Array, if you so need.

Working out Replays

My current project, Protonaut, somewhat recently got a "Replay" feature. You can save your victories and share them with your friends! But how to execute the replay feature is really tricky, especially when you only have finite space and bandwidth to dish them out with.

Protonaut uses a level editor and a collection of Box2D parts - somewhat similar to Fantastic Contraption. Replays in FC are called designs, and all it is is a snapshot of the starting conditions. Since there is now way to interact with FC mid-design, you can safely let the simulation "play out" on your computer, and it will turn out the same. It's as if the fate of your contraption has been pre-determined.

I'm not able to do this obviously. You control the player character throughout, and you can change your mind halfway through playing a level - what with having a brain and free will and all.

After looking at a few options (taking a snapshot of all the objects in the level and tweening them for example), I decided to go with recording keypresses. While a replay is running, it's as if one of those automatic-piano-playing-rollers is over your keyboard. The game otherwise thinks it's you controlling it yourself!

Building the data structure was simple at first. I just wanted to get it done, and I wasn't thinking about storage requirements. Here's an example clip of the replay file:
[...] ,,1,1,0,0,0,0,0,0,,2,2,0,0,0,-1,10,0,,3,3,0,0,0,23,0,0 [...]

I used comma deliminators and the data is broken down as:

,,Array Index, Tick#, jumpstate, firestate, (other keys)...

Keystates could be At Rest (0), Just Released (-1), or Held Down (length).
There was several problems with this setup, mostly structural, but all my fault. It was possible to hold down, say, the fire button for millions of ticks - throwing huge numbers into the mix and making it a very big and clunky bit of code. To help smooth things over, I did ZIP the file - which shrunk things down nicely.

Yesterday I decided to clean things up. I realized that "just released" and "held length" could be programatically determined; If the last frame was > 0 and this frame == 0, then it means the key was down last tick.. but not this tick. -1 for release. So it was no longer necessary to store the actual keystate, but just an up/down 0/1 representation.

That means that the keystate could be summarized in a single 6-bit number, that has 64 possible combinations. From there it was easy to find a spot on the ASCII Character table that had 64 human-readable characters in a row, and just mapped the key value to that.

Then I stripped out the commas and dropped recording of null frames (where you aren't pressing any keys). Then I dropped the array indexes, because they were completely unused. Now the replay data looks like this:
...191J192Q200p201'202'203'204'205W300L...
Quite a bit shorter! All it is is "Tick#" followed by a character that represents the keypresses.

After running this through the ZIP algorythm, total space on the database was reduced to 1/20th of it's original size (using a speedrun on Tutorial #1 as a basepoint)!! I'm so very happy with this... I'm sure my database will agree with me. And my bandwidth bill.

Special thanks go out to Aubrey for helping me out with BitShifting and Ryan for writing me out a psuedocode Binary-to-String function.

Saturday, August 22, 2009

FlexSDK 3.3 How To Make a Flash PreLoader in AS3

One of the things that has been vexing me lately is trying to get a Flash PreLoader working for my games. I've tried Googling it, but there are too many like-terms: Flex Builder, FlashBuilder, Flex, CS3, CS4... The all have different methods, and my method is the least googleable: Flex 3.3 SDK, AS3 only.

I don't want others to run into the same problem, so here's a tutorial on how to make a flash preloader for AS3 with nothing more than notepad.

STEP 1: Why a preloader?

The first thing you have to do is arm yourself with knowledge. Why do you need a preloader?

As you may or may not know, every single SWF file is a movie. Even if it's a simple Hello World application, it is a movie with a single frame. It's hard to remember this sometimes, because working in the AS3 environment we don't have easy access to the stage's timeline, and everything we do happens on the first frame. Here's the key to remember, though: The entire current frame must be loaded before the frame starts to play. Most AS3 applications are built on a single frame (#1), which means your entire SWF must be downloaded, and loaded to memory, to display anything.

"But SWFs aren't all that big," you say. "Why would I need a preloader for that?"

The average connection speed in the United States is probably way lower than you think, or what you currently have. The fact that you are reading this blog at all probably means you have a 5mbps+ broadband connection. But that's how us geeks roll, and we only ever talk to other geeks. I'm on a 10mbps line with access to 50mbps if I wanted to pay extra for it.

The US has made several headlines recently beacuse the average broadband speed in the US is 1mbps. That is 128 kilobytes per second. But did you note the italicised term there? Over 60% of the United States does not have access to Broadband, so dialup is the connection type for many people. But what does that mean in real terms?

Here at Build 35 of Protonaut, the game is sitting at just under 600Kb - not counting audio assets. On the average broadband connection, it will take around 5 seconds to load and display the game to your screen. On a standard dialup connection, it will take over a minute. Many users will leave your page if they see a blank window for more than a second or two. 5 seconds of load time is absolutely painful, and is faster than the average connection!

STEP 2: Setting Up an AS3 Preloader

Allright, now that I've convinced you to use a preloader for your FlexSDK application, let's take a look at what is required.

First, you will need a whole new class file that will be your entire preloader. Here's some sample code for what I've used, and placed inside "Preloader.as" in the root directory of my project:
package {

import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.getDefinitionByName;

[SWF(width='800', height='450', backgroundColor='#E5E5E3', frameRate='30')]

public class Preloader extends MovieClip {

public function Preloader() {
stop();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

public function onEnterFrame(event:Event):void {
if(framesLoaded == totalFrames) {
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
nextFrame();
init();
} else {
// Show your preloading graphic or animation here
}
}

private function init():void {
var mainClass:Class = Class(getDefinitionByName("Main"));
if (mainClass) {
var app:Object = new mainClass();
addChild(app as DisplayObject);
}
}
}
}
It's a very simple application. It simply adds an event listener that waits until ALL frames have loaded, and once that happens it will launch your "Main" class. At this point in the game, we still only have a single frame, so it won't do much. In this case, "Main.as" is my main class for Protonaut and also exists in the root folder of my project. You will have to edit this to match the main class name for your project - use "BobJones" if "BobJones.as" is the primary class in your project.

I've placed a comment where your preloading graphic, animation, advertisment - or heck - minigame, should reside.

If you compile and run this code alone, without following the extra steps below - the preloader will "blip by" in an instant and not show up until the whole SWF has loaded. So we aren't quite there yet, but we're prepared!

STEP 3: Reconfigure Your Compiler

Now that we have "Preloader.as" in place, we want to move the rest of your application off of Frame 1 and onto Frame 2. This will allow the preloader to show itself first, and wait on the loading of the second frame.

Here's a slice of my compiling instructions:
    "mxmlc.exe" -frame two Main -file-specs="Preloader.as"
They key statement here is "-frame two Main". This tells the compiler to move the class "Main" onto the second frame of the movie, and thus preventing it from loading before displaying the preloader.

For advanced users, note that you can specify any number of frames this way - possibly breaking up your application into several loading chunks, which can silently load in the background while people navigate your menus!

THAT'S IT!

STEP 4: Correcting for Errors

That's it, Unless of course you were referencing the Stage a whole lot in your code. Now that the concept of the "stage" resides in frame 1, the stage is outside of the scope for your "Main" class on Frame 2. Any references in your code to "stage" will now return Null, and probably cause you some headaches.

There's nothing stopping you from passing the stage to Frame 2 as a variable, though!

I dove back into Preloader.as and changed:
    var app:Object = new mainClass();
To:
    var app:Object = new mainClass(this);
Then, in Main.as's constsructor, I had it accept this as a variable and stored it for later reference. Couldn't be simpler!

STEP 5: Basking in your Glory

Now it's about time to crack open that beer because you're done. If you had any questions, or if this helped you at all, please leave a comment! I'll try to update this with any answers to questions people have.

Friday, August 21, 2009

The Pressure to Release on-Time

I am starting to wonder if I can get Protonaut out the door on time.

Greg and I set a goal to have the game in releasable form by September 14th - the date I'll be flying down to GDC Austin. I figured this was a good a date as any - might as well have your game done before going to a game conference. As of this posting, there is just about 3 weeks left. It seemed far enough away, at the time - and our progress on the game appears to be maintaining a steady pace. But then real life steps in.

I could start with the small complaints - tonight's programming timeslot was instead wasted fighting the first-ever porn-spammer on the Fantastic Contraption forums. I am still very proud of how the community held together and stayed sane for over a year before this happened, and I'm pretty sure this will blow over as well - but due to some technical difficulties my entire night was consumed.

I have bigger fish to fry than a single night, though. Some old chums I used to work with have roped me into covering some shifts at their new office next week. Sure, it's part time; I can work most (if not all) of it from home; and the workload is likely light. But it'll harm my train of thought fairly hardcore, and code will progress at a halting pace at best.

Then there is the last-minute ticket purchase for PAX. I've never been to the Penny Arcade Expo, but I hear it is a blast - and that's going to consume a hearty 4-day weekend, plus some recovery time.

Then there is the Great Canadian Beer Festival, for which I am not only attending both days - but am also volunteering for, doing the volunteer orientation, and doing the afterparty. The recovery time for this is going to be even longer.

Let's not forget that Colin Northway, old chum of mine and writer of Fantastic Contraption, is in town and we will likely hang out at least a tiny bit.

That isn't to mention my regular routines (Aikido, getting exercise on my bike, chores, harvest season in the garden, etc.) that pretty much slims my remaining working time down to just about 7 days worth of solid effort. It's suddenly gotten dark in here, what with all the foreboding-ness. I'm officially daunted.

It's not all doom-and-gloom, though. We've hit Build 35 in Protonaut now, which sports the first incarnation of music and sound effects, not to mention a few key tweaks and the usual barrage of new menu interfaces - which has really got me excited. For the first time, Protonaut feels like an unfinished game instead of a collection of parts that might amount to something someday. Roger Levy is now on board with Greg and I to do our music, and he produced a great 8-bit Russian folk-tune to fit the Red-theme of the game today. It reminds me of Monkey Island music, it's really sweet.

For more external influences, Greg posted to his blog about the success of his latest game, Fig. 8, and how the bidding war went down. It's a very interesting timeline and I think it does a good job at representing the value behind proper marketing, and putting your game in the correct (bidding) spotlight. Congrats to Greg & the others at Intuition. It's very motivating reading about other's success.

I suppose I just have to keep my chin high and my nose down to the grindstone. I guess I'll be coding inverted.

Monday, August 17, 2009

Build 33: Protonaut Gameplay Finalized

We hit a milestone this weekend, and it feels really nice. The gameplay is finalized.

That's not to say that the entire game is finalized - oh no. Still lots of work to do. But in terms of actual gameplay elements - how the character moves, how elements work, how levels are designed - that's all finalized. If you were to make a level in the game today, it would still work upon release.

This is very good news, as it means I can now start building levels for this beast.

We're up to Build 33 - check it out at www.protonaut.net .

Monday, August 10, 2009

Build 30: Epic Changes

It's finally here!

I'm sorry it took so long to get Build 30 out, but I really had no choice. Exactly two weeks ago I put out Build 29, and things started changing so much that the game was relatively unplayable until just recently. I put in a final few touches tonight and I am left with a product I am happy to release.

I also wanted to make it a big one, since I'm turning 30 this year, and 30 is a big round number, and I'm hoping to have the game in a releasable state 30 days from now... It's just a nice convergence of numbers.

Here's the gist of things:

- Complete UI do-over. All the major graphics and art have been updated and replaced. This was the biggest speedbump - I couldn't release a game if you couldn't sign in!
- Replays. Yep, you can now record and playback your victories!
- A lot of gameplay changes - nothing incredibly major, but important nonetheless.
- New website uploaded.
- New forum software installed and re-built. Also hacked to accept user registrations right from the game.

I thought the old graphics were hot, but this new hotness is just... on fire. I love it, I love it to bits. I especially like how it looks sitting pretty in the new website. The notification boxes and level save boxes are all in place now too, and I've implemented handy new features like URL-copying-to-clipboard and other fun stuff. The entire graphical user experience is simply doublegood now.

It's getting pretty late here so I'm going to sign off for now. Updates and new builds should come more frequently now, and the changes will become smaller and smaller in scope as we start ramping up for launch day. Thank you, Alphanauts, for helping us get this far.

Check out the brand new website at www.protonaut.net.
Check out the complete changelog for Build 30 at this forum post. (It's a big one!)

Thursday, August 6, 2009

The Indie's Lament

I just hopped out of a steaming hot shower (where I do most of my thinking) and listening to The Decemberists when I started having conflicting thoughts on how big an Independant Games team should be.

The fella doing art for Protonaut, and my primary partner in this venture, is Greg Wohlwend (who has a wicked website). He's great. He works tremendously fast and is wonderfully talented. He has a good head on his shoulders about how the industry operates and has a good handle on games themselves, and gives very valuable feedback on how things are going on the code end of things. If I could buy stock in G.W. futures, I would.

I think one of the best things about having a single partner like Greg is the mutual motivation. Like a climbing plant seeking sunshine, I'm just a dude in search of a relaxed, lazy lifestyle on the beach. When I code alone, I can often lose multiple weeks of development time to a newly released game. I can get distracted with watching Firefly again. If the sun shines a bit more brightly today I might just go down to said beach. Having Greg around keeps me motivated - not just out of guilt for letting him down, but also by genuinely keeping me excited about the project. When he produces a new piece of art, I can't wait to implement it!

There is, however, a fleck of dust within that diamond. When I am motivated; when I am actually getting things done, I have a very one track mind. I get an idea, I iterate the code towards the utlimate goal, and I end up having an agreeable chunk of software - something to be proud of. During this process I'm often observed to decline food (gasp!) and push away beer (the horror!), and hardly move from my chair for upwards of 12 hours. I'm not complaining here, I'm just saying - this is how I do my best work.

Sometimes those coding sessions can go on for weeks.

By having a partner, it's pretty much guaranteeing an interruption. Sure, sometimes the interruption is good - feedback on the current project, maybe some hints or shortcuts to make me finish faster - but sometimes it can be a bit more trying. While I'm excited to accept new game assets (be it code, art, sound), and I know the game will be better for it; I think many programmers will agree: Dropping a project halfway through to switch to a new task is like trying to change gears without a clutch.

As each additional project member is added to the mix, this can occur more and more frequently. I believe this is observed even at the highest levels of corporate culture, where daily status meetings can end up being your primary export. More people to pay attention to, with a deteriorating level of productivity.

It's at around this time I start remember the recent Cogs Postmortem I read. They pretty much say the same thing, but quantify it with a graph.

As much as the businessman in me wants to run my own studio; as much as I want to have a team and command them to fetch me my surfboard; I don't think I can be what I want to be... a Programmer... In a team with much more than 2 to 3 people.

And with a team of 1, I'd never get anything done.

I guess that makes me Indie!