Archive for March, 2010

Programming Made Easier with the Right Formats

Friday, March 26th, 2010

We’re going to go WAY back in my programming career this time. I’m almost embarrassed, in fact, to be mentioning this. My first real attempt at action game programming was making a game out of a silly paper drawing that my friends and I had worked on, called a “Torture Course.” Screenshot is below.

Torture Course

It looks like your typical “get through a dungeon full of traps without dying” type of game. More or less, it’s true. ASCII characters plopped on the screen, leaving much (okay, just about everything) to one’s imagination.

Incredibly, a game this early in my programming career (circa 1991) had sound programming, mostly in the form of creative effects when your character gets zapped, stabbed, burnt, cut up, etc.

But how was the level information stored? How did I edit it? How to test it?

Heh heh…well, folks, I hadn’t yet learned that you can actually call API functions to save and load information. What’s that, you say? You can SAVE your designed data and LOAD it later?

If you don’t believe that the level was generated ENTIRELY by code, just look at a sampling of how the BASIC code was constructed:

19 I$ = INKEY$: IF I$ = “y” OR I$ = “Y” THEN SYSTEM ELSE IF I$ = “n” OR I$ = “N” THEN 0 ELSE GOTO 19
20 I$ = INKEY$: IF VAL(I$) > 6 OR VAL(I$) < 1 THEN 20 ELSE TYPEVAL = 0: CHAIN "intermis.bas"
49 L = 40: FL$ = CHR$(15)
50 A = 2: B = 1: C = 102: SQ = 6: F1 = 26: F2 = 26: F3 = 30: F4 = 30: UP = 1: LEFT = 1: F$ = "M": T1 = 3: T2 = 6: WP1 = 10: WP2 = 25: JUMP = 2: H = 3: LF = 1
60 LA$ = CHR$(175): W$ = CHR$(219): U$ = CHR$(24): D$ = CHR$(25): R$ = CHR$(17): L$ = CHR$(16): LS$ = CHR$(176): WP$ = CHR$(254): V$ = CHR$(179): LN$ = CHR$(196)
61 CLS : COLOR 8: LOCATE 1, 1: PRINT STRING$(45, W$); : LOCATE 8, 1: PRINT STRING$(45, W$); : LOCATE 8, 40: PRINT " "; W$; " "; W$; " "
62 FOR X = 2 TO 7: LOCATE X, 1: PRINT W$; : LOCATE X, 9: PRINT W$; : LOCATE X, 16: PRINT W$; : LOCATE X, 24: PRINT W$; : LOCATE X, 45: PRINT W$: NEXT
63 LOCATE 2, 2: COLOR 10: PRINT V$; " "; V$; " "; V$; " "; V$; " "; : COLOR 6: PRINT WP$; SPC(13); : COLOR 8: PRINT W$; : COLOR 6: PRINT WP$; : COLOR 8: PRINT " "; W$; " "; : COLOR 10: PRINT V$; : COLOR 8: PRINT "oooooo "; LS$; " "; LS$
64 LOCATE 3, 2: COLOR 10: PRINT V$; " "; V$; " "; V$; " ": LOCATE 3, 16: PRINT " ": LOCATE 3, 32: PRINT V$: LOCATE 4, 2: PRINT V$; " "; V$: LOCATE 4, 27: COLOR 8: PRINT W$; W$; " "; : COLOR 10: PRINT V$
65 LOCATE 5, 2: PRINT V$: LOCATE 5, 28: COLOR 8: PRINT LS$; " "; : COLOR 10: PRINT V$; : LOCATE 6, 28: COLOR 8: PRINT W$; " "; : COLOR 10: PRINT V$: LOCATE 7, 2: COLOR 12: PRINT U$; U$; U$; U$; U$; U$; U$; : COLOR 8: PRINT W$; : COLOR 14
66 PRINT LS$; LA$; LA$; LA$; LA$; LS$: LOCATE 7, 24: COLOR 8: PRINT " "; LS$; " "; : COLOR 10: PRINT V$;

