Diesel is a blitting engine for Flash Player 8.5 using ActionScript 3. Uses 1 bitmap to paint to vs. using many DisplayObjects in an effort to utilize less CPU & RAM.
Skip to Introduction if you want to know more about Diesel, or read on for background as to why I’m posting this.
- Why Should I Care?
- What’s wrong with MovieClips for games?
- How is Diesel Better?
- Why not use the DisplayList?
- How do I use it?
- Source Code
I was originally using this project as a part 2 & 3 followup to my blitting post, but realized it is a ton of work. Even getting simple benchmarks down on alpha software is pointless because many memory bugs are fixed in later versions, rendering your previous benchmarks worthless. For example, I’ve found a bug with flash.display.Loader where, if you issue a ton of loads, say over 1900, each load allocates almost a meg of memory. The problem is, even if you delete the loader as well as what it loads, the memory isn’t freed. This is known and will apparently be fixed in a later build.
Not to mention I’m still learning ActionScript 3, so my style of coding has changed the more I learn, making it hard to keep 2 different approaches to a problem in sync: using Sprites vs. blitting to 1 bitmap.
I will say this with confidence; blitting is far more scaleable than using a multitude of Sprites. While the memory usage for blitting is far below what the Sprites use, the processing isn’t what I’d hope it’d be. Additionally, I’d forgotten just how much RAM bitmaps can take. So, even if you make a 2880×2880 blank, transparent bitmap in RAM, it still takes about 44megs.
I still believe, however, that blitting is the future of Flash games, and all I need to do is optimize the Diesel engine a bit more, and she’ll be a more attractive alternative to utilizing Sprites for game development.
My original goal in posting was to show my older version of Battlefield, a simple tile-based map engine based on Sprites, and one based on Diesel. A milestone I had reached as getting the TileMap, a base class, to using blitting only, and scrolling via double-buffering (copying pixels from a larger bitmap, not-shown off-screen). While this made the map scroll really fast, when I started adding Sprites, it still kept a good refresh rate, but started using way more processor than I had experienced in earlier tests on a smaller scale using Flash Player 8.
Frustrated, I realized I had to re-write even all of the sub-classes in Battlefield that rendered sprites, as well as the main walking character. I did so at the cost of not updating the older Sprite one with which to do benchmarking at a later date. Don’t care, though, because again, I feel blitting is worth spending more time on perfecting and optimizing.
So, without further adu, I present a really early build of Diesel, a blitting engine, and Battlefield a simple tile-based engine example that uses Diesel.
With the addition of Bitmap classes in Flash Player 8, developers now have the ability to utilize blitting and double-buffering techniques to create resource efficient gaming engines in the Flash Player. Diesel is a set of ActionScript 3 classes that provide a conveinent display engine to take advantage of these new player features.
Diesel uses 1 bitmap to draw to vs. hundreds of MovieClips. This results in a more scaleable engine, allowing for more moving sprites, lower usage of RAM & Processor, and better refresh rates.
While MovieClip’s are conveinant to code & design with, they are not efficient when dealing with a multitude of bitmaps for games. They also do not scale well when you need to create many of them, and have them all move on the screen at the same time. Finally, large bitmaps in Flash traditionally have not scrolled very fast when used as tile-based game backgrounds. You either have to use 1 large bitmap that is pre-rendered, or you can use tiles in the traditional sense, but neither is an optimal solution for games.
Big bitmaps are not an ideal solution for a couple reasons. First off, it’s not dynamic; you have to create this before hand. While you can load it in dynamically, you have to use MovieClips atop it to generate any effects. Secondly, even if you mask a certain area of the screen, the rest of the bitmap is still drawn the screen, taking up a lot of processor & ram and sacrificing a good refresh rate (smoothness of the animation).
For tile based games, you have 2 solutions. Either draw all of your tiles as multiple MovieClips, and have all of them created in one parent MovieClip. When moving your map, you simply move the main MovieClip that houses them. While this makes coding easy, it suffers from resource usage, namely reduced refresh rate, and it gets worse the more tiles you create. This is even before you start putting gaming sprites on the screen.
Your other solution is to create the tiles on the fly based on the direction the character in the game moves. While this is a lot more scalable than the above, allowing you to create bigger maps, you suffer from redraw speed when creating the new tiles. The creation & destroying operations that you use on the tiles takes up a lot of processor, reducing the continual smoothness of your animations.
It uses a technique called double-buffering. By using 1 bitmap, you solve a bunch of issues MovieClips have traditionally caused. First, you have 1 bitmap, not hundreds. Each sprite in your game is represented as a data object, but it’s bitmap data is copied to the main big bitmap. All sprites are copied to this main big bitmap. This big bitmap is actually not shown, but is off-screen and not in the Display List. A portion (or all of it) is copied to an on-screen bitmap that is repainted when something moves or changes.
This uses significantly less RAM because each sprite in your game is actually just a data object vs. a Sprite or MovieClip. You store basic information like x and y position as well as width and height as BitmapSprites. They are then added to the BitmapDisplayObject, much like you add MovieClips to the Display List. BitmapDisplayObject is just a flash.display.Bitmap that renders all of the BitmapSprites added to it’s list of things to draw.
Additionally, the entire bitmap does not have to be drawn. For example, many tile-based games consist of a large map, but only a small portion is shown. For this reason, only a small portion of the map can be shown, and thus drawn, not the whole thing. So, when repainting, only those portions of the screen that need to be redrawn are, not the whole thing, nor things not shown.
In my tests, Diesel uses less RAM, and uses less processor vs. using Sprites and the Display List.
Simply import the classes into your project. I’ve done my best to match the syntax like the ActionScript 3 flash.display.DisplayObject syntax.
For example in ActionScript 3, if you want to create a sprite and show it, you do something like:
var my_sprite:Sprite = new Sprite();
Diesel’s code works on the same concept of seperating the object from the actual drawing. However, instead of adding your BitmapSprite, the Sprite equivalent, to the normal Display List, you instead create a BitmapSpriteDisplayObject, and add your BitmapSprites to it. The BitmapSpriteDisplayObject class is just a flash.display.Bitmap with optimized code to handle drawing BitmapSprites.
An example of creating a BitmapSprite, and showing it, just like you would create a Sprite to show it, is:
// create your BitmapSpriteDisplayObject
var bsdo:BitmapSpriteDisplayObject = new BitmapSpriteDisplayObject();
// add it to the Display List so it's shown
// now, create your BitmapSprite
var my_bSprite:BitmapSprite = new BitmapSprite();
// and add him to the BitmapSpriteDisplayObject
You can add and remove as many BitmapSprites as you want. Additionally, you can create multiple BitmapSpriteDisplayObjects.
I am definately interested in contributions, suggestions, and/or criticisms. If you’re seriously interested in helping improve the engine so it performs like Andre Michelle wrote it, and/or taking Battlefield to another level, drop me a line in the comments, and I’ll hit you up with Subversion access.
Diesel & Battlefield Source Code
ZIP (beta1)Get latest build from SVN
This work is licensed under a Creative Commons Attribution 2.5 License.