3rd Oct 2008
Having returned back from Flash on the Beach 2008 yesterday I finally have time to sit down and collate my thoughts.
I had been looking forward to FOTB for months, the constant emails from them bigging it up, the “you must be there!” attitude coming from the blogosphere, the list of impressive speakers. It was set to be 3 days of Flash heaven. In reality it didn’t quite pan-out like this. I think my expectations were a bit too high to be honest, and should I attend again I’d know exactly what to expect, and crucially which speakers to avoid.
I have full respect for anyone who can get up on stage and talk to hundreds of people. It’s something I know I’d have real trouble doing well, so I do genuinely admire them for it. But what I don’t admire are speakers who are highly dis-organised, easily distracted / side-tracked, or who delivered extremely content-weak sessions.
A couple of the sessions were truly terrible from an organisation point of view – minutes of wasted time spent messing around in iTunes, or frantically trying to find a file somewhere on the hard drive (is it really that difficult to organise your presentation material into a single folder or set of short-cuts on your desktop?). It’s not like they didn’t have enough time to plan for the event.
A few sessions also felt like little more than a narrated showreel of work (most of it quite old). This really bugged me, I wanted to learn new tricks and tactics to take home and play with, that is why my company had spent good money to send me there. But in reality this didn’t happen half as much as I would have liked.
But it wasn’t all bad and some of the sessions were truly incredible. The absolute highlight of the whole 3 days for me was Joa Ebert talking about “Audio Tools Private Parts“. This was a superb session and truly inspirational. He covered object pools (and how they applied to their new Tween engine), lots of detail of approaching the seemingly simple problem of bending a cable around an object (lots of graphs, lists, sorting methods, etc). He also alluded to the fact that their AS3 disassembler is nearly ready. In short, the guy is a genius and I have absolutely maximum respect for him.
I guess his session appealed the most because I’m a coder, I’m not a Flash “designer”, I didn’t acidentally fall into coding as a means to get my artwork to move. I’ve always been a coder. So it takes clever code to impress me. Joa’s 10 minutes of “live coding” in the Jam Session was excellent, but full respect to the C64 emulator (written in AS3) with sound support too
I’m still kicking myself for not going to Andre Michelle’s talk, but it clashed with a session on decompiling and hacking SWFs which I hoped would be far more in-depth than it actually was (but again I can appreciate why it stopped where it did).
Keith Peters did a good talk on playing around with verlets. It wasn’t complex stuff, but it was nice to see it presented so well. All of his slides were in order, his code easily accessible, his timing spot-on. I liked the little bits of history he dropped into it as well (about the real mathmaticians behind it all). It convinced me to pre-order his new book, not because I think it’ll contain anything earth shattering, but just because he has an obvious love for this stuff, and that’s always a good thing to inject into your book.
I regret very much not hearing Grant Skinner, Richard Lord or Rob Bateman talk. They all clashed with things that sounded more useful in my everyday work, but sadly didn’t turn out to be the case.
If I go back to FOTB I’ll definitely know how to pick better, which should hopefully increase what I ultimately take away from the event. But I can tell this much already – if none of the uber-skilled German guys are talking next year, I certainly won’t go.
28th Sep 2008
Everything is packed, all the tickets are in order, and very soon I’ll be heading off to sunny Brighton for 3 days of intense Flash on the Beach.
My only concern is that lots of the sessions I want to attend overlap each other!
For example I’d love to hear Joa Ebert speak about Audiotool, but I’d also like to hear Grant Skinner talk about general AS3 (they clash). Keith Peters also clashes with Rob Bateman but the one I’m most upset about is that Andre Michelle clashes with what sounds like a fascinating session on SWF decompilation. That’s a topic I’m extremely interested in, but Andre is an ActionScript God, so I don’t doubt he’ll impart some excellent advice during his session.
Damn it, I wish I could clone myself!
Anyway if you’re there (or possibly even there already if you’re at the workshops!) then “Hi!” I’ll be there with two other Aardman dudes, and much enjoyment and learning shall ensue. I’ll post a report when I return next week as I don’t intend taking any hardware with me – I’m going to let my brain soak it all up and give my typing fingers a rest.
19th Sep 2008
Tonight I updated the PixelBlitz Engine with a small but significant feature. I attacked the issue of redundant redrawing of elements, and updated both the PixelSprite and RenderLayer classes so they no longer refresh all of their content if nothing has actually changed since the last render call.
Sounds simple and it is, but it makes a world of difference to the speed of things.
I’ve been researching how beneficial adding a dirty rect system in the engine would be. The problem I have is that it’s all dependant on the type of game. For example a vertical shooter, with a scrolling background and bullets flying everywhere, would have no benefit at all – if anything the extra calculations may even slow it down. But in a sedate game, especially one with large (overlapping) objects, it could be a dream.
So, still in two minds really – perhaps it’s something we allow the user to disable at will.
For now I’m going to optimise the 2DRenderer further by making it only copyPixels() from the area of the RenderLayer that has changed. At the moment it grabs a full sized layer even if the layer only contains say a 64×64 sprite somewhere.
Anyway until then the new code is available in svn.
19th Sep 2008
While planning some new routines for the PixelBlitz engine tonight one thing struck me – is it actually worth it?
There are a number of articles across the web about pixel blitting in AS3 (most of them at 8-bit Rocket but I did wonder if anyone had actually done some tests to see just what difference it makes in real-world terms.
After all, why mess around “blitting” things about if using a Sprite or MovieClip is just as fast anyway? Infact you could easily argue that using a native Flash display object gives you far more control (as you get to play with scaling, alpha, rotation, animation, sound events and more, easily).
Another thing also struck me – when building up the display for render the AVM will automatically use a dirty rectangles system. If you’ve got two overlapping movieclips then it won’t waste time drawing pixels that would otherwise be obscured by the one in front. Traditional blitting on the other hand doesn’t care about this, it’ll gleefully copyPixel() until the cows come home, pasting image after image on-top of each other (PixelBlitz suffers from this issue too).
[ Side note: It’s true we could add a similar dirty rectangles system to Pixel Blitz, to avoid copying data when it’s guaranteed to be overwritten further up the chain – but this is not something we’ve found a fast way to do yet (the potential alpha channel of a bitmap causing the most problems), the overhead of sorting and checking for overlaps is always taking longer than just brute-force copying everything each time (if you can help, email me!) ]
Tonight I decided to write two simple tests. They would measure the speed of the AVMs dirty rectangle system vs. raw bitmapdata copypixel power. I was interested in 3 things – the overall time it took to run the test, the amount of memory it used and the average fps rate.
I took a 550 x 400 sized stage published at 30 fps. All tests were run using the Debug version of the Player (9.0 r 124). The test consisted of creating an array of X number of sprites (to test the AVM) and PixelSprites (to test blitting). Each sprite was 50×50 in size and contained an alpha channel. I then drew all of the sprites onto the stage and moved them along by 4 pixels per frame, if they hit the left of the stage they wrapped around to the right again. The Sprites had cacheAsBitmap set to true (see note below)
Then I ran the tests multiple times, with varying numbers of fish, for varying durations, recording the data at each step and averaging it out.
I agree that this is in no way a truly “scientific” test, but I wanted a general “feeling” as a result, to see if this was an avenue still worth walking down or not.
With 500 sprites both the standard Sprite and the blit method kept a solid 30 fps frame rate. Using Sprites consumed 15MB of RAM, using blits 11MB.
At 1000 sprites we’re still at a consistent 30 fps, but there is noticeable “tearing” in the visuals as the sprites move across the stage. It’s not terrible, but you can easily see it. The standard method is now using 20MB while the blit is using 14MB.
2500 sprites and we see both techniques struggle to keep-up with the 30 fps rate. The traditional Sprites actually outpace the blitting at 23 fps vs 21 fps, but the memory consumption is more than doubled, 35MB vs. 15MB.
At 5000 sprites they are both starting to feel the strain, each level pegging at 12 fps. But the standard Sprites technique is using a staggering 58MB, while the blit is only up to 20MB.
7,500 sprites all moving at once and both techiques are virtually bought to their knees managing just 8 fps each. Given the amount of data moving this isn’t totally surprising. The blit technique at this point is literally copying 18.7 million pixels around in memory. The AVMs internal dirty rectangle is feeling the full force of what’s going on however, and is now consuming 237MB of RAM vs. the blit techniques 25MB.
10,000 sprites crashes the Debug player for both versions, it literally runs out of memory
As I mentioned at the start, the Sprite version had cacheAsBitmap set to true. This is the main cause of the huge amount of RAM being used. As our Sprite only contained a single Bitmap this wasn’t needed. By removing this setting the amount of RAM used dropped, ending up only a few MB higher than the straight blit method.
So what can we pull from this?
First of all, the AVM dirty rectangles implementation is pretty damn sweet! But brute-force blitting is equally as fast in this test case. Logic tells us that adding redraw aware optimisation to our blit engine should increase this gap in our favour significantly.
NEVER enable cacheAsBitmap on a Sprite or MovieClip if all it contains is bitmap data.
The blit engine uses less memory. If you need to cache vector Sprites in your game, then it uses considerably less memory!
No-one really needs a game with 7,500 fish swimming around in it 😉
Maybe the test wasn’t “real world” enough – even at the 1000 sprite level (at which both methods kept a 30 fps frame rate) we were still moving 2.5 million pixels around a 550 x 400 stage. That’s enough to fill the stage 11 times over (and still have some spare). Is this likely in a real game? Well no, I don’t believe so – but it isn’t that far off either. Games are getting bigger (we published one at 800×600 today for example), and if you had a game featuring multiple layers going on (foreground, player, background, distance, etc) with alpha showing through them all, then it doesn’t take long to start using pixels in the millions range.
There are instances when I believe it’s just easier to deal with things on a blit level – for example building up a large n-way scrolling tilemap, where you constantly need to redraw the scroll buffers. Doing the same by placing (and updating) hundreds of Sprites would be an exercise in pain I wouldn’t wish on anyone.
Is a combination of both worlds the way to go? Quite possibly. While I loathe using the timeline (or Movieclips in general) for anything, they do offer Flash animators a rich featured tool-set that let’s them create vibrant moving games. Whereas the blit method requires graphic artists trained in the way of the pixel, and I believe those are a dying (and expensive) breed indeed. Creating quality animations at that level is time-consuming and costly. But as we’ve seen, animating on a vector level introduces both resource and speed issues into your game.
What about collision detection? Well we all know this pretty much sucks in Flash. So we have to roll our own methods anyway. For pixel perfect collision detection we need to inspect the elements on a pixel level (surprise surprise), at least with the blit technique we’re already operating on that level, so there’s no extra draw() overhead involved.
Are AS3 Sprites “evil” for those of you trying to create arcade style games? No, I don’t believe so. They can hold their own in the speed stakes thanks to the power of the AVM, but you do have to watch yourself and be very careful re: memory consumption.
Is “blitting” really that much faster the using normal Sprites? No, it isn’t. It does have less memory overhead and a “cleaner” feel to it, but it’s no speed demon in comparison.
Would a hybrid solution work? (i.e. a fully blitted tilemap with Movieclips characters on-top) – yes, absolutely!
Don’t feel that because you have travelled down the “blit” route you need to have the whole game living there. If you can mix and match your game logic and most importantly your collision systems, then there’s no harm in splitting these elements up, using both at once.
P.S. If you’ve got some ideas or concepts on optimising blit level drawing, please get in touch. I’ve been reading a lot about this recently (what I can find at least) but it’s always good to pick someone’s brain.
16th Sep 2008
sergej wrote a comment to my BlitzMouse post saying that if you right-clicked the custom pointer gets lost until the page is refreshed. Here is some simple code to work around this.
In your main SWF make sure you import ContextMenu and ContextMenuEvent. Then add 2 new global vars:
private var rightClickContext:ContextMenu;
private var contextOpen:Boolean;
and within your init (or constructor) add this:
rightClickContext = new ContextMenu();
this.contextMenu = rightClickContext;
rightClickContext.addEventListener(ContextMenuEvent.MENU_SELECT, contextMenuOpen, false, 0, true);
“this” is a Sprite in this case, but any valid display object (that has access to the contextMenu) will do. The “contextMenuOpen” function is literally just the following:
private function contextMenuOpen(event:ContextMenuEvent):void
contextOpen = true;
and finally, in your main game loop, just check the state of this var and reset accordingly:
if (contextOpen && mouse.isDown)
When the context menu is opened (by a right-click on Windows) it fires the ContextMenuEvent.MENU_SELECT event, which we capture and set a boolean for accordingly. While the menu is open we can do nothing about the standard mouse pointer, but in our main loop we can listen out for a mouse click (mouse.isDown) and then hide the pointer again accordingly.
I’ve not tested this on a Mac (where you can command-click to get the context menu up) so if anyone reading can do so, please let me know if it works.
The SWF below should allow you access to the context menu, but upon clicking the SWF again the custom pointer should return (assuming you click within the limit zone!)
All about Photon Storm and our
HTML5 game development services
Filter our Content
- Cool Links
- Flash Game Dev Tips
- Game Development
- Geek Shopping
- In the Media
- Phaser 3