SWFObject, ExternalInterface and Internet Explorer

Posted in: ActionScript, JavaScript |

I was working on something earlier today, and became so frustrated with it that I just got up and went home early for the day.  I was very pleased with the work I had completed to this point, and as soon as I launched the dreaded Internet Explorer browser to 'test compatibility' ... I immediately threw my arms up in the arm and spouted out a handful of expletives.

I created a very simple Video player in Adobe Flex 2.0, and exposed all of its functionality through ExternalInterface so that a javascript framework I am working on could communicate with it -- allowing for 'media controllers' (play, stop, pause, forward, backward, rewind, progress, etc) could be rendered to the page using HTML and CSS.  I had the following general code in my Adobe Flex application:

Actionscript:
  1. ExternalInterace.addCallback('startPlayback', play);
  2. ExternalInterface.addCallback('stopPlayback', stop);
  3. // .... more calls for other events

I dropped a reference to my compiled SWF onto the page using the latest SWFObject 2.0, recently released on Google Code. I even back-ported it to the last 1.5 release on blog.deconcept.com, when it failed initially ... assuming, of course, that the 2.0 release was still 'buggy'.  I stood corrected.

I did some research, and found a few posts related to the issue, one that I found more or less 'ensuring' was Mihai Bazon's.  He basically stated that to accomplish the ExternalInterface integration to my page, I'd have to load my SWF's with the initial page ... well, this is sort of a 'oops, would have been nice to know this AHEAD OF TIME' thing, as it makes quite a few changes to the framework a requirement.  Especially since Flash Video's are going to be one of the driving forces to the end result.

So, with that ... Mihai suggests that you can load the SWF's dynamically still, if you load them into an IFRAME.  This seems like a logical solution, but I had another alternative idea ... which is to use Flash's LocalConnection system to 'relay' the events, and simply loading a small lightweight 'listening server' on the page at 'page load' which can be passed the 'destination' and the 'method' with 'arguments'.  Now, to pull this off, all dynamically loaded SWF's on the page would have to implement the same basic startup process ... Which would go something like:

Pass a static param into the 'listener server', this represents it's "LocalConnection Name" that it will listen on

Pass the same param into all the dynamically loaded SWF's that will 'attach' to the 'listener server'

Once the dynamically loaded SWF is done, in it's "creationComplete" it can simply connect to the 'listener server' and ask to be an event handler.

When you have javascript on the page that needs to execute some ActionScript in a dynamically loaded SWF, the Javascript can tell the 'listener server' and then the 'listener server' can basically 'relay' the information to the handler.

Now, I've only thought about this for a few minutes ... and I haven't tried to put it into practice, not sure if I can 'late bind' "external interface callbacks" with the "early-load" SWF ... or if all the "addCallback" methods have to be executed as part of the "creationComplete" process or not.  Knowing what I know so far of ActionScript and Flash, I'm thinking it's just some sort of a goofy limitation either with the Flash Player 9 Plugin ... or with the way Internet Explorer allows plugins access to the page's JavaScript run-time.

Either way, I'll probably be trying to put one of the two idea's into practice, as it will be a required feature set for the framework I'm building.

I'll write more about the final solution, and possibly some example code for those who may be struggling with the same issue.

Want to Advertise on this Site?

ActionScript Function Object - Know Who Called You!

Posted in: ActionScript |

I was working on what I thought would be a fairly simple solution, reusable code ... which wound up biting me in the ass shortly after implementing it. I forgot to take into consideration that Alert.show() is non-blocking and so my reusable code that was turned into a function ... failed to operate as I hoped it would. I came up with a really bad work-around which required the end user to perform the same action twice, now, last I checked ... the definition of insanity was doing the same thing multiple times, expecting different results each time ... so, I decided my 'insane solution' needed some work.

I looked around, thought it through and realized that ActionScript 3 (maybe even 2?) has a 'Function' object, which can basically store an instance of a function (most likely just a pointed to it, not a duplicate copy).

So, I had the following code:

