If you are interested in Objective C programming this article a good start to explore:
Cocoa Chronicles #1: ActionScript vs. Objective C
If you are interested in Objective C programming this article a good start to explore:
Cocoa Chronicles #1: ActionScript vs. Objective C
Every year I spend two days sitting in the audience of the Flashforum conference (FFK) listening to great speakers and getting impressed by their experiments and thoughts. It’s also a good way to renew some of the basic knowledge in Flash development and of course to meet some friends in the Flash scene.
So this are most of my notes:
Flash / Flex development:
DisplayObject.width / height should be divisible by 2 as often as possible
Events and / or stop propagation as soon as possible
DisplayObject.mouseEnabled=false if possible
MovieClip animations when removed from stage
TextField.opaqueBackground=true if possible
final statement (final class ClassName {})
BitmapData.get / setVector()
HTML / JavaScript basics:
Useful workflow utils:
Almost every Flash project needs some embedded fonts and it is a good practice to compile the fonts into a separate SWF file. So here is a simple way to create a file that contains only embedded fonts. The SWF file will also show the exact internal font names:
Security.allowDomain( "*" ); // Step 1: Create new fonts in flash library // and select "Export for ActionScript". // Step 2: Run ONLY this code to evalute and trace the exact font names. /**/ var embeddedFonts : Array = Font.enumerateFonts ( false ); var c : uint = embeddedFonts.length; for ( var i : uint = 0; i < c; i++ ) { var font : Font = embeddedFonts[ i ] as Font; var className : String = font.fontName.split( " " ).join( "" ); var lowerFontStyle : String = font.fontStyle.toLowerCase(); if ( lowerFontStyle.indexOf( "bold" ) != -1 ) className += "Bold"; if ( lowerFontStyle.indexOf( "italic" ) != -1 ) className += "Italic"; trace( className ); } /**/ // Step 3: Assign the exact font names to the actual // library symbols and their export class name. // Step 4: Export the swf using ONLY this code. /**/ var posX : int = 10; var posY : int = 10; var embeddedFonts : Array = Font.enumerateFonts ( false ); embeddedFonts.sortOn( "fontName", Array.CASEINSENSITIVE ); var c : uint = embeddedFonts.length; for ( var i : uint = 0; i < c; i++ ) { var font : Font = embeddedFonts[ i ] as Font; var lowerFontStyle : String = font.fontStyle.toLowerCase(); var textFormat : TextFormat = new TextFormat(); textFormat.bold = ( lowerFontStyle.indexOf( "bold" ) != -1 ); textFormat.italic = ( lowerFontStyle.indexOf( "italic" ) != -1 ); textFormat.font = font.fontName; textFormat.size = 14; var className : String = font.fontName.split( " " ).join( "" ); if ( textFormat.bold ) className += "Bold"; if ( textFormat.italic ) className += "Italic"; Font.registerFont( Class( getDefinitionByName( className ) ) ); var boldItalic : String = ""; if ( textFormat.bold && textFormat.italic ) { boldItalic = "( needs to be BOLD and ITALIC ! )"; } else if ( textFormat.bold ) { boldItalic = "( needs to be BOLD ! )"; } else if ( textFormat.italic ) { boldItalic = "( needs to be ITALIC ! )"; } var textField : TextField = new TextField(); textField.autoSize = TextFieldAutoSize.LEFT; textField.defaultTextFormat = textFormat; textField.embedFonts = true; textField.text = font.fontName + "\t" + boldItalic; textField.x = posX; textField.y = posY; posY += textField.height + 5; addChild( textField ); } /**/
Just some helpful links:
Understanding the security changes in Flash Player 10
Policy file changes in Flash Player 9 and Flash Player 10
I did some research about using Amazons SimpleDB service within a Flash based application and found these basic facts:
So using Amazons SimpleDB for browser based Flash applications makes not much sense to me.
It might be more useful for Flash applications running on local machines like Flash projectors or Adobe AIR applications but there is still a security problem with hiding your AWS key.
Anyway, I found two ActionScript libraries that might be useful:
http://code.google.com/p/actionscript-simpledb-library/
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1365
And this thread in Amazons discussion forums:
http://developer.amazonwebservices.com/connect/thread.jspa?threadID=19698
I found a good explanation how to support HTTP authentication with URLRequests here.
That’s the most interesting part:
Best I can tell, for some reason, this only works where request method is POST; the headers don’t get set with GET requests.
Interestingly, it also fails unless at least one URLVariables name-value pair gets packaged with the request, as indicated above. That’s why many of the examples you see out there (including mine) attach “name=John+Doe” — it’s just a placeholder for some data that URLRequest seems to require when setting any custom HTTP headers. Without it, even a properly authenticated POST request will also fail.
You’ll almost surely have to modify your crossdomain.xml file to accommodate the header(s) you’re going to be sending. In my case, I’m using this, which is a rather wide-open policy file in that it accepts from any domain, so in your case, you might want to limit things a bit more, depending on how security-conscious you are:
<?xml version="1.0"?> <cross-domain-policy> <allow-access-from domain="*" /> <allow-http-request-headers-from domain="*" headers="Authorization" /> </cross-domain-policy>… and that seems to work; more information on this one is available from Adobe here).
Apparently, Flash player version 9.0.115.0 completely blocks all Authorization headers (more information on this one here), so you’ll probably want to keep that in mind, too.
So this little code snippet explains the basics:
// Base64Encoder contained in Flex SDK import mx.utils.Base64Encoder; // Encode username and password var base64Encoder : Base64Encoder = new Base64Encoder(); base64Encoder.encode( "username:password" ); // Create authorization request header var urlRequestHeader : URLRequestHeader = new URLRequestHeader( "Authorization", "Basic " + base64Encoder.toString() ); // URLRequest setup var urlRequest : URLRequest = new URLRequest( "url" ); // Needs to send some data!! urlRequest.data = new URLVariables( "name=John+Doe" ); // Only supported with POST method!! urlRequest.method = URLRequestMethod.POST; // Apply authorization request header urlRequest.requestHeaders = new Array( urlRequestHeader );
Just a quick note about working with DisplayObject.rotationX,Y,Z:
Keep in mind that your DisplayObject rotates around it’s center point. This may result in weird optics if you forget to align your DisplayObject properly.
Update: Well, there is much more to know!
There’s need for an DisplayObjectContainer with an properly assigned PerspectiveProjection.
Copy & paste this code and you’ll see what I’m talking about:
stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.addEventListener( Event.RESIZE, onStageResize ); function onStageResize( event : Event ) : void { draw(); } function createRectSprite( w : int, h : int, rotationY : Number, container : Sprite, useProjection : Boolean ) : Sprite { // 3D object var graphicSprite : Sprite = new Sprite(); graphicSprite.name = "graphicSprite"; graphicSprite.rotationY = rotationY; graphicSprite.buttonMode = true; graphicSprite.useHandCursor = true; // Make sure 3D objects content is centered var g : Graphics = graphicSprite.graphics; g.beginFill( 0, .5 ); g.drawRect( w * -.5, h * -.5, w, h ); g.endFill(); // 3D Container var containerSprite : Sprite = new Sprite(); containerSprite.addChild( graphicSprite ); // Apply projection to 3D Container instead of 3D Object if ( useProjection ) { var projection:PerspectiveProjection = new PerspectiveProjection(); projection.projectionCenter = new Point( 0, 0 ); containerSprite.transform.perspectiveProjection = projection; } // Visualize center g = containerSprite.graphics; g.beginFill( 0xff0000 ); g.drawCircle( 0, 0, 2 ); g.endFill(); container.addChild( containerSprite ); return containerSprite; } var left : Sprite; var right : Sprite; function draw() : void { while ( numChildren > 0 ) { removeChildAt( 0 ); } var container : Sprite = new Sprite() container.name = "container"; container.x = stage.stageWidth * .5; container.y = stage.stageHeight * .5; addChild( container ); var stepX : int = stage.stageWidth / 3; var w : int = 200; var h : int = 200; left = createRectSprite( w, h, -60, this, true ); left.name = "left"; left.x = stepX; right = createRectSprite( w, h, 60, this, true ); right.name = "right"; right.x = stepX * 2; left.y = right.y = stage.stageHeight * .5; } function onEventHitTest( event : Event ) : void { var containerSprite : DisplayObjectContainer; var graphicSprite : DisplayObject; containerSprite = this.getChildByName( "left" ) as DisplayObjectContainer; graphicSprite = containerSprite.getChildByName( "graphicSprite" ) as DisplayObject; trace( "hit left containerSprite:", containerSprite.hitTestPoint( mouseX, mouseY, true ) ); trace( "hit left graphicSprite:", graphicSprite.hitTestPoint( mouseX, mouseY, true ) ); containerSprite = this.getChildByName( "right" ) as DisplayObjectContainer; graphicSprite = containerSprite.getChildByName( "graphicSprite" ) as DisplayObject; trace( "hit right containerSprite:", containerSprite.hitTestPoint( mouseX, mouseY, true ) ); trace( "hit right graphicSprite:", graphicSprite.hitTestPoint( mouseX, mouseY, true ) ); trace( "" ); } stage.addEventListener( MouseEvent.MOUSE_DOWN, onEventHitTest ); draw();
Since I had to figure out some basics about local server development on my Mac, I really recommend these tools:
But one thing sucks: You have to set read/write access (in finder) for everyone. I wonder if that might cause system security problems?
And I strongly recommend to read this nice tutorial about setting up virtual hosts manually: http://www.sawmac.com/mamp/virtualhosts/
Firefox users probably know the Flashblock plugin and I just want to note a link to a similar plugin for webkit which works well with Safari.
http://rentzsch.github.com/clicktoflash/