Real 3D is coming to Adobe Flash Player

October 26th, 2010

read more at:

http://labs.adobe.com/technologies/flash/molehill/

Access totalFrames from an external loaded swf

August 30th, 2010

Use UILoader to load the external swf and on the INIT event we will be able to get the loaded swf total frames. Don't forget to drag the UILoader component (from the components panel, ctr+F7) into your library, and import fl.containers.*.

Actionscript:
  1. import fl.containers.*;
  2.  
  3. var swfLoader:UILoader = new UILoader();
  4. swfLoader.scaleContent = false;
  5.  
  6. swfLoader.addEventListener(Event.INIT, loader_init);
  7.  
  8. function loader_init(evt:Event):void
  9. {
  10.     var mc:MovieClip = swfLoader.content as MovieClip;
  11.     trace(mc.totalFrames)
  12. }
  13.  
  14. var urlReq:URLRequest = new URLRequest("to_be_loaded.swf");
  15.  
  16. swfLoader.load(urlReq);

I recently used this technique to build video like player (play, stop, seek) for swf's.

New match 3 puzzle game – Gems Swapping Knight

August 26th, 2010

I am releasing a new game (in-house build), Gems Swapping Knight

gems swapping knight

It's a classic match 3 gems puzzle game. In this version the engine only recognizes 3 gems in a row (not 4 or 5), in the future I do plan to change this and also add more fun stuff into the game like bombs. Initially it was planned as a demo for a potential client, but I soon realized that I would rather build the game for myself, and release it here.

The game is build using actionscript 3, it took me around 4 days to build a working version and several days to build the graphics and put it all together, all this while working on other projects. I am planning to release the source code in the future.

Here are the game instructions:

The goal of the game is to gain higher scores by matching three gems of the same color, vertical or horizontal. You can only move a gem up, down, left or right. When a chain of three gems is formed, they disappear, the gems on top fall down and the empty space is filled with random new gems.

Every 10 matches earns you a special coin. You use this coins to get a new mix of gems in the case you see that no more moves are possible.

To move the gems, you click on the gem you wish to swap, click again on the gem you wish to be swapped with or hold down your mouse, move your pointer over the gem to be swapped with, and release your button.

The game is over when you have zero coins and no more moves are possible.

Give Gems Swapping Knight a try !

Simple actionscript text animation engine

June 23rd, 2010

This is a very basic text animation engine, but it allows you to build your own animation styles and it's fairly easy to understand how it works.

Download the source file..

