Archive for ActionScript

Flash’s Text Engine and it’s incredible behavior

It’s been a while since my last post concering AS3. I’m currently developing the HUD/GUI for awesay and yesterday, I came in contact with the new flash text engine for the first time.
For the HUD, I created a window, where I want to display a title centered on a sprite (horizontally, as well as vertically).

So, after reading some docs about how to create a simple line of text, I finally got it on the screen. To me, the process of creating such a simple line of text, seems horrific. However, you’re able to do a lot of nice things with the FTE, and the good old TextField won’t be improved in future, but is still supported. Because we want our HUD to be multilingual, I decided using the FTE would be a good choice. OK, I went a bit off-topic, so let’s get back to it.

How do I positon a simple line of text (flash.text.engine.TextLine) centered on a sprite? The horizontal positioning is easy, because it behaves like every DisplayObject, so we do it like this:

var sptMyTitleSprite:Sprite = new Sprite;
  1. sptMyTitleSprite.graphics.beginFill(0xDEDEDE);
  2. sptMyTitleSprite.graphics.drawRect(100, 25);
  3. sptMyTitleSprite.graphics.endFill();
  4. this.addChild(sptMyTitleSprite);
  5.  
  6. var tlSimpleTextLine:TextLine = myTextBlock.createTextLine(null, 100);
  7. sptMyTitleSprite.addChild(tlSimpleTextLine);
  8.  
  9. tlSimpleTextLine.x = (sptMyTitleSprite.width >> 1)(tlSimpleTextLine.width >> 1);

What I do in the code above, is creating a Sprite and draw a rectangle (100 width, 25 height) onto that Sprite. After adding the Sprite onto my displayList, I create my textLine from a TextBlock(not defined in the code above), and finally add the textLine onto my Sprite. When this is done, the textLine’s x-position is centered with the calculation(bitShift by 1 is a simple divison by 2, where the result is an integer).

Ok, that wasn’t too hard, it’s something I do very often. Well, I thought positioning the title in the vertical center of my Sprite is even that simple – Naaah, it’s not! Did you really thought it was that simple, hrhr :D

  1. tlSimpleTextLine.y = (sptMyTitleSprite.height >> 1)(tlSimpleTextLine.height >> 1);

That does not work. The 0, 0 Point of a TextLine (Roman) is always on the very left of the baseline.
TextLineDiagram
(I catched this image from the Adobe docs).

This behaviour causes the main part of our textLine to be in the negative y-direction(up) of it’s DisplayObject. The Adobe-People may again have smoked one pipe too much while coding this ;-) just kidding!
So when I calculate the vertical center of the Sprite (sprite.height >> 1), and I position the textLine at that position, it will nearly be centered, because it’s baseline is now at y: (sprite.height >> 1).
What we have to do, to position it at the absoule center, is subtracting the half of the textLine’s decent-value. That is everything what’s below the baseline. For example the lower parts of “j, g, y”.
The final solution will be:

tlSimpleTextLine.y = (sptMyTitleSprite.height >> 1) - (tlSimpleTextLine.descent >> 1);

I wrote this post, because I didn’t find any solution to this in the net. This will hopefully help other people.

awesay.com – presentation website online

badnoob.com just published the presentation website of our project awesay.
awesay is going to become a virtual, interactive shoppingmall in 3D!

Visit http://www.awesay.com (German language only)

company blog started

I just wan’t to inform my visitors that we (my company badnoob.com) has started it’s own blog. Main topics are our new Flash 3D-Engine, which is currently under heavy development, and also our project called “awesay” – more information can be found on the blog: http://blog.badnoob.com

Flash’s internal functions scuk!

yeah, it’s not a typo in the title, but it’s almost true!
Flash’s own functions and/or method are slow as I can say. I first noticed this while having a look at TweenLite’s easings.
Math.pow is slow. It’s faster doing x * x * x and so on – yeah really! Don’t believe me? Give it a try!
I assume this behaviour not only to sin, cos and other trigonometric functions (as already found out to be right by polygonal labs), but also to Flash’s own graphics-library.
So I’m on trip atm where I’ll do EVERYTHING myself. I’ve already done a small Bitmap-based Font-Engine, Textfields, unbelievable fast OBJ-Parser and a lot of more stuff… just wanted to let you know this :D (if anyone reads this at all – I dunno)

