A dated ActionScript 3.0 Engine
The story of a Game Engine, or a series of "oh noes"...
Oh no, most Flash games suck
Back in the day when Flash did not have Stage3D, wannabe game developers like me wanted more performance from it. My games had to be better than every other playable kludge at Kongregate and Newgrounds, I thought a better engine would accommodate the much needed technical advantage I needed to raze my competition to the ground.
After rigorous testing and meticulous squeezing of the language’s performance; the conclusion was sound, to get it just right I would have to rework its rendering engine from the bottom, using methods as low level as I could and a custom blitter to output images.
Oh no, new rendering back-end needed
The project had begun earnestly, and soon features like sprite-sheet animation were needed; sprite-sheets were not able to be added intuitively from any graphics package, so I built my own tool which, in addition to regulate speeds and other parameters, generated the code to embed the graphical assets into the engine.
The complexity in the characters meant that sprite-sheet animations were orders of magnitude faster than Flash’s vectorial key-frame based animation. Looking backwards it would’ve been so much easier to just drop the complexity in the characters; but nay—I thought— I must not do what the feeble lazy masses of talentless game devs do. My games would be different, awesome.
After some time the sprite-sheet animation system was ready, it had lots of features which would accommodate to the different kinds of games I would be churning out soon. There was, however, a huge drawback: bitmaps were heavy.
Oh no, size constraints
What could I do to fight this monster? I wanted that complexity, I wanted those bitmaps and sprite-sheets. Again, willing to push the extents of Adobe Flash gaming I did the unreasonable thing: I wrote my own compression algorithm.
It turned out that PNG was not as efficient as I had previously thought, by merely changing the direction in which run length encoding was performed I had considerable gains in some images and not others. So my compression algorithm tested every possible RLE traversal combination I could come up with, and compressed it. Another day I thought: “What if every texture is in one big texture and I just retrieve it from there somehow?”, and day after day I kept optimizing that compression algorithm.
One of those days I stumbled upon this thought: “How am I able to quantify my benefit from compression?” After all, all of this took processor time to be decompressed. Pencil and paper in hand, I began outlining some crude equations to determine this. I ended up with—among other things—something as simple as: c = s / d; where c was the compression/decompression time, s size, and d download speed. Which was the “smart” way of saying that if the download speed was high enough I wouldn’t need so much compression at all, for an object of 100 kb downloaded at an average 100 kb/s my decompression speed would have to be better than 1 second to see a difference.
Oh no, particles
There was lots I needed to continue doing with the engine, and while the compression results were good, I was not happy with them. Having learnt from my previous unreasonableness, I did the lazy thing, and simplified the art style for the game. Instantly my compression gains were more than tenfold.
Cool games need awesome physically based particle systems—I thought—so the particle quest for my engine begun. Trying to be reasonable I tested the glorious FLINT particle engine, my first tests where things like rain, fire and blood. The results were good, but I was not pleased with them. Adding FLINT would’ve meant using someone else’s code and adding lots of dependencies, I didn’t need most of flint’s features; neither all that extra code I didn’t understand fully, nor did I want to read that source code.
To my surprise, the particle system I wanted was not hard to implement, and soon enough I had a small functioning particle system capable of rendering pixelated rain directly to the blitter.
Oh no, procedural content please
As a single developer with a single artist (my brother), my games’ scope was very limited by the amount of art we could output in a given timeframe. So procedural generation was a must, after reading lots on L-Systems and other interesting topics; I set on to build my own procedurally generated forests. Not being a quitter didn’t help, and soon a tile map generator followed.
Some features were missing from my blitter, and not any moment sooner I added the needed custom bitmap resizing capabilities and some other stuff I really dug, like quincunx antialiasing. Quincunx was slow without GPU acceleration, but I could just apply it as a filter to the sprite sheets and voilà.
Oh no, lots of subsystems needed
I had to manage most things by hand so to speak, that way camera handling appeared, a very memory efficient sound manager, key-binding with support for multiple key presses and combinations (as in fighting games), asset loading, custom data structures, scene management; everything was double checked for consistency and low coupling, if it wasn’t modular enough I made it so.
The engine was VERY fine grained, and nothing was created if its components could be extracted from another dead entity, the Flash runtime was not characterized by its fast creation of objects (I don’t know if it does now).
Finally, my game prototype was being efficiently loaded, drawn and handled by my engine. Everything was working fine, with one big exception, my game entities were really stupid.
Oh no, AI
Work began on my rudimentary AI, I studied lots, neural networks seemed like too much, I settled on state machines and behavior trees. There was slow progress, testing AIs was boring and repetitive. My game enemies chased my avatar and made some centralized group decisions, still some things had to be worked here and there; but it worked reasonably well.
All I needed to do was just keep adding content and testing, and my game would be finished in no time. Except… I didn’t, I had discovered the marvelous world of AI. It occurred to me that I shouldn’t write my AIs by hand, instead I could write an AI to write AIs. The endless tweaking would certainly end if I built an automated tweaking-machine of sorts, to my pleasure it worked. And soon I thought that it got too good for a simple Flash game, I tested it in many environments and it provided very good results; even while running on something as slow as ActionScript 3.0.
Recently someone on Facebook told me that either you make games or engines, now I can see the truth to that. Years later, my AI got more sophisticated than the Game Engine ever was, and Flash added Stage3D and many more things which render my blitter obsolete I guess.
I have an ActionScript 3.0 Game Engine with:
- A fast bitmap blitting engine.
- Sprite sheet animation
- Automated asset importing pipeline
- Sprite sheet animation editing tools
- Custom bitmap compression better than PNG
- Particle system
- Procedurally generated content
- Tile map editor.
- Full screen Quincunx antialiasing.
- VERY fine grained game entities.
- A blitter compatible tweening engine.
- State machine based AI.
And it spawned an AI which got more complex and advanced than the Game Engine itself.