Actionscript:
  1. private function canMove():Boolean {   if(!isValid) {
  2.      Alert.show("Your trying to move, but you cant ... do you want too?", "Can Not Move", (Alert.YES | Alert.NO), this, function(event:CloseEvent):void {
  3.        if(event.details == Alert.YES) {
  4.          isValid = true;
  5.        }
  6.      });
  7.      return false;
  8.    }
  9.    return true;
  10.  }
  11.  private function doSomething():void  {
  12.    if(canMove()) { /* do some more */ }
  13.  } 
  14.  
  15.  private function doAnotherThing():void {
  16.    if(canMove()) { /* do some more */ }
  17.  }

Well, this code worked fine ... but, as you can see ... the user had to initiate the action of calling "doSomething" or "doAnotherThing" twice ... once to make isValid true and once again to execute the 'do some more' code block. This was unacceptable. So I made the following changes:

Actionscript:
  1. private var lastAction:Function = null
  2.   private function canMove():Boolean {   if(!isValid) {
  3.      Alert.show("Your trying to move, but you cant ... do you want too?", "Can Not Move", (Alert.YES | Alert.NO), this, function(event:CloseEvent):void {
  4.        if(event.details == Alert.YES) {
  5.          isValid = true;
  6.          if(lastAction != null) { lastAction(); }
  7.        }
  8.      });
  9.      return false;
  10.    }
  11.    return true;
  12.  }
  13.  private function doSomething():void  {
  14.    lastAction = doSomething;   if(canMove()) { /* do some more */ }
  15.  } 
  16.  
  17.  private function doAnotherThing():void {
  18.    lastAction = doAnotherThing;   if(canMove()) { /* do some more */ }
  19.  }

And viola, problem solved ... 'canMove' would display an Alert and prompt the user, and the Alert's callback could re-execute the code for them ... perfect!

Want to Advertise on this Site?

Memory ala Adobe Flex

Posted in: ActionScript, Game Development |

I got bored this evening, so I whipped together a quick Memory game in Adobe Flex, more as a means to test some basic things ... like extending built-in controls (Image) and building out dynamic displays (the images don't exist in the MXML) and working with them through the event system (adding/removing them from the effect list). The card 'flip' is actually just a simple image.source = newSource (each Card has a 'front' and 'back' source).

Enjoy: http://projects.zoulcreations.com/games/FlexMemory/

Want to Advertise on this Site?

Adobe Flex - Enhanced DateField

Posted in: ActionScript |

Today, I ran into a small issue with the default DateField in Adobe Flex 2.0.1 (which also seemed to be an issue in Flex 3 MS3B2).  The issue was simply that I could not manually enter my date into the text field and was forced to select it from the PopUp DateChooser.  Normally, this wouldn't be a problem ... but when trying to select a date that is several years in the past or future, makes it quite hard. So, I took it upon myself to whip together this little component to use in my project.

It's still fairly new, but is entirely usable. Some things that are missing are validation and date 'string' formats.  Currently, the code requires the date to be entered in 'mm/dd/yyyy' format.  Although, it does accept 'mm/dd/yy' (assuming the first two 'yy' values are that of the current year).

So, here's the code ... feel free to use it as you like.

com.zoulcreations.flex.controls.DateField source:


XML:
  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3.         <![CDATA[
  4.             import mx.managers.PopUpManager;
  5.             import mx.controls.DateChooser;
  6.             import mx.controls.Alert;
  7.  
  8.             [Bindable] public var selectedDate:Date;
  9.             public var showToday:Boolean = false;
  10.  
  11.             [Embed(source="C:/Program Files/Adobe/Flex Builder 3/sdks/2.0.1/frameworks/source/mx/controls/DateChooser.png")]
  12.             [Bindable] private var chooserIcon:Class;
  13.  
  14.             private function onCreation():void
  15.             {
  16.                 if(showToday)
  17.                 {
  18.                     selectedDate = new Date();
  19.                 }
  20.             }
  21.             private function textChanged(event:Event):void
  22.             {
  23.                 var dp:Array = ti.text.split('/');
  24.                 if(dp.length == 3)
  25.                 {
  26.                     try
  27.                     {
  28.                         var m:int = int(dp[0]);
  29.                         var d:int = int(dp[1]);
  30.                         var ys:String = dp[2];
  31.                         var y:int = 1900;
  32.                         if(ys.length == 4)
  33.                         {
  34.                             y = int(ys);
  35.                         }
  36.                         else if(ys.length == 2)
  37.                         {
  38.                             y = int( (new Date()).fullYear.toString().substr(0,2) + ys);
  39.                         }
  40.  
  41.                         var dt:Date = new Date(y,m-1,d);
  42.                         selectedDate = dt;
  43.                     } catch(err:Error) { Alert.show(err.message, "Date Format Error"); }
  44.                 }
  45.             }
  46.  
  47.             private function chooserChanged(event:Event):void
  48.             {
  49.                 selectedDate = dc.selectedDate;
  50.                 //ti.text = formatDate(selectedDate);
  51.  
  52.                 hideChooser();
  53.             }
  54.  
  55.             private function formatDate(dt:Date):String
  56.             {
  57.                 var m:int = dt.month;
  58.                 var d:int = dt.date;
  59.                 var y:int = dt.fullYear;
  60.                 return (m + 1) + '/' + d + '/' + y;
  61.             }
  62.  
  63.             private var dc:DateChooser = null;
  64.             private function imgClicked(event:Event):void
  65.             {
  66.                 img.setFocus();
  67.                 if(dc == null) { showChooser(); }
  68.                 else { hideChooser(); }
  69.             }
  70.  
  71.             private function showChooser():void
  72.             {
  73.                 if(dc == null)
  74.                 {
  75.                     dc = new DateChooser();
  76.                     dc.selectedDate = selectedDate;
  77.                     dc.addEventListener("change", chooserChanged);
  78.                     PopUpManager.addPopUp(dc, this, false, null);
  79.                     dc.y = this.y + this.height + 4;
  80.                     dc.x = (this.x + this.width) - dc.width;
  81.                 }
  82.             }
  83.  
  84.             private function hideChooser():void
  85.             {
  86.                 if(dc != null)
  87.                 {
  88.                     PopUpManager.removePopUp(dc);
  89.                     dc = null;
  90.                 }
  91.             }
  92.         ]]>
Want to Advertise on this Site?

It’s Math, ala Adobe Flex

Posted in: ActionScript, Game Development |

For those of you who have seen my simple 'Its Math' application written in Torque Game Builder, here's a remake of it in Adobe Flex. The Adobe Flex version actually contains much more 'logic', but is no where near as 'pretty' looking (not that the TGB version was 'pretty' by any means ... haha).

http://projects.zoulcreations.com/games/ItsMath_Flex/

Want to Advertise on this Site?

Space Invaders ala Adobe Flex

Posted in: ActionScript, Game Development |

Ok, I had a really nice story written up, and then Mambo's Story Editor blew up and refreshed the page for no apparent reason.  So I'll keep this one short and simple.

http://projects.zoulcreations.com/games/FlexInvaders/

Above is a link to a Space Invaders clone written in Adobe Flex.  There are three components that make up this game, the Ship, Shot and Invader classes.  The Ship component is the player ship and has simple 'move left/right' functionality along with 'fire shot'.  The Shot component is the fiery bullet that the Ship shoots when you press the Spacebar.

The Invader class is fairly simple at this point, and contains little to no logic.  The Invaders are currently stale and do not move around the level.  This functionality was not required to accomplish my simple test, which was to see if Flex was a suitable game development environment.  So far, I'm thinking that is definitely has the potential to develop simple Flash video games ... not sure about it's ability to get more complex -- along with Flex's ability to load up SWF's 'on the fly' ... you could intermix Flash and Flex stuff to make the game more complex (visually).

So give it a try, and let me know what you think ...

Want to Advertise on this Site?