I also think about y everyone doing flash 3d on this planet, uses sin/cos and so on with radians, instead of creating a lookup-table “once”. horrific – it’s just that what’s done in code these days… ugly code! ever had a look at papervision, away3d, and some more google code project? blehyawk.
enough for know – have a nice day :)

ListenerProxy v2

I just found some improvements on my ListenerProxy-Class and packed them into a new “Version 2″. I also added a license-information. You can get the new Version 2 of ListenerProxy here.

Updated List of References

I updated the List of References, because the link to the old version of the HugoBoss Flash-Shop was incorrect.
Check it out: List of Refrences

ListenerProxy::BUGFIX

I updated the ListenerProxy-class, because I detected a bug with adding/removing multiple listeners to multiple objects.
I also removed duplicate entries of “if(objToAdd.hasOwnProperty(‘addEventListener’))”

Get the newest version[v1.3.4-stable]: ListenerProxy

Add methods to native Classes in ActionScript 3.0 – Prototype functions

Hi again!
Yesterday I’ve found out a cool new feature of ActionScript 3.0. You will sometimes have to use associative Arrays. The problem with these is that you can’t easily loop through them with a for-loop like

  1. var    myAssocArray:Array = [],
  2.         i            :int,
  3.         intLength    :int;
  4.  
  5. myAssocArray['foo'] = 'one';
  6. myAssocArray[1] = 'two';
  7. myAssocArray['bar'] = 'three';
  8. myAssocArray[0] = 'four';
  9. intLength = myAssocArray.length;
  10.  
  11. for(; i< intLength; ++i)
  12. {
  13.     trace(myAssocArray[i]);
  14. }

The trace will probably print out “four, two, undefined, undefined”. The fact is that you can get the elements 0 & 1 via the variable i, but the the other keys can’t be accessed with this method.
As I also like PHP very much, I also know the function array_keys(array) of PHP, which returns the key-values of the array given in the parameters. I thought that I really need this functionality within AS3, so I tried a lot, searched the internet and finally got it! It’s pretty simple for those knowing AS2 – prototype functions.
What do we need to do? Place the following code in your main, unnamed package below or above the class-definition and you can use it everywhere else in the code:

  1. package
  2. {
  3.     public class foo
  4.     {
  5.         public function foo():void
  6.         {
  7.             trace('bar');
  8.         }
  9.     }
  10.    
  11.     Array.prototype.arrayKeys = function():Array
  12.     {
  13.         var    arrReturn    :Array = [],
  14.             strKey        :String;
  15.  
  16.         for(strKey in this)
  17.         {
  18.             if(typeof this[strKey] == 'function') continue;
  19.             trace('in Array:: value->'+ strKey +' typeOf:'+ typeof strKey +' proto:'+ ((this[strKey] !== false) ? typeof this[strKey] : 'NULL'));
  20.             arrReturn[arrReturn.length] = strKey;
  21.         }
  22.  
  23.         return arrReturn;
  24.     }
  25.    
  26.     Number.prototype.give = function():String
  27.     {
  28.         return 'Number::giveItToMeBaby';
  29.     }
  30. }

You can now use this method to get the keys of the variable:

  1. var arrKeys        :Array = myAssocArray.arrayKeys(),
  2.     i            :int,
  3.     intLength    :int = arrKeys.length;
  4.  
  5. for(; i < intLength; ++i)
  6. {
  7.     trace(myAssocArray[arrKeys[i]]);
  8. }

Pretty easy, isn't it? Well, it is easy because the native Array-Class is dynamic, but what do we do with Number (final class)? Let's see...

  1. var num:Number = 4;
  2. num.give(); //doesn't work! final class, can't add methods to it?
  3.  
  4. num['give'](); //does work :) you can dynamically add methods to a class even if it's final; problem is that this code is hard to read, but it actually works

So far...
Daniel

ActionScript 3.0 ListenerProxy goes public

Hello everybody!
Since February I wanted to put my great ListenerProxy-class onto the page, but I forgot it every day… So now I’m here and remembered that there was a Class to publish!

Hey Daniel, tell me what the heck is a ListenerProxy and why did ya write that piece of code man? Let’s go on…
Since ActionScript is enourmously memory-consuming, I often tried to get rid of this. Once I found out that you can’t remove any objects that are still having a Listener registered on them. So what do you have to do, to get an object out of the memory? Setting the value to null or probably 0 (ints and so on), doesn’t seem to do the trick. You also have to remove the EventListeners – and of course – ALL of them!
Some time ago in an old Flash CS3-Version, you could find a listeners-Array of every object when you debugged the movie, but you can’t access this array – no way!
Well that was really annoising me, so I decided to write a class that keeps track of all the listeners registered on an object.

