18th November 2008

New MinimalComp: WheelNav

This is an idea I got from this article:

http://jonoscript.wordpress.com/2008/10/28/pie-in-the-sky/

I read it a while back, but was recently thinking of ways to make a decent 3D interface. Not an interface that is in 3D, but an interface that allows for rotating, scaling, and moving 3D objects. I've done all sorts of menus, toolbars, keyboard shortcuts, but it never was too usable. I thought this might be better. I'm not sure it will be better for that purpose, but at least I wound up with a cool component that will surely be useful for something.

Here's some demos. First with labels, like you see above. Just click anywhere. Drag to the item you want, and release.

And here with icons:

The use is a bit different, but pretty straightforward. When you create the menu, you need to specify the parent (usually best to place in main class so it's above everything), the number of segments, outer radius, icon radius, inner radius, and default select event handler. Actually, you only need to specify the first two. The rest have default params.

Actionscript:
  1. wheel = new WheelMenu(this, 8, 80, 60, 10, onSelect);

The number of items, and radii cannot be changed after creation. Hey, this is a minimal comp!

After creation, you add your items, specifying the index of the item, the icon or label, and any data.

Actionscript:
  1. wheel.setItem(0, "one", "one");
  2. wheel.setItem(1, "two", "two");
  3. wheel.setItem(2, "three", "three");
  4. wheel.setItem(3, "four", "four");
  5. wheel.setItem(4, "five", "five");
  6. wheel.setItem(5, "six", "six");
  7. wheel.setItem(6, "seven", "seven");
  8. wheel.setItem(7, "eight", "eight");

The second param is iconOrLabel. You can pass in an instance of any display object, or a class that extends DisplayObject and it will be used as an icon. Or you can pass in a string and a label will be created. No, you can't have a label and an icon. Again, this is a minimal comp, and the layout for that would open a big can of worms. Anyway, you could make your own class that contains a label and an icon and use that easily enough. So if you need both, there you go.

It's up to you to make sure your label isn't too long or your icon isn't too big. And use the iconRadius param of the constructor to adjust how close to the center it goes. A neat trick - you can even set iconRadius larger than outerRadius and your icons/labels will appear outside, around the menu.

To activate it, usually you want to listen for a MOUSE_DOWN event and call wheel.show(). It will automatically center itself on the mouse. Here's the code for the full example above:

Actionscript:
  1. package {
  2.    
  3.     import com.bit101.components.Component;
  4.     import com.bit101.components.Label;
  5.     import com.bit101.components.WheelMenu;
  6.    
  7.     import flash.display.Sprite;
  8.     import flash.events.Event;
  9.     import flash.events.MouseEvent;
  10.    
  11.     [SWF(backgroundColor=0xffffff, width=800, height=800)]
  12.     public class Playground extends Sprite
  13.     {
  14.         private var wheel:WheelMenu;
  15.         private var label:Label;
  16.        
  17.         public function Playground()
  18.         {
  19.             Component.initStage(stage);
  20.            
  21.             label = new Label(this, 10, 10);
  22.            
  23.             wheel = new WheelMenu(this, 8, 80, 60, 10, onSelect);
  24.            
  25.             wheel.setItem(0, "one", "one");
  26.             wheel.setItem(1, "two", "two");
  27.             wheel.setItem(2, "three", "three");
  28.             wheel.setItem(3, "four", "four");
  29.             wheel.setItem(4, "five", "five");
  30.             wheel.setItem(5, "six", "six");
  31.             wheel.setItem(6, "seven", "seven");
  32.             wheel.setItem(7, "eight", "eight");
  33.             stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
  34.         }
  35.        
  36.         private function onMouseDown(event:MouseEvent):void
  37.         {
  38.             wheel.show();
  39.         }
  40.        
  41.         private function onSelect(event:Event):void
  42.         {
  43.             label.text = "You chose item " + wheel.selectedItem;
  44.         }
  45.     }
  46. }

Download / checkout here:
http://code.google.com/p/minimalcomps/

posted in Components | 16 Comments

18th November 2008

Flash on the Beach Miami tickets on sale!

For those of you who have been unable to make it over to Brighton to Flash on the Beach, this may be your chance to get a taste of the awesomeness that is FOTB.

http://www.flashonthebeach.com

Tickets are on sale now, and the super early bird price for the first 199 tickets is just $299.

Less than three hundred dollars!!! For one of the best conferences you could go to! Un-freaking-believable!

Now if you look at the list of speakers, you're not going to see my name. Due to various potential scheduling situations, I couldn't make a commitment at an early date. But I just might hop on a plane at the last minute and go down there.

posted in Conferences | 2 Comments

17th November 2008

The Flash Platform is dead! Long live the Flash Platform!

Adobe announced, or TechCrunch announced, or Adobe will announce... um... anyway, there's this brand new thing called the Flash Platform now on Adobe.com:

http://www.adobe.com/flashplatform/

The Adobe® Flash® Platform is an integrated set of technologies surrounded by an established ecosystem of support programs, business partners, and enthusiastic user communities.

This is not to be confused with the Flash Platform that was announced by Macromedia several years ago. Not to be confused, because it's the same thing. Which is good, because I've been running the Boston Flash Platform User Group for 3 years now. Would be a shame if that meant something else now.

Some have reported that Flex is changing its name to the Flash Platform, but I don't really read it like that. In fact, this chart shows things very clearly:

I have to say though, that I'm really disappointed that Flex Builder is still Flex Builder. It's SUCH a misnomer. As Chuck said in the link above:

The product we knew as FlexBuilder has really just been a much more code-friendly way to build apps for Flash. This name-changing effort will clear up a lot of confusion, especially to those new to Flash that didn't quite understand how/why two differently named products ended up producing the same thing -- a SWF.

I wholeheartedly agree. I spend many, many, MANY hours a week using Flex Builder and the last time I did anything with Flex itself was... I don't remember. Some time this past summer I guess. It really should be Flash Builder, Flash Platform Builder, Adobe Builder, something else. I mean, look at that diagram above. It doesn't make sense at all. Flex Builder is the tool, tied to the Flex Framework by name. But it also does just about everything in that Client box too. Well, we'll see what they actually call it when Gumbo goes live.

posted in Flash | 31 Comments

14th November 2008

25 Line ActionScript Contest begins tomorrow

We have rules. We have judges. We have prizes.

Now we need code.

The contest begins at 12:00:01 a.m. tomorrow morning EST (GMT - 5).

Check it out.

posted in ActionScript, Flash | 23 Comments

10th November 2008

Deconstructing Flash 10 3D

In the comments of this post, Emanuele Cipolloni put forth the idea that Flash 10 3D is simply done behind the scenes using drawTriangles. That was a interesting realization for me. Made sense, so I decided to test it out. Basically, how would I create a 3D engine like Flash 10 3D using drawTriangles?

1. I'd get the bounds of an object as a rectangle.

2. Create a bitmap of that width and height and draw the object into it.

3. Transform the four corner points of the bounds using standard 3D formulas.

4. Use these transformed points as vertices for triangle drawing, and the bitmap as a bitmap fill.

Here's what I came up with. The image on the left (the only image you can see at first) is simply an imported bitmap in a movie clip sitting on stage. Click on it, and I do steps 1-4 repeatedly, drawing the triangles in the right part of the stage. The rotationY is increased on each frame.

Essentially, the same thing. The built in version is a lot smoother and cleaner looking, but I'm only using two triangles. And I think they are throwing some smoothing into the mix somewhere. (Perhaps even a slight blur???)

Here's the code. Beware, it's crappy, crappy, crappy code. Done on the train and bus on the way to work. Begs to be cleaned up, but I've proved my point and probably won't do much more with it unless I can think of some practical use for it.

Actionscript:
  1. var r:Rectangle = box.getBounds(box);
  2.  
  3. var bmpd:BitmapData = new BitmapData(r.width, r.height, true, 0);
  4. //var bmp:Bitmap = addChild(new Bitmap(bmpd)) as Bitmap;
  5.  
  6. bmpd.draw(box, new Matrix(1, 0, 0, 1, -r.x, -r.y));
  7. var rotY:Number = 0;
  8. var scales:Array;
  9. root.transform.perspectiveProjection.projectionCenter = new Point(200, 140);
  10.  
  11. var running:Boolean = false;
  12. stage.addEventListener(MouseEvent.CLICK, onClick);
  13. function onClick(event:MouseEvent):void
  14. {
  15.     running = !running;
  16.     if(running)
  17.     {
  18.         addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  19.     }
  20.     else
  21.     {
  22.         removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
  23.     }
  24. }
  25. function enterFrameHandler(event:Event):void
  26. {
  27.     tick();
  28. }
  29.  
  30. function tick():void
  31. {
  32.     var ry:Number = -rotY * Math.PI / 180;
  33.     scales = new Array();
  34.     var p0:Point = rotateY(r.top, r.left, ry);
  35.     var p1:Point = rotateY(r.top, r.right, ry);
  36.     var p2:Point = rotateY(r.bottom, r.right, ry);
  37.     var p3:Point = rotateY(r.bottom, r.left, ry);
  38.    
  39.     var vertices:Vector.<Number> = new Vector.<Number>();
  40.     vertices.push(p0.x + 600, p0.y + 140);
  41.     vertices.push(p1.x + 600, p1.y + 140);
  42.     vertices.push(p2.x + 600, p2.y + 140);
  43.     vertices.push(p3.x + 600, p3.y + 140);
  44.    
  45.     var indices:Vector.<int> = new Vector.<int>();
  46.     indices.push(0, 1, 3);
  47.     indices.push(1, 2, 3);
  48.    
  49.     var uvtData:Vector.<Number> = new Vector.<Number>();
  50.     uvtData.push(0, 0, scales[0]);
  51.     uvtData.push(0, 1, scales[1]);
  52.     uvtData.push(1, 1, scales[2]);
  53.     uvtData.push(1, 0, scales[3]);
  54.    
  55.     graphics.clear();
  56.     graphics.beginBitmapFill(bmpd);
  57.     graphics.drawTriangles(vertices, indices, uvtData);
  58.    
  59.     rotY += 3;
  60.     box.rotationY = rotY;
  61. }
  62.    
  63. function rotateY(xpos:Number, ypos:Number, a:Number):Point
  64. {
  65.     var x1:Number = xpos * Math.cos(a);
  66.     var z1:Number = xpos * Math.sin(a);
  67.     var foc:Number = root.transform.perspectiveProjection.focalLength;
  68.     var scale:Number = foc / (foc + z1);
  69.     scales.push(scale);
  70.     return new Point(x1 * scale, ypos * scale);
  71. }

posted in ActionScript, Flash | 11 Comments

8th November 2008

More on Flash 10 3D

One more problem you might run into with Flash 10 3D is when you rotate a display object in 3D. Display objects are perfect planes, which means they don't have any thickness. The old joke, "he's so thin that if he turns sideways you can't see him" can be taken literally when dealing with display objects, as you can see below:

Here, I'm just drawing a bunch of circles, while slowly rotating them on the y axis. As you see, the closer you get to 90 degrees, the less you see of the circle. Actually, I've arranged it so it never hits exactly 90 degrees, so you can still see a few pixels of the center circle. If you rotate something exactly 90 degrees AND view it head on, you won't see it at all.

But worse than just not seeing it is the degradation it goes through as it approaches that invisibility threshold. You can see the two circles on either side of the center one almost seem to be drawn with dotted lines.

Again, I'm not out to totally bash Flash 10. I think it's awesome that Adobe has finally put this into Flash, and for a first release, I'm thrilled. These are just things to keep an eye out for, and hopefully things that Adobe will take a look at improving in round 2.

posted in ActionScript, Flash | 13 Comments

8th November 2008

Flash 10 3D vs. “The Old Fashioned Way”

I've done tons of 3D in ActionScript over the years. I wrote 3 chapters about 3D in Making Things Move. I could code that kind of simple 3D in my sleep. When I say 3D, I'm not talking about the insane light map, bump map, texture map insanity that the likes of Andy Zupko and Ralph Hauwert get up to, but just scaling objects in a 3D space to give the illusion of depth.

So naturally, when Flash 10 came out with built in 3D, I was pretty excited. It offers just about the same level of stuff that I always do in code, but built in. Now instead of setting a focal length and making some new class to keep track of z, and calculating a scale value and a vanishing point, all that is done for me. Great!

But... maybe it's not so great. I've found that a lot of stuff that I do with Flash 10 3D just doesn't look as good as the stuff that I code by hand. The reason for this has to do with bitmaps. It seems that when you apply any 3D transformation to a display object, it turns it into a bitmap - same as applying filters. Unfortunately, this results in some pretty crappy results.

As an example, let's make a bunch of circles and randomly place them in 3D space. We'll use the same coordinates but do it once with Flash 10 3D, and once with hand-coded 3D. An interesting thing to note is that you can access perspectiveProjection.focalLength from the main container, and use that in your own 3D code with the exact formulas I gave in Making Things Move and get the exact same 3D projection. This really is a science!. Here's the code I'm using:

Actionscript:
  1. var h:Sprite = new Sprite();
  2. addChild(h);
  3. h.x = 400;
  4. h.y = 200;
  5.  
  6. var h1:Sprite = new Sprite();
  7. addChild(h1);
  8. h1.x = 400;
  9. h1.y = 600;
  10.  
  11. root.transform.perspectiveProjection.projectionCenter = new Point(400, 200);
  12. var focalLength:Number = root.transform.perspectiveProjection.focalLength
  13.  
  14. for(var i:Number = 0; i <100; i++)
  15. {
  16.     var s:Sprite = new Sprite();
  17.     s.x = Math.random() * 2000 - 1000;
  18.     s.y = Math.random() * 400 - 200;
  19.     s.z = Math.random() * 8000
  20.     s.graphics.lineStyle(0);
  21.     s.graphics.drawCircle(0, 0, 50);
  22.     s.graphics.endFill();
  23.     h.addChild(s);
  24.    
  25.     var s1:Sprite = new Sprite();
  26.     var scale:Number = focalLength / (focalLength + s.z);
  27.     s1.x = s.x * scale;
  28.     s1.y = s.y * scale;
  29.     s1.scaleX = s1.scaleY = scale;
  30.     s1.graphics.lineStyle(0);
  31.     s1.graphics.drawCircle(0, 0, 50);
  32.     s1.graphics.endFill();
  33.     h1.addChild(s1);
  34. }

I'm adding two containers: h and h1. Setting the vanishing point of the first to the center of the h container. Then drawing 100 random circles in each one, at the same location for each. This gives you the following picture:

Note that the two pictures geometrically, are exact duplicates. But the top one, done with Flash 10 3D had some really HORRIBLE artifacting. This is due to the fact that the circles are no longer represented as vectors, but as poorly scaled bitmaps. We can zoom in on them a bit:

Or even a bit more:

to see the problem. Note that the bitmap is regenerated each time you scale. The small circles in the full size image don't have nearly that resolution. If you control-scroll (on a Mac), or otherwise zoom your screen without using the Flash player's zoom in feature, you'll see it looks even crappier up close.

Contrast that with the handcoded version, which never stops being vector. Zoomed in all the way:

You can't actually tell how zoomed in you are. It's just vector circles.

Of course, the vector version looks a bit harsh as the far away circles are just as dark and crisp as the close up ones. But it's easy enough to apply a bit of aerial perspective. The easiest way to do it is use the calculated scale value to adjust alpha - either the alpha of the sprite itself, or the alpha of the line drawing it.

Adding this one line between lines 29 and 30:

s1.alpha = scale;

gives us this:

That's just a simple example. The best part about this handcoded 3D is that you can adjust the aerial perspective however you want. You can apply it directly as above, or just use that scale value in a more complex equation to change the dropoff. Or you can use it to apply a blur filter. Or change the color or width of the line you are drawing. In other words, you have complete control.

Another weird thing related to this Flash 10 3D rendering happened with these images at my other site, Art From Code:

These were all done with Flash 10 3D. All are done with an unbroken series of lines running left to right, and scaled back as a number of layers, using various sine wave expressions to affect the shape of the lines. But notice the holes. The tops of some of the curves got cut off. I left them that way, as it was an interesting effect, but it is really just an artifact, horrible enough to even be called a bug.

So, I'm not saying that Flash 10 3D is useless. It's fast and easy, and the examples here involve mainly line drawing, where the effect is massively amplified. If you are drawing straight fills or bitmaps, the effects may be barely noticeable. And there may be some way of compensating for this that I am not aware of. I've messed with cacheAsBitmap and LineScaleMode, and some other stuff, none of which seems to make any difference.

So all I'm saying is, don't throw out your old 3D code yet. Evaluate both methods and see which works best. I think it's great to spike ideas using Flash 10 3D and then make it look better by converting it to handcoded 3D. And, maybe it's something for Adobe to look at in Flash 11. :)

posted in ActionScript, Flash | 9 Comments

4th November 2008

Why do they call it Vector?

AS3 has a new type known as Vector, which is essentially a typed array. So you can say:

var myList:Vector.< Point > = new Vector.< Point >();

Now myList functions almost exactly like an array - has most of the same properties and methods as an array, but you can only put Point objects in it. And you can be sure that anything you get out of it is a Point. This allows the compiler to compile much more efficiently and your code to run much faster. All cool.

But I've heard a lot of people ask, "Why do they call it a Vector?"

I've always just said, well that's what they call it in other languages, like that is some kind of answer or something. But I finally decided to come up with a real answer.

So Vector means a few different things when you're doing programming. You have vector graphics, which define lines and curves instead of bitmaps, and you have vectors which define a magnitude in a specific direction. But neither one of those has anything to do with a typed array, do they?

Well, to find the answer, we go into linear algebra and matrices (matrixes if you prefer). So you know what a matrix is maybe. A two (or more) dimensional grid:

Turns out that a vector is a single row or column (one-dimensional) matrix:

See row vector or column vector.

Well, that's starting to look like an array. But still, why do they call a one-dimensional matrix a vector? Well it does go back to that definition of a magnitude and a direction.

Say you have a vector with a magnitude of 5, and an angle of something around 36.869. The x and y components of that vector would be 4 and 3 (if I got my math right). You could express this vector in a one dimensional matrix like so:

[4, 3]

Similarly, a 3-dimensional vector could be expressed in a matrix:

[x, y, z]

This site helps too:

http://www.kwon3d.com/theory/vectmat.html

So, a one dimensional matrix is a vector. And we borrowed the term in computer science, even though our vectors aren't always used to hold vectors and have many more elements than most vectors would normally have. That's the best answer I have. If I've screwed up too badly, I know there's a few smart people who read this blog who will correct me.

posted in ActionScript, Flash | 15 Comments

4th November 2008

What I DON’T like about Flash CS4

Just to give equal air time to my apparently scandalous post proclaiming how much I liked Flash CS4, let me say that it is not perfect and there are some things that bug me about it. Still, overall, an awesome release, but just to prove I'm not an Adobe robot, here we go. Note, these have to do with the OS X version. Not sure about Windows.

1. It takes a while to start up. The splash screen comes up and stays on top of everything while it launches, rendering your computer relatively useless while you wait for it to finish. No way to click on it or otherwise make it go away.

2. I love the new single window UI, but something odd happens all too often. Maximize the window, create a new FLA, then Cmd-S to save. A save dialog pops up from the bottom of the screen. Escape to close that window. The whole UI slides down about 1/4 way down the screen and you have to re-maximize it. Grrr.

3. I mentioned this before, but the live stage preview thing really irks me. Essentially, there's a Flash player running in the stage full time. Just create a new FLA and your CPU jumps up to an unacceptable level for a program that is sitting there doing absolutely nothing. Up to 12% for me. CS3 in the same situation is under 1% CPU use.