Ha ha ha ha he he ha ha ha–oh, whoops. I gotta continue this entry. You can continue laughing if you want. If a software engineer in his right mind would ever code like this, he would have to be under one intense deadline. Obviously, coding discipline and coding standards are very important, neither which I had even heard of back then.

If only I had thought ahead of time how to put the program’s architecture together. But when you have only your own resourcefulness, every line of code you write is a proof of concept in some fashion. I will note that programming courses on the level of what I was trying to do were NOT offered at my schools. So I improvised.

Walls and movers were drawn on the screen with for…next loops. If…then statements were used to check for collisions. And I mean a LOT of If…then statements. One for each wall segment or obstacle. The Torture Course bears a striking resemblance to a game known as “Escape from Epsilon,” which at the time, I had never seen. But the creators of THAT game had it together. I clearly did not.

It would have been far better if I had designed the levels in a text editor, with various symbols representing the walls and obstacles. It would have been much better if I had simply chosen an intra-code gridded format, like what Scott Miller did with Kroz. Making my own independent level editor would have been excessive, though. Especially when you consider that I’d have to create an entirely new format.

Speaking of which, there are a LOT of game design formats out there. Since every game is its own beast (and often its own programming masterpiece), it’s reasonable to assume that just about every game has its own custom formats, specific to JUST that game. Well, sort of. The resources used to create games are now a lot more standardized than before: GIF, BMP, JPEG, PNG for images, MPEG, MOV, and AVI for video, WAV, AIFF, and MP3 for audio.

But the level designs for games are all over the place. I’ve got several of my own: NIB, NGR. There are FR files, UNR files, MAP files, and the list goes on. Savegame formats? Once again, all over the place. What do these mean? Should we care?

Granted, there are somewhat standardized level design formats. A software engineer must decide on the ease of implementation when figuring out how to store the formats. I’ve mentioned how BARfly can transform text into binary with the formats used in Brian’s Journey. But really, a designer needs to start out with concepts, and not so much formats.

What is the designer trying to represent? If it’s a static 3-D map, try using an off-the-shelf editor. If it’s a standard 2-D grid, try using an off-the-shelf editor. If you need to start adding game-specific features that no off-the-shelf formats support, think about XML or other text-based formats. There should be no shame in starting out a level design with multiple formats per level. After all, many maps are designed in such a fashion: static elements on one layer, and actors and dynamic elements in additional layers, which are placed at pre-map based on a specific context.

Software engineers are supposed to be resourceful. Use text when you want to edit quickly and experiment. Use off-the-shelf editors to generate static designs.

But whatever you do, DO NOT create your own level editor unless you think it’s value-added in terms of time. It can save loads of time if the editor and the game app are the same program, but remember, the cost of developing the editor is something you can’t get back. Try to figure it out:

Is (Cost of Editor Creation) + [(Less Time Editing) * (Total Number of Levels)]

less than or greater than [(More Time Editing with COTS editor and text files) * (Total Number of Levels)] ?

In my case with the Torture Course, and in Scott Miller’s case with Kroz, a single change to a single level feature required a recompile of the ENTIRE program. And back in the day, compile times were not fast. That adds to your development and testing time!

In the case of Nibbler, an intra-game level editor allowed much more rapid development and testing of levels, even though it’s just a compressed gridded format.

I guy I know named Josh uses text files to script when enemy ship formations appear in his side-scrolling shooter. Is that wrong? He has claimed it could be viewed as lazy, but I think, what’s a more straightforward way to fine-tune level features than to modify a text file?

There is no consistent answer to how you should use formats to make your development job easier. But if you ask the right questions, you’ll be in good shape.

But one thing is clear: good riddance to “FOR X = 2 TO 7: LOCATE X, 1: PRINT W$;” !!!!

