After reading this article about using Flash 8 in Flex 1.5, and failing to prove it wrong, I still figured I could blend the best of both worlds.
I’ve always wanted a Map Revealer, like Fantasy Grounds has; here’s a screenshot. The goal it accomplishes is it allows players in the game to see where they have explored, but not the whole map until they’ve explored it. That way, they have a visual aide to track their progress, and it gives a sense of accomplishment to those explorers in the party. If you walk down the hallway (and don’t fall in a trap), then that hallway is revealed on the map.
Taking ideas from my JXLScratch Off component, I tried to do this pre-Flash 8 by having about 2000 (20×20 10 pixel tiles) loaded on top of a large bitmap. You could, as the presenter (DM) toggle their visibility since they were just clickable MovieClips. Even at that low-level on my Alienware, though, she chugged. The redraw froze the app for 3 seconds. I’m sure I could of done 1 redraw and just synchronized it amongst clients, but… bleh, don’t think so.
Now that we have the pixel pushing power of Director, with the addition of half-pixel support, I figured I could implement what I truly wanted; an anti-aliased fog of war that could be used to reveal a map to a list of clients connected, with the Presenter/DM controlling the revealing.
The original Baldur’s Gate had a GIF transparency approach; pixel on, pixel off. It was actually more close to the Fireworks 1bit transparency you can do with single color images by making every other pixel transparent, alternating rows. You can see an example here.
The sequeal improved it by making what you didn’t see solid black, revealing it with a nice, soft gradient transparency edge seen here, and re-covering visited areas with a transparent gray.
Finally, I can do that in Flash!
Whiteboards Rendering Engines, BitmapData, and Flashcom
Most Whiteboards done in Flash consist of a rendering engine. They take shapes, and render them to the screen. Each shape is unique, and has attributes that are set when it is created and manipulated by the user. When those attributes are changed, they are sent over the wire so each rendering engine on the client can show the same whiteboard state. That way, you have small pieces of data, and when a new piece comes in, your code goes “oh, this is an ‘arrow’, it’s red, is so large, and sits at these screen coordinates.” This process repeats for when an object is manipulated, those changes are sent over the wire. If it’s deleted, those changes are sent as well.
The pros? The data sent over the wire is extremely small since the rendering engine is capable of drawing a lot of objects (arrows, text boxes, drawings, etc.). The cons? Too many frikin’ objects… Flash Player has a lot of overhead (currently, hehe) when creating objects; that’s why when you create a lot of MovieClip’s, things start to slow down. RAM & CPU get ravished.
What’s a bitmap? 1 object. Yeah, it’s a series of pixels, but showing 1 bitmap in Flash is cake, utilizes low resources, and if you change it, it’s still 1 bitmap!
Since you can’t shove it over the wire, though, I had to utilize the best of both worlds. I created a rendering engine based off of Senocular’s code, specifically the Erase & Draw’s example that will draw the changes to the bitmap based on a stored array of mouse movements. This has been done before by GE, but they utilized a vector line. While that certainly does NOT limit ones creativity, the presentation and ability to manipulate bitmaps has been more mature for awhile, and the implementation of such effects in Flash does what bitmaps do best; render well with low resource usage. While erasing the mask, or covering it back up again, I record the mouse movements. You can then run through this recorded array of x and y coordinates to redraw the bitmap exactly as the user did. The sending of the data over Flashcom wasn’t as latent as I thought; there is a noticeable delay, but considering I’m sending almost a thousand numbers in 4 arrays across, it’s not bad.
Pros & Cons
And now, time to tear it to pieces. First off, I do not record the order in which you erase and then re-draw, so if you swap the order, it doesn’t matter; the engine does 2 passes; 1 to do the erasers, and then 1 do to the redrawing of the mask you just erased. Secondly, I could of put a bunch of info objects into 1 array to make the code simpler, OR I could of put each object on a unique slot on the SO to allow the data changes to stream; however, to me, you typically draw the image, and when ready sync it so the rest of your viewers can see. I felt that was a reasonable tradeoff since you only throw that big message every once in awhile. Third, while the erasing of the image mask is a nice anti-aliased (smooth gradient) brush, the redrawing of the mask is not. Couldn’t figure out how to get it to work. Fourth, while “seeing the drawing draw itself” is a novelty, that wasn’t the goal; the goal was to update state and syncronize it across many clients. If you screw up and erase a part, it records that… so it’s not a perfect drawing engine. Finally, it’s a white mask if you are not the presenter; I wanted black, but putting the black color in there doesn’t work since it’s an alpha… or something.
Whiteboard(s) In Our Future
Anyway, after seeing what I could in a few hours after 2 nights, I can DEFINATELY infer what Breeze 6 will have; the most powerful and ubiquitious multi-user whiteboard on the internet. If Macromedia’s smart they’ll withold the key feature for Breeze, like they did with Screensharing for Flashcom, to allow BitmapData objects to be shared over Flashcom. The whiteboards out there currently for Flash/Flashcom are pretty good, but you ain’t seen nothing yet. Either way, if someone spent a few weeks on one… sick!
Map Revealer Demo + Source
Here’s my Map Revealer in action; 2 clients, 1 a presenter, and the other an attendee, share the Whiteboard over the wire. Source FLA + AS in ZIP.