4. Window management needs a bit of work. It's not bad, but I have one workspace set up with just about everything closed but the Actions, Output, and Compile Errors panels, with the Actions panel taking up about half the screen. That's my "Code Monkey" workspace. And another workspace with tools and components and align/info/transform/color, etc. etc. showing. When I switch back and forth, about half the time the Actions panel in the Code Monkey workspace has minimized or is at least much smaller than I set it. Can't get it to stick the way I want it.

5. Library Panel. Various weirdnesses. If I close the library and reopen it, I often get something like 4 extra library panels opening up. WTF? Also, I feel that in the library list, the selected library item is not highlighted nearly obviously enough. It's really subtle. A slight shade of gray different from the unselected items.

6. Focus issues. I really often run into a case where I switch to another program such as Mail or Adium to check something, then click on Flash to go back to it. But Flash doesn't always get focus when you do this. I'll start typing something, thinking I'm typing into Flash, and instead I'm sorting my mail, or typing into an Adium window, or doing something random in some other application. Repeated clicks in the Flash UI absolutely refuse to give it focus. Only by Cmd-Tabbing to Flash does it get focus.

I suppose I should officially log these as bugs with Adobe, but I've been utterly unsuccessful in logging into the public bug base. Never sends me a confirmation email, then says I've already got an account, but my password is wrong, ask for new password, it never arrives. It's a long sad story. Hopefully someone at Adobe is listening and can either fix my bugbase account or log these things as bugs for me.

But again, overall, I love CS4. With these things fixed, I would love it even more.

posted in Flash | 33 Comments

4th November 2008

Mathographic Eggs

Lee Brimelow mentioned recently that he had picked up this book while in Singapore.

It looked pretty interesting, so I grabbed it off Amazon, and it does have some cool concepts in there. For me, it seems just about the right balance of explanation and open-endedness. It gives you some concepts and a gentle nudge and you're left to explore on your own.

Read the rest of this entry »

posted in ActionScript, Flash | 0 Comments

Who is reading BIT-101?