2009-07-04

Technically Competent Flash Game Engine

After playing with flash enough (Flash Professional 8)
I've reached a conclusion about how to build powerful, dynamic flash games.

I've worked with flash off and on for years, C/C++ and OpenGL are much cooler, but it has become difficult to manage my pipeline without additional tools that do not exist; So I am taking a break from that for a bit.

In order to properly make a flash game, you must first understand what a 'video game' is and how it works internally; They are full of interesting technical challenges as well as evil hacks; Because a game tends to be a simulator or emulation of some system, that means we'll never be able to truly make exactly what we want, either due to time or power constraints.

With that in mind, let's build up a 'megaman' example game.

We know from playing the megaman series on the NES that megaman is a little robot dude that can shoot other robots, some of which can move around and shoot back! And, if he enters a boss room, he can shoot a special enemy that can give him additional weapons!

Not much else too the game, really! Let's generalize it.

What kinds of things are there in the game?
-Sprites (2D Pictures)
-Sounds (Sound effects)
-Music (Longer strings of sounds! .nsf or some other mod format)

Well, that's kind of an aesthetic look. The actual game however, isn't quite as simple, as there are a variety of object types, like each type of enemy, each type of bullet, and so on.

When we look at a game from the programmers perspective, we can group all the things that work that same, and build a hierarchy:

Object
-Sprite
-Moving Object
--Bullet
--Controlled Moving Object
---Enemies
---Megaman

So, for each level down we go, we have to add more special code; There still is no magical way to code each type, that will ultimately have to be done. However, we can reduce the amount of work signifigantly by providing generic utilities for moving and updating those objects;

For example, we can have "MoveAsPlatformingCharacter" "MoveAsFlyingThing" "MoveAsBullet".

And, the ironic thing, is the game is still just moving pictures that can add and remove pictures and sometimes play sounds. There isn't anything more to it than that.


So, stepping back a bit, let's look at what flash can do for us:

-Automatic Heirarchy
-Display sprites, images, movies...
-AND can move, rotate and scale them!
-AND can colorize, shade, ect...
-AND can dynamically draw shapes!
-Automatic Sound playing
-Streaming music palying
-Input handling

So flash can do everything we need! But, flash is not assembly code, it is a SCRIPT LANGUAGE. That means that you cannot apply the same logic you use in C to flash; Script languages are not C, and C is not a script language and vice versa.

So in flash terms, we will have 1 movie clip called 'game' that has everything we need in it, as well as having ALL the functions we will use in it, so that you can do this:

game.moveObject( obj, 4, 0 ); //Move object obj right by 4 units

Inside of the game movie clip, we must have all the clips we want to duplicate in real time. Usually this is accomplised by:

game.dup_character;
game.dup_bullet;
ect...

Where, inside each of those dup_character, you have a lot of named frames for that specific character type, like "Heatman", "Iceman", "Megaman", and in each of those frames, you put down the instance of the clip you want to animate; you do not do the animations in the duplicate clip, you make a seperate layer;
This way, you can name each clip inside of the duplicate clip the SAME THING, ergo: "mc", so that the game can reference the mc identically for each instance, AND separate scaling and other properties from it.

[MovieClip: dup_robot]
[FrameName : "Megaman"]
mc [Instance of "Megaman" movie clip, which has all his named animations, like "run", "jump", ect...]
[FrameName : "Heatman"]
mc [Instance of "Heatman" movie clip, which has all HIS animations ]

so your 'game' clip now has this:

[game : Game clip]
dup_robot [Instance of "dup_robot" movie clip, which has all the possible robot types each in a specially named frame]
dup_bullet [Instance of "dup_bullet" movie clip, which has all possible bullet types each in a named frame]
ect...

Using this method, you can simply duplicate a dup_clip, then set it's frame, then once you do that, you can set the mc inside of it's frame, thus instantly allowing your game to be very flexible to add extra things later!

So this is all fine and dandy' Now in flash you can duplicate any clip that graphically represents what your game is, but, what about the actual game?

Here's where it get's difficult; If you trust flash's 1 collision function (hitTest) then you might know that it DOES NOT WORK on and point test that is NOT on the stage (any non-rendered pixel CANNOT be hit-tested against. SO DONT USE IT!)

That means yes, you have to make up your own collision scheme, and make up your own collision math, and your own physics system for motion.

Basically, that means that every object should have a .x, .y, .vx, .vy in it, so you can perform basic rectilinear motion. As for updating your objects, so long as you make a working rectilinear motion function, you can add any complex types of motion you want later.

This will be covered later, but the easiest solution is to add another dup_clip that creates boxes and ramps, which are very basic and mathematically simple collision primitives that you CAN make a game out of quickly.


But all this high level talk isn't much use; Because when you get started, you'll find you need a couple of basic tools:

Something to store this data,
A Map (dict for those python kidz)
A SpaceHashing/Broadphase test

Map is actually simple in flash,

var mymap = new Object();
mymap[ "any key as a string" ] = data;

So you can abuse flash's quick Log2(n) internal string search for object properties as a map. It's as fast as it get's folks.

A Spacehash is up to you, I prefer using a single axis sort and doing a map/array of bins, which have maps of catergories, each which stores an object UID

Yes, every object you make should have a non-repeating Unique ID. Don;t rely on the movieclip as one, you never know when depth levels can change or clips for that matter. Use a Number and just increment it, or make a map and reuse unused keys.

Blargh; What a mess. Too much information to disgorge for ya'll.

I'll post the flash engine later. Then you can just %#@*(& use it!

Happy fourth!

-Z

No comments: