The Making of VigeTurf - Flash
Erik Olson, Former Viget
The actionscript side of uploading photos is very simple, but more involved for Matt who had the mighty task of putting the entire site together and did an awesome job. I just referenced the FileReference class, which will tell your OS to open a file browser window when you call FileReference.browse(). Because of security restrictions in Flash player 9, you need to send the file to a remote server before you can access it. This changes in Flash player 10, where you can directly access files at runtime (woohoo!).
Once the image was fully clipped, I simply took a snapshot of the stage and saved it out as a byte array. Using Adobe's Jpeg encoder class, I saved the image back to the server, where Matt returned the unique (and fun!) url's.
The blades of grass were probably the most fun part of this project. I was so excited about the task of making interactive grass that I started messing around with it that night. (You can see the grass in an earlier version here.) All of the blades are individually drawn using the AS3 drawing API and are given a random height and angle to look like nice, organic grass. All the blades are placed into a movie clip because, later, I will need to convert that movieclip into a bitmap to enable erasing.
The interaction with the mouse pointer was a bit tricky, and the result was not perfect, but the effect works (right?!). When the mouse pointer passes over the blade, it sticks to the pointer until you bend the blade to 45 degrees in either direction. At that point, the blade stops following the pointer and a tween takes over to get that "snap back" effect. That effect is handled using a simple tween that sends it back to its original rotation. The ease on the tween is set to "Elastic EaseOut" to get that great pendulum-like bounce (I used the TweenLite tweening library from GreenSock, which has become my tweening class of choice). When first envisioning the grass, I pictured very life-like blades that bow organically instead of the stiff bend they have now, but I quickly abandoned that idea after Steph said I couldn't take several weeks to perfect it because it had to be done by the holidays. Picky picky.
Another challenge I was unable to overcome was the speed of the initial "growing" animation. There are 300 blades of grass, which means there are 300 tweens that need to happen. I chose the TweenLite library because it is the fastest one out there, but it still wasn't fast enough to allow for 300 perfectly smooth tweens at the same time. I think I started seeing lag at around 75 or so blades. I tried using a timer to fire at various intervals growing a few blades at a time, but was never satisfied with the outcome. Blades of grass don't grow in even intervals anyway. The blades are just 2 colors of vector and are tweening on height so nothing I could strip out of them.
Actually, I am realizing as I write this that they have a dropshadow on them, which uses up a good chunk of CPU. Perhaps if I strip that out until the blade is fully grown, I will get a cleaner tween. Any ideas on how to further optimize for tweening?
Erasing is far more complicated that drawing, and by the time the erasing functionality was working, I still didn't fully understand how it worked. The erasing is handled using a poorly rewritten class from senocular, and you can see another great example that was very helpful to me here.
On a high level, the erasing works like this: You take what you want to erase and convert it to a bitmap. At this point, you are able to manipulate its bitmap data in all kinds of crazy ways that go way over my head for this project. Next, you take a shape for your eraser (or, if you are working with grass, a set of clippers) and duplicate that shape. The shape will trail the mouse, but only as a visual for the user. It is not necessary for erasing. (Please see the source files below for the actual code).
Another aspect of working with grass are the clippings! It's effects like these that make me love what I do.
As the clippers pass over the grass, they spit out bits of green shapes that really have nothing to do with how much you are actually erasing but are just randomly sized and shaped chunks of grass that fly around. A problem I ran into was how to detect when you were or were not actually clipping grass. It would be pretty silly to have grass clippings flying everywhere when there is no grass left! The way this is handled is by looping through all the pixel data that is under the eraser as it moves. Since we have converted the turf into bitmap data and have access to it on a pixel level, then we are able to read the colors of each pixel in a byte array. However, a byte array is very long (1,600 characters of 0-255) it would be too overwhelming to the CPU to loop through all 1,600 numbers at 30 times per second, so I look for every 10th number in the array. If I detect any numbers, I allow for the clippings to fly around; if there is no data, the clippings cease. Again the effect isn't perfect, as you can see sometimes when you are erasing left to right.