So what else can we do with your ListenerProxy, Daniel?
You probably already had some code where you needed to add multiple Listeners with the same callback-function. You then had to write code like this:

  1. var myLoader:Loader = new Loader();
  2.     myLoader.addEventListener(Event.COMPLETE,                this.loadHandler);
  3.     myLoader.addEventListener(IOErrorEvent.IO_ERROR,        this.loadHandler);
  4.     myLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS,    this.loadHandler);
  5.     myLoader.addEventListener(ProgressEvent.PROGRESS,        this.loadHandler);

This are four lines of code for the listeners…. Wanna do it within a single line? Watch this:

  1. ListenerProxy.getInstance().addListener(myLoader, [Event.COMPLETE, IOErrorEvent.IO_ERROR, HTTPStatusEvent.HTTP_STATUS, ProgressEvent.PROGRESS], this.loadHandler);

You can of course add a single Listener for a object, just pass the type as second parameter without the brackets:

  1. ListenerProxy.getInstance().addListener(myLoader, Event.COMPLETE, this.loadHandler);

Ok that’s nice, isn’t it? So you have multiple objects to listen for the same Event calling the same callback-function? Hmmm….

  1. var myLoader_1:Loader = new Loader();
  2. var myLoader_2:Loader = new Loader();
  3. var myLoader_3:Loader = new Loader();
  4. var myLoader_4:Loader = new Loader();
  5.     myLoader_1.addEventListener(Event.COMPLETE,    this.loadHandler);
  6.     myLoader_2.addEventListener(Event.COMPLETE,    this.loadHandler);
  7.     myLoader_3.addEventListener(Event.COMPLETE,    this.loadHandler);
  8.     myLoader_4.addEventListener(Event.COMPLETE,    this.loadHandler);

Argh*!$# I hate such crappy code :)

  1. ListenerProxy.getInstance().addListener([myLoader_1, myLoader_2, myLoader_3, myLoader_4], Event.COMPLETE, this.loadHandler);

Yeeehaa! It makes the whole thing a bit easier, don’t you think so?

And that’s not all. If you have multiple objects with multiple listeners and the same callback-function, you can simply pass the elements as arrays as shown above.

So what are the key-functions to use?

  1. 1. ListenerProxy.getInstance():ListenerProxy //Singleton-Pattern is used
  2. 2. addListener(objToAddTo:*, strListenerType:*, funcCallback:Function):void //to add Listeners
  3. 3. removeListener(objToRemoveFrom:*, strListenerType:*, funcCallback:Function):void //to remove Listeners
  4. 4. hasListener(objToAsk:*, strListenerType:String, funcCallback:Function = null):Boolean //check whether the specified object has that listener or not
  5. 5. pop(objToPop:*, blnRemoveAllListeners:Boolean = false):* //remove the object from ListenerProxy's Dictionary (the 2nd param is VERY USEFUL!)

Get the Code here!

[UPDATE]

::06th August 2009 { fixed bug with adding/removing multiple listeners to multiple objects; also remove duplicate entries of “if(objToAdd.hasOwnProperty(‘addEventListener’))” }

[/UPDATE]

if-statements – checking strings for being null

hello again!
Yesterday I wrote some code again and had to check if a String is null or not. The check was performed in a for-loop.
Below is some example code:

public var arrToFill:Array = [];
  1. [some more code here …]
  2. private function foo():void
  3. {
  4.   var i:uint;
  5.   for( i = 0; i < 10; ++i)
  6.   {
  7.     if(!arrToFill[i])
  8.     {
  9.       arrToFill[i] = '';
  10.     }
  11.   }
  12. }

This function was called different times and I wondered, that the if-statement returned false everytime.
For me it was theoretically correct that an Array-Element with a value of ” is not empty, because ” is an empty String for me, but it is something.
ActionScript3 doesn’t work like that, so for AS3 a String with a value of ” is equal to null or 0.

Conclusion:
If you have code like this and want to preallocate an element, just set it to 1. Then you can do a simpy

if(!arrToFill[i])

and everything would be fine.