I developed this animation engine while working on the Semicolon Wars game. The whole purpose was to identify punctuations and blank spaces in any given sentence (it's a punctuation game). Once the function worked as I wanted, I realized that I can use this function as an animation engine.

How it works.

It takes the string you want to animate and for each character in the string it creates a new MovieClip that contains a dynamic TextField.

Actionscript:
  1. function animateText(textToAnimate:String, animationType:String){
  2.     var totalCharacters:int = textToAnimate.length;
  3.     for (var i:int = 0; i<= totalCharacters; i++)
  4.     {
  5.         var myChar:charMc = new charMc();
  6.         textContainer.addChild(myChar);
  7.         var mcRef:MovieClip = myChar as MovieClip;
  8.         mcRef.name = "myCharMc" + i;
  9.         myChar.letterText.autoSize = TextFieldAutoSize.LEFT;
  10.         myChar.letterText.text = textToAnimate.charAt(i);
  11.     }
  12. }

To create the charMc class, create a dynamic textfield (embed the font, set the Anti-alias for animation), name it "letterText". With the textfield selected hit "F8" (convert to symbol), type MovieClip, check the "Export to Actionscript" box and in the Class box name it "charMc".

Now we have to arrange the MovieClips x, y positions.

Actionscript:
  1. function animateText(textToAnimate:String, animationType:String)
  2. {
  3.     //clean up
  4.     while (textContainer.numChildren> 1)
  5.     {
  6.         textContainer.removeChildAt(textContainer.numChildren-1);
  7.     }
  8.  
  9.     var margin:int = 20;
  10.  
  11.     var cX:int = margin;
  12.     var cY:int = margin;
  13.  
  14.     var rightLimit:int = textContainer.width - margin;
  15.     var totalCharacters:int = textToAnimate.length;
  16.  
  17.     var metrics:TextLineMetrics;
  18.  
  19.     for (var i:int = 0; i<= totalCharacters; i++)
  20.     {
  21.  
  22.         var myChar:charMc = new charMc();
  23.         textContainer.addChild(myChar);
  24.         var mcRef:MovieClip = myChar as MovieClip;
  25.         mcRef.name = "myCharMc" + i;
  26.         myChar.letterText.autoSize = TextFieldAutoSize.LEFT;
  27.         myChar.letterText.text = textToAnimate.charAt(i);
  28.        
  29.         metrics = myChar.letterText.getLineMetrics(0);
  30.         if (cX> rightLimit)
  31.         {
  32.             cY +=  metrics.height;
  33.             cX = margin;
  34.             var reverCounter:int = i;
  35.             while (textToAnimate.charAt(reverCounter) != " ")
  36.             {
  37.                 reverCounter--;
  38.             }
  39.             for (var lb:int = reverCounter+1; lb <= i; lb++)
  40.             {
  41.                 var myMc:MovieClip = textContainer.getChildByName("myCharMc" + lb) as MovieClip;
  42.                 myMc.y = cY;
  43.                 myMc.x = cX;
  44.                 metrics = myMc.letterText.getLineMetrics(0);
  45.                 cX +=  metrics.width;
  46.             }
  47.         }
  48.         else
  49.         {
  50.             myChar.x = cX;
  51.             myChar.y = cY;
  52.             cX += metrics.width;
  53.         }
  54.         animateMc(mcRef, myComboBox.selectedItem.label, i*0.01);
  55.     }
  56. }

The metrics = myMc.letterText.getLineMetrics(0); does the trick we need to correctly space the movieclips.

To animate we create a simple animateMc function:

Actionscript:
  1. function animateMc(targetMc:MovieClip, animationType:String, delayAmount:Number){
  2.  
  3.     switch(animationType){
  4.         case "writeOn":
  5.         TweenLite.from(targetMc, 1, {alpha:0, ease:Linear.easeOut, overwrite:true, delay:delayAmount});
  6.         break;
  7.         case "flyIn":
  8.         TweenLite.from(targetMc, 1, {alpha:0, z:-500, ease:Sine.easeOut, overwrite:true, delay:delayAmount});
  9.         break;
  10.         case "3DSpin":
  11.         targetMc.visible=false;
  12.         targetMc.z = -500;
  13.         var myPath:Array = new Array();
  14.         myPath.push({z:-200, rotationX:randRange(-360, 360), rotationY:randRange(-360, 360), rotationZ:randRange(-360, 360)});
  15.         myPath.push({z:-400, rotationX:randRange(-360, 360), rotationY:randRange(-360, 360), rotationZ:randRange(-360, 360)});
  16.         Tweener.addTween(targetMc, {z:0, rotationX:0, rotationY:0, rotationZ:0, _bezier:myPath, time:3, transition:"easeoutquad", delay:delayAmount, onStart:tweenStart});
  17.         break;
  18.         case "randomColor":
  19.         targetMc.visible=false;
  20.         TweenLite.from(targetMc, 2, {tint:randomColors[randRange(0, randomColors.length)], rotationZ:randRange(-360, 360), ease:Linear.easeOut, overwrite:true, delay:delayAmount, onStart:tweenStart});
  21.         break;
  22.     }
  23.    
  24.     function tweenStart(){
  25.         targetMc.visible=true;
  26.     }
  27.        
  28. }

Thanks to the TweenLite and Tweener tween engines you can easily animate any MovieClip propriety (3D position, alpha, color, blur etc).

Get the source files and make some great animations on your own.

Customizable HTML Shoutbox

June 21st, 2010

The front end is html and css, powered by flash p2p and javascript

I just wanted to see if I can build a shoutbox/group chat app that has the front end build in html and styled with css. And here it is: Shoutbox/Chat in HTML, CSS, powered by JavaScript and Flash Player 10.1. Open a few of them in different windows to see how it works.

This technique would let any designer implement it's own front end looks via the CSS styling. Download the files from here and try a different look.

Here is the JavaScript functionality (located in the "shoutbox.js" file):

JavaScript:
  1. function onLoadedSwf(){
  2.      var flashobj = document.getElementById("flash_obj");
  3.      flashobj.focus();
  4. }
  5.  
  6. function onConnected(){
  7.  
  8.  var chatiframe = document.getElementById("chat_iframe");
  9. chatiframe.style.visibility = "visible";
  10. chatiframe.style.height = "300px";
  11.  
  12.  var shoutbox_elem = document.getElementById("shout_box");
  13.  shoutbox_elem.style.visibility = "visible";
  14.  shoutbox_elem.style.height = "80px";
  15.  
  16.  var flashobj = document.getElementById("flash_obj");
  17.   flashobj.style.height = "0px";
  18.  flashobj.style.visibility = "hidden";
  19.  
  20.    sendToJavaScript("connected", "");
  21. }
  22.  
  23. function getFlashMovie(movieName) {
  24.   var isIE = navigator.appName.indexOf("Microsoft") != -1;
  25.   return (isIE) ? window[movieName] : document[movieName];
  26. }
  27.  
  28. function sendMessage(value) {
  29.     getFlashMovie("flash_obj").sendToFlash(value);
  30.     document.getElementById('chatmessage').value = "";
  31. }
  32.    
  33. function sendToJavaScript(user, message){
  34.  
  35.  
  36.     var oIframe = document.getElementById("chat_iframe");
  37.     var oDoc = oIframe.contentWindow || oIframe.contentDocument;
  38.     if (oDoc.document) {
  39.         oDoc = oDoc.document;
  40.     }
  41.     oDoc.write("<br />" + user + ": " + message);
  42.    
  43.     oIframe.contentWindow.scrollTo(0, oDoc.body.scrollHeight);
  44.    
  45.     return true;
  46.  
  47. }
  48.  
  49. function onEnter(e){
  50. var keynum
  51. if(window.event) {keynum = e.keyCode} else if(e.which){keynum = e.which}
  52. if(keynum == 13){sendMessage(document.getElementById('chatmessage').value);}
  53. }
  54.  
  55. function onEnterUp(e){
  56. var keynum
  57. if(window.event){keynum = e.keyCode} else if(e.which){keynum = e.which}
  58. if(keynum == 13){document.getElementById('chatmessage').value = "";}
  59. }

Also here is the actionscript code.

Actionscript:
  1. const StratusAddress:String = "rtmfp://stratus.rtmfp.net/your-own-stratus-ley/";
  2. var nc:NetConnection;
  3. var netGroup:NetGroup;
  4. var user:String;
  5.  
  6. var messageIncrement:int = 0;
  7.  
  8. var myGroupName:String = "your-shoutbox-adress";
  9.  
  10. function connect():void
  11. {
  12.     conMc.visible = true;
  13.  
  14.     user = usr.text;
  15.     nc = new NetConnection();
  16.     nc.addEventListener(NetStatusEvent.NET_STATUS,netStatus);
  17.     nc.connect(StratusAddress);
  18.  
  19. }
  20.  
  21. function setupGroup():void
  22. {
  23.     var groupspec:GroupSpecifier = new GroupSpecifier(myGroupName);
  24.     groupspec.serverChannelEnabled = true;
  25.     groupspec.postingEnabled = true;
  26.     netGroup = new NetGroup(nc,groupspec.groupspecWithAuthorizations());
  27.     netGroup.addEventListener(NetStatusEvent.NET_STATUS,netStatus);
  28. }
  29. function netStatus(event:NetStatusEvent):void
  30. {
  31.     switch (event.info.code)
  32.     {
  33.         case "NetConnection.Connect.Success" :
  34.             setupGroup();
  35.             break;
  36.         case "NetGroup.Connect.Success" :
  37.             ExternalInterface.call("onConnected");
  38.             break;
  39.         case "NetGroup.Posting.Notify" :
  40.             receiveMessage(event.info.message);
  41.             break;
  42.     }
  43. }
  44.  
  45. function sendMessage(msg:String):void
  46. {
  47.     messageIncrement++;
  48.  
  49.     var message:Object = new Object();
  50.  
  51.     message.sender = netGroup.convertPeerIDToGroupAddress(nc.nearID);
  52.     message.user = user;
  53.     message.mi = messageIncrement;
  54.     message.text = msg;
  55.     message.action = "postChat";
  56.  
  57.     netGroup.post(message);
  58.  
  59.     receiveMessage(message);
  60.  
  61. }
  62.  
  63. function receiveMessage(message:Object):void
  64. {
  65.  
  66.     var removeBreakRegExp:RegExp = new RegExp("\n","gi");
  67.     var ms:String = message.text;
  68.  
  69.     ms = ms.replace(removeBreakRegExp,"");
  70.  
  71.     if (ms != "")
  72.     {
  73.         ExternalInterface.call("sendToJavaScript", message.user, message.text);
  74.     }
  75.  
  76. }
  77.  
  78. if (ExternalInterface.available)
  79. {
  80.  
  81.     try
  82.     {
  83.         ExternalInterface.addCallback("sendToFlash", receivedFromJavaScript);
  84.  
  85.     }
  86.     catch (error:Error)
  87.     {
  88.         ExternalInterface.call("sendToJavaScript", error.message);
  89.     }
  90.  
  91. }
  92.  
  93. function receivedFromJavaScript(value:String):void
  94. {
  95.     sendMessage(value);
  96. }
  97.  
  98. conBt.addEventListener(MouseEvent.CLICK, onConnectClick);
  99.  
  100. function onConnectClick(event:MouseEvent)
  101. {
  102.     connect();
  103. }
  104. usr.addEventListener(KeyboardEvent.KEY_DOWN, onEnterKey);
  105. function onEnterKey(event:KeyboardEvent)
  106. {
  107.     if (event.keyCode == 13)
  108.     {
  109.         connect();
  110.     }
  111. }
  112.  
  113. user = "user" + Math.round(Math.random() * 10000);
  114. usr.text = user;
  115. conMc.visible = false;
  116.  
  117. usr.addEventListener(MouseEvent.ROLL_OVER, focusOnUserName);
  118. function focusOnUserName(event:MouseEvent)
  119. {
  120.     stage.focus = usr;
  121.     usr.setSelection( 0, usr.length );
  122.  
  123. }
  124. stage.focus = usr;
  125. usr.setSelection( 0, usr.length );

Multiuser flash Whiteboard

June 21st, 2010

To view the app you will need flash player 10.1.

The Flash p2p Whiteboard, let's you:

  • Broadcast an image
  • Simple drawing
  • Text annotation
  • Simple group chat
  • Image, drawing and text annotations X, Y screen position sharing

Video:

How it works:

The whiteboard uses the new p2p flash player 10.1 NetGroup Class to connect app users and netGroup.post(message) to broadcast a message to the group.

Here is some of the code it uses:

Actionscript:
  1. const StratusAddress:String = "rtmfp://stratus.rtmfp.net/your-stratus-key/";
  2. var nc:NetConnection;
  3. var netGroup:NetGroup;
  4. var user:String;
  5. var messageIncrement:int;
  6.  
  7. var myGroupName:String = "your.app.group.name";
  8.  
  9. function connect():void
  10. {
  11.     nc = new NetConnection();
  12.     nc.addEventListener(NetStatusEvent.NET_STATUS,netStatus);
  13.     nc.connect(StratusAddress);
  14.  
  15. }
  16. function setupGroup():void
  17. {
  18.     var groupspec:GroupSpecifier = new GroupSpecifier(myGroupName);
  19.     groupspec.serverChannelEnabled = true;
  20.     groupspec.postingEnabled = true;
  21.  
  22.     netGroup = new NetGroup(nc,groupspec.groupspecWithAuthorizations());
  23.  
  24.     netGroup.addEventListener(NetStatusEvent.NET_STATUS,netStatus);
  25.  
  26.  
  27.     user = "user" + Math.round(Math.random() * 10000); // we need unique usernames
  28.  
  29.     userNameText.text = user;
  30.  
  31.     createDrawLayer(user); // creates the drawing layer based on the username
  32.  
  33.  
  34. }
  35. function netStatus(event:NetStatusEvent):void
  36. {
  37.     //trace(event.info.code);
  38.  
  39.     switch (event.info.code)
  40.     {
  41.  
  42.         case "NetConnection.Connect.Success" :
  43.             setupGroup();
  44.             break;
  45.         case "NetGroup.Connect.Success" :
  46.             txtChatMessages.text = "connected to group";
  47.             break;
  48.         case "NetGroup.Posting.Notify" : // fires each time a message is posted in the group
  49.             receiveMessage(event.info.message);
  50.             break;
  51.         case "NetGroup.Neighbor.Connect" :
  52.    
  53.             break;
  54.         case "NetGroup.Neighbor.Disconnect" :
  55.  
  56.             break;
  57.     }
  58. }
  59. function sendMessage():void
  60. {
  61.     messageIncrement++;
  62.  
  63.     var message:Object = new Object();
  64.  
  65.     message.sender = netGroup.convertPeerIDToGroupAddress(nc.nearID);
  66.     message.user = user;
  67.     message.rnd = messageIncrement;
  68.     message.text = txtMessage.text;
  69.     message.action = "postChat";
  70.  
  71.     netGroup.post(message);
  72.     incomingMessage(message);
  73.     txtMessage.text = "";
  74. }
  75.  
  76. function receiveMessage(message:Object):void
  77. {
  78.  
  79.     if (message.user != user)
  80.     {
  81.         if (message.action != null)
  82.         {
  83.             switch (message.action)
  84.             {
  85.                 case "postChat" :
  86.                     incomingMessage(message);
  87.                     break;
  88.                 case "clear" : // delete your own drawing across all users connected
  89.                     clearMc(message.user);
  90.                     break;
  91.                 case "postImage" :
  92.                     showGroupImage(message.image);
  93.                     break;
  94.                 case "postImagePozition" : // changes the position of the broadcasted image
  95.                     showGroupImagePoz(message.imageX, message.imageY);
  96.                     break;
  97.                 case "postTextField" : // creates the text annotation for all users in the group
  98.                     recreateTextField(message.txtObj);
  99.                     break;
  100.                 case "postTextFieldPozition" : // changes the position of  a text annotation
  101.                     pozitionTextField(message.txtMc, message.px, message.py);
  102.                     break;
  103.                 case "editTextField" : // function that edits the changes made to a text annotation
  104.                     editedTextField(message.txtName, message.txtContent);
  105.                     break;
  106.  
  107.             }
  108.         }
  109.     }
  110.  
  111. }
  112. connect(); // start the application