Local File Manipulation with Flash

Monday, March 1st, 2010

For the last several months, I’ve brought myself up to speed on the Flash platform. This a very common environment for the creation of animation, movie clips, and games that are designed to play in an embedded application. This usually means a web browser.

I find Flash useful for game programming, because it’s cross-platform and doesn’t require a separate download. Give someone a link, and -BAM- they’re playing the game. That’s all you need.

But (and there’s always a “but”)…

What about loading and saving of data files to secondary storage?

The general trend for language runtime development is to add more features, give more flexibility, run on more target platforms, etc. Basically you start small and conquer more territory over time. For Flash, it’s no different: it used to be just a sandboxed environment with arcane scripting, focusing mostly on the animation side of things. Then animation expectations got bigger, with a third dimension. Then people wanted more high-level language features; AS3 is now a lot more akin to Java than ever before. Then people wanted full control over files, local and remote. And control over cookies. And the ability to network remotely. And the ability to–

Whoa, whoa, whoa, whoa! Slow down! Are we talking about a sandboxed environment anymore? It seems like you can do anything from Flash now, including program viruses that infect the moment the animation plays! That’s a risk that Adobe has realized and tried to mitigate.

The Flash security settings are actually designed with a lot of foresight. The Adobe AIR platform, created to act as a Flash-based runtime on the server, can do just about anything with files, much like Java, .NET, Perl, or PHP. If your web server supports AIR, the sky is the limit.

But an SWF in your web browser is another story. The sky is NOT the limit–you can only climb a few feet up the mountain if you’re not using AIR. If a Flash SWF file is run as an embedded control in the browser, you don’t have as much control over networks or files. Mainly:

1) Accessing client data, like cookies, is much harder.
2) Network-based communications face many restrictions (can’t “bot” users who run SWF files).
3) Files can be read with URLRequest, URLLoad, etc. But writing to them is nearly IMPOSSIBLE.

Point #3 has been the biggest disappointment to me in terms of game programming. Writing back data to the web server, even if it’s just a dopey high score list, is WAY harder than I think it should be. But it’s also understandable. Flash is an animation platform–Adobe wants to keep it that way. Would-be virus programmers be damned.

But…what if I just want to make an online level editor and save my work that way? You mean I can’t even do something as simple as fopen, fwrite, and fclose in the same freaking directory as the SWF?

I’m a resourceful sort of person. I didn’t want to believe Flash was so restrictive. And it turns out, it’s not.

There are roundabout ways to save data. The Flash security settings, by default, let you access HTML pages and data files in the same directory as the SWF. You just need to be tricky about how you “read” a file.

In the case of http://www.chriskallen.com, the answer lies in PHP. The following Flash code uses sendToURL to “load” a PHP file. But notice that we’re putting a GET variable, text1field.text, into the URL:

function xferClick(e:MouseEvent):void
{
//Compose URL.
var urlstring:String = text2field.text;
var varstring:String =
"?parameter=" + text1field.text;

//Send request (don't check result).
var myrequest:URLRequest = new URLRequest(urlstring + varstring);
sendToURL(myrequest);
}

This means that we’re loading a dynamic web page–a PHP web page–by virtue of a custom input in a GET variable. Unlike non-AIR Flash, PHP can manipulate files locally. As part of the web page “load,” the server-side PHP script gets executed, causing the GET variable to be “saved.”

The SWF can read the data back by invoking URLRequest. No problem!

What does the user see when sendToURL is invoked? Depends on the browser. Since HTTP is stateless, the user might notice that the status bar indicates web traffic. Nearly invisible web traffic, but to be sure, it’s there.

I’ve got my strategy for loading and saving files. Yours can be the same, or it can be much different. You could use Perl instead of PHP. You could install the AIR runtime on the web server, if you have that ability (I don’t). You could use ASP or JSP. The list goes on and on.

Did someone say something about a sandbox?