ASIDE- FP10
Thursday, May 15th, 2008Well kids, it’s here. Flash Player 10 beta is ready for you to take it out for a spin. Link here.
Well kids, it’s here. Flash Player 10 beta is ready for you to take it out for a spin. Link here.
I can’t decide which man I admire more: the guy behind the Bejeweled proposal or Richard Garfield.
The FIVe3D examples are starting to fly hot and heavy through the blogosphere, so here’s another contribution. This will probably be the theme of my new portfolio, but I was so impressed with the result that I had to post it. This will be perfect with a bit of scratchy 1920’s horn music.
Today I ran into what looks like an odd oversight in Adobe’s otherwise excellent BitmapData class. Alternatively, it could be an oversight in my otherwise excellent critical thinking skills. Neither is unheard of, but either way, someone is missing something somewhere.
Here’s the scenario: I had loaded an image via a Loader, and I wanted to capture a chunk out of the middle of it. For the sake of this example, let’s say I wanted a 200×200 square, starting at (50, 50) in the source image. So, foolishly and naîvely, I used this code:
// create the BitmapData and draw() the contents of sourceImage into it var bmpData:BitmapData = new BitmapData( 200, 200, true, 0x00000000 ); bmpData.draw( sourceImage, null, null, null, new Rectangle( 50, 50, 200, 200 ), true ); var bmp:Bitmap = new Bitmap( bmpData, PixelSnapping.ALWAYS, true ); // add to display list
So imagine my surprise when I got this:
![]()
This was definitely not what I was expecting, but apparently it is the intended functionality of BitmapData.draw(). I expected this image to line up with the upper left corner of the Bitmap container but as you can see, it doesn’t. It does indeed start copying pixels at (50, 50) on the source image, but when added to a Bitmap, it begins drawing those pixels at (50, 50) as well. That means that the whole thing is shifted 50 pixels along both axes, leaving empty space at the top and left while cutting off pixels at the right and bottom. This, to me, seems like a Bad Thing.
I’ve played with this for a couple hours now and I can’t find a way to do this without resorting to what I think most people would term a “workaround.” This is why I think that either Adobe just left out something, or (more likely), that I am just not grasping how this whole BitmapData/Bitmap thing works.
Anyway, this is my workaround. In my traversals of the AS help files, I noticed that there is a method that allows you to specify both things that I need: coordinates of a set of pixels on the source image, and coordinates for where to put said pixels on the target image. That method is BitmapData.copyPixels. However, it only works between two instances of BitmapData.
So, I created two instances of BitmapData. To make it easier to use, I placed it in a static class called BitmapGrabber.
public static function grab( source:DisplayObject, rect:Rectangle, smoothing:Boolean ): BitmapData { if( !source is IBitmapDrawable ) { throw new Error( "Cannot create BitmapData. Source must implement IBitmapDrawable" ); } var bmpData1:BitmapData = new BitmapData( source.width, source.height, true, 0x00000000 ); var bmpData2:BitmapData = new BitmapData( rect.width, rect.height, true, 0x00000000 ); bmpData1.draw( source, null, null, null, null, smoothing ); bmpData2.copyPixels( bmpData1, rect, new Point( 0, 0 ) ); bmpData1.dispose(); return bmpData2; }
And this is me using the class:
// create the BitmapData and draw() the contents of sourceImage into it var bmpData:BitmapData = BitmapGrabber.grab( sourceImage, new Rectangle( 100, 100, 100, 100 ), true ); var bmp:Bitmap = new Bitmap( bmpData, "auto", true ); // add to display list
And this is what I get:
![]()
It’s a ridiculously simple solution. However, I feel so strongly that BitmapData should have this capability (without a workaround), that I can’t shake the feeling that it must have this capability and I am just missing it. But, until some member of the Flash community tells me a better way to accomplish this, this is the class I’ll be using in my code.
UPDATE: I have another FIVe3D example/experiment (3D graphing) here. And, if you’re just cruising the web for FIVe3D examples, I have yet another one here.
I can’t seem to get enough of this FIVe3D thing. It’s even becoming natural to capitalize every letter except for that “e” when I write it. Not that I’m blinded to its faults, for there are a few here and there. But for quick 3D text rendering, I have yet to find its equal.
Take today’s experiment, for example. It was originally a Twitter viewer, but I haven’t figured out how to get it working online yet, so I’ve given it some generic text to render. It uses TweenLite for movement, and FIVe3D for rendering. Try clicking around and moving the mouse.
The part of this project that would have been challenging in PV3D or Sandy is the spacing of the letters. It was a great relief to find that FIVe3D is already intimately aware of each letter’s size, since it is rendering them as shapes. Thus, I didn’t have to painstakingly experiment to find the proper spacing.
Once I actually think up a clever tagline, I might just turn this into my site header. This could also be a pretty slick little tag cloud for site content, but I think it might get annoying if this was the only way to find a category. Ah well. A man can dream.
UPDATE
I did indeed turn this into my header. We’ll see how many people play with it.
UPDATE #2
And… I took it back out. Seems that something was weird with IE and Kimili Flash Embed. Or… it could have been user error.
UPDATE #3And… source code is live! With a tutorial/walkthrough, even! Get it here:
FIVe3D TextCloud: AS3 Tutorial and Source
UPDATE: For a more interesting and less useful FIVe3D example, see my other post here. And for yet another example that runs surprisingly well considering the sheer number of filters it uses, see here.
After some diligent research, I have compiled a list of things that impress me about Mathieu Badimon.
This last one in particular has gotten me excited today, because today I learned that he has released said 3D engine into the wild. Apparently he did this some time ago, but I only found out in the last few hours- and I, suffice it to say, am thrilled.
Here’s why I’m excited about this engine. Everybody in the community knows about Papervision3D, Away3D, or Sandy. There’s nothing new there. But all the development in those arenas seems to be in the direction of textured polygons, an area which holds limited appeal to me because of the limited power of the Flash Player. In general, I’ve found that nice smooth 3D vector effects that I want, I’ve had to bend Papervision to my will. Or, in some cases (such as text), I’ve never gotten a result I’m happy with.
So that’s why I’m thrilled about FIVe3D, which focuses on 3D vectors. Nice smooth lines, better text (although still not perfect), and no weird clipping issues that I’ve run into yet. It still seems to be pretty basic, and hopefully M. Badimon plans on continuing development, but what I see right now is pretty impressive. Here’s what I cooked up in about an hour. It’s a little rough, so forgive me- this is my first time with the engine. Reload the page to see the animation.
The subject matter is a little boring, but I think it will leave a certain potential client muchly impressed. Here’s the direct link, if you’d like to impress your own clients: FIVe3D.
Okay, this was hard for me to wrap my brain around, so let me summarize, in case anyone else is stuck on this. When developing in Flex, all the standard components let you specify a listener when you create them in MXML, like this:
<mx:Button id="someButton" click="handleClick( event );"/>Now when someone clicks on someButton, it calls the function handleClick(). Although not strictly best practice, it really is a nice little shorthand for adding an event listener to a Flex component. And since the Adobe components contain this functionality, people are used to it. If you have any plans of releasing your component into the wild, people will expect it to act like the components they already know and love.
Well, here’s how you do it: with the [Event] metadata tag.
1- First of all, the tag goes before the class declaration because it applies to the entire class. You can actually have more than one of these tags, for different events that you might broadcast. In my example, I have two, and they both broadcast ModelEvents.
// create the [Event] tags [Event(name="onLoad", type="com.pixelwelders.events.ModelEvent")] [Event(name="onLoadError", type="com.pixelwelders.events.ModelEvent")] // declare your class public class DataModel extends EventDispatcher implements IModel { ...
2- The type attribute refers to the actual type of event that this class broadcasts, package and all.
3- The name attribute refers to the string you use when you create a new Event of this type. You have to use an actual literal here; you can’t use a variable like ModelEvent.LOADED. So if you are dispatching an event like either of these:
dispatchEvent( new ModelEvent( ModelEvent.LOADED ) ); dispatchEvent( new ModelEvent( ModelEvent.LOAD_ERROR ) );
…you’ll need to check in your Event class to see what the actual value of LOADED or LOAD_ERROR is. In my ModelEvent class, I have:
public static const LOADED : String = "onLoad"; public static const LOAD_ERROR : String = "onLoadError";
Thus, my complete Event metadata tags are:
[Event(name="onLoad", type="com.pixelwelders.events.ModelEvent")] [Event(name="onLoadError", type="com.pixelwelders.events.ModelEvent")]
Of course, that’s only the first part of the equation. The second part is listening for the event, which thanks to our [Embed] tags, is now a piece of figurative cake. Here’s my Flex tag:
<model:DataModel
id="dataModel"
xmlURL="fileName.xml"
onLoad="handleModelLoaded( event );"
onLoadError=”handleModelError( event );”/>That onLoad and onLoadError attributes have the same value as your name attributes that you specified in step 3 above. Now put your two handlers in your Script tag, and they will be called any time those events are fired. Voilà.
A) In poker, a card that is the only one of its rank.
B) In animal husbandry, the sole surviving offspring of a litter.
C) In astrology, a single planet alone in a hemisphere (or some crap like that).
D) In mathematics, a set with only one member.
E) In England, a small village about 7 miles north of Chichester in West Sussex.
![]()
All of these things share a trait, and that trait is that each is the only one of its kind. If two kittens survive from a litter, neither one is a singleton. If a set has more than one number, it is not a singleton. In works the same way in object-oriented programming; a Singleton is a class that allows only one instance of itself; if there are more than one, that class cannot be a Singleton.
So why would one want a class that only allows one instance of itself? I can think of many applications. A ScoreKeeper class for your game, perhaps, or a Countdown class that keeps track of how much time you have to complete a level. In OS Wars I use a Singleton to keep track of all building resources currently in the game. There’s another one that keeps track of all the units on the battlefield. In fact, the Battlefield itself is a Singleton, because there’s no reason I would ever need more than one.
Another great thing about a Singleton is that, because there is only one, it’s very easy to get to. With a normal object, you have to worry about passing it around to the various classes that might need it. With a Singleton, that’s not necessary. All you need to do is import the class and voilà- there’s your Singleton.
![]()
It works this way because the class itself keeps a static reference to the only instance of itself. So instead of calling the constructor to get a reference to a new instance, you call the SingletonClassName.instance method to get a reference to the already-created instance. If that doesn’t make sense, here’s an example. This first piece of code is what a normal ScoreKeeper class would look like. With this structure, you can use that syntax that everyone knows and loves, new ScoreKeeper(), which returns a brand new ScoreKeeper every time it’s called.
package { public class ScoreKeeper { public function ScoreKeeper() { trace( "new ScoreKeeper" ); } } }
But suppose you wanted to ensure that there was only one ScoreKeeper, and you wanted to be able to easily access it from any location in your program. That means two things: A) the constructor can only be called once, and B) you need to keep track of the new ScoreKeeper that one time the constructor does get called. What good is having one instance of a class if you can’t get to it? So here’s the Singleton version of the above class:
package { public class ScoreKeeper { private static var _instance:ScoreKeeper; public static function get instance() { if ( !_instance ) { _instance = new ScoreKeeper(); } return _instance; } public function ScoreKeeper() { trace( "new ScoreKeeper!" ); } } }
There are two differences here: the static variable _instance and the static method get instance(). The _instance variable is where the actual instance of this class is stored. And the get instance() method, of course, enables you to access this instance. So to access this Singleton, you would use:
ScoreKeeper.instance;And to call any methods or properties of the Singleton, you would use this syntax:
ScoreKeeper.instance.addScore( 50 ); trace( ScoreKeeper.instance.score );
This of course assumes that your class has a public method called addScore() and a public property called score. You can get to any public methods or properties this way.
This also adds one more layer, called lazy initialization. Look in the get instance() method, and notice that before it returns a reference to the Singleton, it checks to see if that reference exists. If so, it simply returns it. If not, it creates it first and then returns it. Either way, you’re guaranteed to get the one existing instance.
There is one problem remaining- if you were so inclined, you could still call the constructor without going through get instance(), which would of course result in two Singletons. And as we discussed above, making two of something makes it not a Singleton anymore. So how can we prevent this? There are a few ways I’ve seen floating around, but the simplest is this:
package { public class ScoreKeeper { private static var _instance:ScoreKeeper; public static function get instance() { if ( !_instance ) { _instance = new ScoreKeeper(); } return _instance; } public function ScoreKeeper() { if ( _instance ) { throw new Error( "Singleton already exists- use get instance() to access" ); } else { trace( "new ScoreKeeper!" ); } } } }
The new lines are in the constructor. The get instance() method still only calls the constructor once, but if you forget it’s a Singleton and call the constructor later, you get a runtime error.
There are also a couple more complicated ways of ensuring that your Singleton is in fact a Singleton, but I haven’t lost too much sleep over over it. I usually even leave out the check in the constructor. Just remember that if it has _instance and get instance(), and a big comment up at the top that says “SINGLETON!”, it’s probably a Singleton.
The David Perry Game Industry Map has launched: link here. They claim to be tracking 10,000 organizations in 72 countries, so take a look around to see who’s in your neighborhood.
If you’re not clear on what a Singleton is, try glancing through my brief yet poignant article here: The Art and Beauty of Singletons.
Okay, so I’ve been putting together a little image-viewer component in Flex, and I wanted it to load one data model that all other components would share. Sounds like a job for a Singleton, right? However, I also wanted to instantiate said model from MXML, which adds some kinks. In fact, I’ve heard it said that it’s not possible at all. And after some trial and error, I found that apparently it is possible- you just have to hack around a little bit.
If you instantiate your class (or “component”) through MXML, Flex will automatically call its constructor. Typically, this is a bad thing because you don’t call constructors directly in Singletons- instead of calling a method that returns a new object (i.e. a constructor), you call a method that returns a reference to an already-created object (getInstance() or instance()). Flex won’t do that for you. However, this is not a deal-breaker. To make that class a Singleton, you just need to make sure that the constructor is only called once.
So, set up your Singleton like normal:
private static var _instance: DataModel = null; public static function get instance(): DataModel { return _instance; }
Then, in the constructor of said Singleton, add the following:
if ( !_instance ) { _instance = this; } else { throw new Error( "DataModel is a Singleton: only one instance allowed." ); }
All I’ve done here is move the creation of the Singleton from the get instance() method to the constructor. And if the constructor is called more than once, it throws an error. Now you can instantiate the class through MXML, just like any other component.
<model:DataModel
id="dataModel"
xmlURL="fileName.xml" />Meanwhile in Actionscriptland, you can refer to this instance of your class just like it was a normal Singleton:
trace( DataModel.instance ); // traces "[object DataModel]"
Plus, if you try to create another instance, be it through MXML or through ActionScript, you’ll get a good ol’ runtime error. You’ll have to wait until runtime to see it, but that’s certainly better than nothing, right?