Goodbye 2012

Well that’s another year over and it’s been a hugely satisfying one. I’ve also just realised that I’ve kept this blog going for just over three years now, which I’m actually pretty damn proud of. You may have noticed that I haven’t blogged as frequently this year. That’s intentional as I wanted to focus more on writing good quality tutorials rather than just feeding you guys community news that can be found anywhere else.

I thought I’d take the opportunity in this post to recap my achievements over the past 12 months and to see how close I came to actually accomplishing the goals I set myself at the start of the year.

Flash iOS Apps Cookbook

February saw the release of my Flash iOS Apps Cookbook, which I’d spent the majority of 2011 writing. It was real labour of love for me and something I put every ounce of energy and time into. To be honest, it left me completely exhausted but the response from the community has been fantastic and I’m quite chuffed that it has currently received 5-star ratings on Amazon from everyone who has reviewed it.

I also decided to spend the remainder of the year supporting the book via this blog by releasing material that didn’t make it to print. There were various reasons that content had to be dropped, but it was mostly down to the fact that I had a page count to stick to. I’ve made it available in the Additional Material/Tutorials section of my support page where you can also find two whole chapters that were dropped at the last minute.

I also get frequent emails from those who have read the book, which has been great as I get to see all sorts of interesting iOS projects that they’ve gone on to create. So a big thanks to everyone who has contacted me.

I might continue to push out additional material this year but it really depends on my time and how much effort is required to get some of the stuff to an acceptable standard. Quite a lot of the remaining material didn’t make it past the initial draft stages so will need some work.

Other Publications

I was also given the opportunity to write a few magazine articles over the past 12 months. It wasn’t something I’d done before and enjoyed the experience. I wrote a few Starling Framework tutorials for Flash & Flex Developers Magazine, and also an introduction to CreateJS and JavaScript. I was also asked to be section editor for an issue of Software Developer’s Journal, which was good fun. In fact, for SDJ I managed to bag an interview with Daniel Sperl, the author of Starling. It was great getting the opportunity to speak to Daniel about Starling and the Flash platform in general.

Match Mee for iOS

At WeeWorld we released Match Mee, our first Adobe AIR-based iOS game. This was a huge deal for me personally as until that point all our mobile content had been written using either Objective-C or Java. I’ve certainly got nothing against either language, but considering the Flash expertise we have in-house it always seemed odd that we hadn’t utilised it on mobile.

It became clear at the beginning of 2012 however, that Adobe AIR had matured to the point where it was a more than viable mobile development technology. Adobe had done a great job of getting the performance there on lower-end devices and there were more than enough native extensions out there to plug any holes in the AIR API.

We’ll probably spend a few months adding some updates to Match Mee and there’s also the chance we’ll be pushing out an Android version too. The fact that we can publish to both iOS and Android is obviously a very strong reason for using AIR and ActionScript 3 in the first place.

Other Programming Languages

I certainly didn’t restrict myself to Flash and ActionScript over the past 12 months. One of my goals for 2012 was to look more closely at HTML5 and JavaScript. To that end I worked on a handful of small projects, some of which found their way onto this blog. Plus, I also wrote a few HTML5 tutorials, both on my blog and elsewhere. Some of the projects were ports of previous ActionScript work I’d done such as the Monster Dash styled scroller, and my speedometer app. A few others used the excellent CreateJS framework.

I also spent a few weeks in June doing a spot of C programming. It’s been many years since I wrote any serious C or C++ code so thought I’d spend some time proving to myself that I could still write in it 🙂 Nothing came of it that was worth blogging about but I’m hoping to spend a bit more time with C/C++ this year again.

Reading List

I had quite a few technical books on my reading list last year. I didn’t get through them all but did manage to find time for a couple of Flash books including Thibault Imbert’s excellent Introducing Starling. I also spent a few days working through Box2D for Flash Games by Emanuele Feronato, which I’ll write a proper review of soon. Emanuele runs a really great Flash games blog, which you should check out.

Outside of Flash, I spent some time tinkering with Unreal Development Kit and found Unreal Development Kit 3 Beginner’s Guide by Richard Moore to be a decent introduction. I also got about a quarter way through Unreal Development Kit Game Programming with UnrealScript: Beginner’s Guide before I got distracted by other things. Hopefully I can pick that book back up this year.

Looking Forward to 2013

So I managed to tick quite a few boxes this year. The only disappointment was that I didn’t get to spend as much time learning 3D games programming. It’s something I tell myself every year that I’m going to seriously look at then get distracted by one thing or another. Maybe this year.

In my next post I’ll outline my rough plans for 2013.

Have a very HTML5 Christmas

At WeeWorld we rely quite heavily on the Flash runtime and its excellent vector renderer. However for toady’s post I thought it would be fun to use the Toolkit for CreateJS to export some of our Flash assets to HTML5. Of course, the assets are of no use whatsoever on their own, so I rolled up my sleeves and bashed out a quick JavaScript Xmas themed WeeMee builder.

So, to get yourself into the festive spirit, simply find a suitable xmas jumper and apply a splash of colour to it. There’s a nice little magnifying glass on the bottom-right of the screen if you need to take a closer look at all the vector goodness that makes up each of our WeeMee assets. Have a great Christmas and New Year folks!

Flash Player Success Stories

Recently I wrote about several Adobe AIR success stories for iOS. For today’s post I thought I’d focus on the Flash Player and point out just how advanced Flash gaming in the browser has become. Just over a year ago, Adobe introduced access to the GPU via the Stage3D API. Let’s take a look at a few high-profile titles that take advantage of all this hardware accelerated goodness.

FarmVille 2

Stage3D’s potential is huge and it looks like the boys and girls at Zynga have done a great job of showing just what the Flash platform can now produce within the browser. FarmVille 2 takes the game mechanic from the original but now renders everything in glorious 3D. Even on fairly modest hardware the results are very impressive.

If you’re considering getting into 3D programming with Flash then there are many available 3D frameworks built on top of Stage3D. However deciding which one to use can be a problem. Zynga opted for Flare3D and its suite of tools. I’m sure you’ll agree that FarmVille 2 does a great job of demonstrating what can be produced with Flare3D.

Angry Birds Star Wars

I don’t think there’s single person on this planet who doesn’t know what Angry Birds is. The iOS hit made its web debut last year thanks to Stage3D and the Starling Framework, and it’s back once again with this really amazing Star Wars edition.

Developers Rovio once again opted for the Flash Platform for their second Angry Birds Facebook offering. The excellent Starling Framework was employed as the game’s rendering engine.

Ruby Blast

There are tons of match-three games out there and Zynga’s Ruby Blast is an excellent example of the genre. Tap sequences of coloured gems to blast your way underground. The deeper you get, the more time you earn to prolong each game and increase your score.

Powered by Stage3D and the Starling Framework, Ruby Blast is another excellent example of what Flash is capable of these days. There’s also an Adobe AIR port of Ruby Blast for iOS.

CityVille 2

I’ve already mentioned FarmVille 2, but there’s also CityVille 2, which is definitely worthy of some of your gaming time. Similar to the classic Sim City game, it’s your job to build and manage your own city.

As with FarmVille 2, Zynga decided to build CityVille 2 using Flare3D. Once again, performance is excellent and it really is hard to believe that we’re now seeing content this rich running within a web browser.

Creating a Custom Virtual Keyboard

Although AIR for iOS offers access to the iOS virtual keyboard, you have limited control over the type of keyboard that appears. If you want additional keyboard configurations within your Flash project then you’ll need to build your own custom keyboard component. Although this will require some development effort it will allow you to tailor the user experience. For certain apps such as games, you may actually find a custom keyboard is the preferred option, as it will better fit your visual design.

Let’s see how to create one using Flash.

Flash iOS Apps CookbookThis tutorial is a previously unreleased recipe from Flash iOS Apps Cookbook and supplements the content found in Chapter 7, Working with Text and the Virtual Keyboard.
Flash iOS Apps Cookbook provides the recipes required to build native iOS apps using your existing knowledge of the Flash platform. Whether you want to create something new or simply convert an existing Flash project, the relevant steps and techniques are covered, helping you achieve your goal.

Getting Ready

An FLA has been provided as a starting point.

Download this recipe’s accompanying source bundle and open chapter7/recipe8/recipe.fla into Flash Professional.

The visuals for this application have already been created. Sitting on the stage is a virtual keyboard and a dynamic text field. The text field will be used to output what the user types.

The dynamic text field has been named field while the movie clip instance that represents the virtual keyboard has been named keyboard.

Entering a player's name with a custom virtual keyboard.

With the Selection tool (V) selected, double-click on the keyboard instance to examine its timeline. The keyboard contains 28 keys – 26 for the letters of the alphabet, an ok key for when the user is finished typing, and a del key to delete a character. You’ll find that each alphabetic key is represented by its own movie clip and that the instances are named a_key to z_key. This naming convention makes it easy to determine the letter that a key represents by simply examining the first character of its instance name. The remaining two keys have instance names of ok_key and del_key. Additionally there’s a movie clip named surface that sits beneath the keys and represents the keyboard’s body.

Double-click on any one of the keys to examine its timeline. Each is represented by two frames, where the second frame will be shown when the key is being pressed. The movie clip symbol for each key is linked to a class named Button, which was introduced in the Handling user interaction recipe from Chapter 4. Open Button.as and familiarize yourself with the code.

How to do it…

Perform the following steps.

  1. From Flash, select File | New and create a new ActionScript 3.0 class. Name it VirtualKeyboard.
  2. Add the following ActionScript to the class:
    package {
    	
      import flash.display.MovieClip;
      import flash.events.MouseEvent;
    	
      public class VirtualKeyboard extends MovieClip {
    		
        static private const keys:Array = [
          "a_key", "b_key", "c_key", "d_key", "e_key", "f_key", 
          "g_key", "h_key", "i_key", "j_key", "k_key", "l_key", 
          "m_key", "n_key", "o_key", "p_key", "q_key", "r_key",
          "s_key", "t_key", "u_key", "v_key", "w_key", "x_key",
          "y_key", "z_key", "ok_key", "del_key"
        ];
    		
        static public const KEY_ALPHABETIC:uint = 0;
        static public const KEY_DELETE    :uint = 1;
        static public const KEY_OK        :uint = 2;
    		
        private var _key:Object;
    		
        public function VirtualKeyboard() {
          mouseEnabled = false;
          surface.mouseEnabled = false;
          for(var i:uint = 0; i < keys.length; i++)
          {
            var key:Button = this[keys[i]];
            key.addEventListener(
              MouseEvent.MOUSE_UP, keyPressed);
            key.mouseChildren = false;
          }
        }
    		
        public function get key():Object {
          return _key;
        }
    		
        private function keyPressed(e:MouseEvent):void {
          var keyName:String = e.target.name;
          switch(keyName)
          {
            case "ok_key":
              _key = {type:KEY_OK};
              break;
    
            case "del_key":
              _key = {type:KEY_DELETE};
              break;
    
            default:
              var letter:String = keyName.charAt(0);
              _key = {type:KEY_ALPHABETIC, char:letter};
          }
    
          e.stopPropagation();
          dispatchEvent(e);
        }
      }
    }
    
  3. Save the class to the same location as your FLA and name it VirtualKeyboard.as.
  4. Move back to your FLA. Now you can link the class to your virtual keyboard's movie clip symbol. Within the library, right-click on the Keyboard symbol and select Properties. Click the Export for ActionScript checkbox. Enter VirtualKeyboard into the Class field. Click OK.
  5. Now we need some ActionScript that will populate the dynamic text field in response to the user interacting with the virtual keyboard. Create a document class and name it Main.
  6. For this class add the following ActionScript:
    package {
    
      import flash.display.MovieClip;
      import flash.events.MouseEvent;
    	
      public class Main extends MovieClip {
    		
        private const MAX_CHARS:uint = 10;
    		
        public function Main() {
          keyboard.addEventListener(
            MouseEvent.MOUSE_UP, keyPressed);
        }
    
        private function keyPressed(e:MouseEvent):void {
          var keyObj:Object = e.target.key;
          var keyType:uint = keyObj.type;
    
          switch(keyType)
          {
            case VirtualKeyboard.KEY_ALPHABETIC:
              if(field.text.length < MAX_CHARS)
              {
                field.appendText(e.target.key.char);
              }
              break;
    
            case VirtualKeyboard.KEY_DELETE:
              var text:String = field.text;
              field.text = text.substr(0, text.length - 1);
              break;
    
            case VirtualKeyboard.KEY_OK:
              keyboard.visible = false;
              break;
          }
        }
      }
    }
  7. Save the document class and name its file Main.as.
  8. Move back to the FLA and save it.
  9. That's us finished! Either test your FLA using ADL or deploy it to your device.

How it works...

Three simple classes were all that was needed to build your own custom virtual keyboard.

We won't go into the internals of Button.as since it was covered earlier in this book, but let's spend some time looking at both VirtualKeyboard.as and Main.as.

The VirtualKeyboard class is linked to the Keyboard symbol within your library and manages key presses. It does this by determining which movie clip was pressed before dispatching an event to any listeners.

The document class, Main.as, simply listens for this event and updates the dynamic text field to reflect the user's current input.

Let's move back to VirtualKeyboard.as within Flash Professional and take a closer look.

A constant named keys is declared within the class and holds within an array, the instance name of each key:

static private const keys :Array = [
  "a_key", "b_key", "c_key", "d_key", "e_key", "f_key", 
  "g_key", "h_key", "i_key", "j_key", "k_key", "l_key", 
  "m_key", "n_key", "o_key", "p_key", "q_key", "r_key", 		
  "s_key", "t_key", "u_key", "v_key", "w_key", "x_key",
  "y_key", "z_key", "ok_key", "del_key"
];

Within the class' constructor we make the keys interactive by simply looping through the keys array and attaching a MOUSE_UP event handler to each:

public function VirtualKeyboard() {
  mouseEnabled = false;
  surface.mouseEnabled = false;
  for(var i:int = 0; i < keys.length; i++)
  {
    var key:Button = this[keys[i]];
    key.addEventListener(
      MouseEvent.MOUSE_UP, keyPressed);
    key.mouseChildren = false;
  }
}

We receive this event when a user lifts their finger off a key, indicating a successful press. When this takes place, our keyPressed() handler is called and information regarding that key is created and stored. Here's the code for this again:

private function keyPressed(e:MouseEvent):void {
  var keyName :String = e.target.name;
  switch(keyName)
  {
    case "ok_key":
      _key = {type: KEY_OK};
      break;

    case "del_key":
      _key = {type: KEY_DELETE};
      break;

    default:
      var letter:String = keyName.charAt(0);
      _key = {type: KEY_ALPHABETIC, char: letter};
  }

  e.stopPropagation();
  dispatchEvent(e);
}

The handler checks the name of the movie clip instance that was pressed, and from the name determines which of the following key types it represents:

  1. The okay key.
  2. The delete key.
  3. An alphabetic key.

The type of key is stored within the _key member variable, and if the key represents a letter from the alphabet then its character is stored too. The class also provides a public getter method named key, which provides access to this information. We'll see the key property being accessed from the document class in a moment. Finally a MOUSE_UP event is dispatched to any listeners.

Okay, now take a look at Main.as again.

It simply listens for the keyboard movie clip dispatching a MOUSE_UP event. This event will only be dispatched if the user has successfully pressed one of the virtual keyboard's keys. You can see the event listener being added below:

public function Main() {
  keyboard.addEventListener(
    MouseEvent.MOUSE_UP, keyPressed);
}

Then within the keyPressed() event handler, we simply update the dynamic text field - field - in response to each of the user's key presses. Here's the method again as a reminder:

private function keyPressed(e:MouseEvent):void {
  var keyObj :Object = e.target.key;
  var keyType:uint = keyObj.type;	

  switch(keyType)
  {
    case VirtualKeyboard.KEY_ALPHABETIC:
      if(field.text.length < MAX_CHARS)
      {
        field.appendText(e.target.key.char);
      }
      break;

    case VirtualKeyboard.KEY_DELETE:
      var text:String = field.text;
      field.text = text.substr(0, text.length - 1);
      break;
			
    case VirtualKeyboard.KEY_OK:
      keyboard.visible = false;
      break;
  }
}

The handler calls the virtual keyboard's key property to determine which of the three types the pressed key belongs to. If it's an alphabetic key then the letter it represents is appending to the dynamic text field. If the user presses the del key then the last character is removed from the text field. Finally, if it was the ok key then the keyboard is simply hidden from view.

Building your own custom keyboard can create a more engaging experience for the user and provide consistency with your app's user interface. However if the native iOS keyboard that's available to you is sufficient then consider using it, as it's familiar and understood by all iOS users.

See also

iOS HTML5 Speedometer App

Here’s something I’ve been meaning to blog about for well over a year but for one reason or another didn’t get round to it. It’s an HTML5 port of a speedometer app I once wrote using Adobe AIR. I thought it would be a good way of polishing up on my JavaScript and also learn a few of the HTML5-specific APIs such as Geolocation. The original was badly in need of a lick of paint, so I changed the graphics a bit and also added a Need For Speed styled camera shake effect when a certain speed was reached.

To be honest, porting it from ActionScript 3 to HTML5 was fairly straightforward, and the app performed pretty well on iPhone and iPad, which I used as my test devices. Of course, the development was done on a PC so I made sure the app could swap between real geolocation data (for running on a device) and some test data (for development) I’d created. I’ve embedded a video of the app running above, complete with some test data so you can see it running.

Adobe AIR iOS Success Stories

“Really! That was done in Flash?” I’m hearing this quite frequently these days. It’s an extremely positive sign and it validates our own evaluation at WeeWorld that Adobe AIR is a more than viable tool for the creation of mobile games. If you’re still in any doubt then here’s a list of games you should download straight to your iPhone.

SongPop


Take part in music challenges between friends in this hugely popular music trivia game. At SongPop’s heart is an excellently crafted social gaming element allowing players to connect with friends via Facebook or simply find new friends who love the same music. It employs a turn-based battle mechanic, where games are won by identifying a collection of songs faster than your opponent. You can choose from over 35 playlists with samples from thousands of popular artists across multiple genres.

SongPop is available from the App Store free of charge, and has a five-star rating with over eleven thousand votes.

Wonderputt


Wonderputt is a quite beautiful isometric crazy golf game that started life on browsers and was recently ported to iPad. As soon as you launch this app you’ll understand why it was a Visual Arts Finalist at both the Develop Awards 2012 and IGF 2012. Wonderputt’s 18 holes are full of delightful little details that are unravelled as you work your way through its world of geographic delights. With Game Center leaderboards, achievements, and a triple length soundtrack, there’s plenty here to keep you occupied.

Wonderputt is available from the App Store and it’s also worth visiting the game’s development diary where you can find out all sorts of detail about its creation.

Match Mee


Easy to pick up but extremely difficult to put down, Match Mee is a simple matching game with many hidden layers. It’s incredibly addictive and if you start chasing high scores or going after its many achievements then you could easily lose hours to this one (I know people who have). Also, if you’re a developer looking for an example of an iOS game that makes great use of Flash’s vector renderer then Match Mee is definitely worth taking a look at.

Match Mee is available for free from the App Store and runs on iPhone, iPad and iPod touch.

Super Hexagon


If someone had told me a few years back that my favourite iOS game would be developed using Flash I’d have immediately suggested they visit a psychiatrists and get themselves checked out. But here I am now with Super Hexagon, a slice of gaming genius that I can’t get enough of. Marrying both retro and casual gaming elements, Super Hexagon will have you coming back for more time and again. Its hardcore nature ensures that most games last only a handful of seconds, but when beating your previous best by milliseconds feels like serious progress you’ll soon find yourself losing hours as you convince yourself that all you need is one more try.

Smart Aliens


If you’re looking for an example of what can be done with the Starling framework then look no further than Smart Aliens. Running at a super smooth 60 frames per second, it shows the performance benefits you can get from working on top of Adobe’s Stage 3D. Smart Aliens is another perfect example of social gaming. Whereas many iOS games employ turn-based mechanics, Smart Alien goes for real-time battles with friends in what can only be described as a modern take on hangman.

Smart Aliens is available for free from the App Store. Check it out.

Ruby Blast


Last but certainly not least is Zynga’s Ruby Blast, which is a direct port of their excellent Facebook game. The fact that social gaming experts Zynga are now developing cross-platform mobile apps with AIR is a shining endorsement for the Flash platform. It’s also another great example of the power of Stage 3D and the Starling Framework. It has only been available for a few weeks but Ruby Blast has already gathered nearly seven thousand positive reviews. Pop on over to the App Store and give it a try.

Match Mee for iOS Released

At WeeWorld we just released our latest iOS game, Match Mee, and I’m delighted to announce it’s our first app written using Adobe AIR. This is quite a departure for us as previously we’ve exclusively written native apps. However, given the continual improvements to the AIR SDK and the fact that Match Mee required the use of a vector rendered, it just made more sense to use our Flash expertise. Plus it puts us in a very nice position where we can relatively quickly push out an Android port when the time comes.

Match Mee’s a universal app (iPhone, iPad & iPod touch) and although Apple announced the iPhone 5 shortly before we were due to release, we managed to squeeze in support for the new resolution at the last minute. A few native extensions were also written in-house to provide support for Flurry Analytics and various ad networks. Additionally, Game Center, Facebook integration, and app rating support was provided by Milkman Games who also gave excellent support to iron out a few minor issues we were seeing on legacy hardware.

I can’t over emphasise how important Flash’s vector renderer was for us in this project. The game randomly generates WeeMee’s of varying sizes from a pool of over 200 assets. The combined size of all this vector information was just over one megabyte and, of course, scaled perfectly across the various resolutions supported across the full range of iOS devices. Keeping the file size down using a bitmap-based solution would have been very difficult.

If you have an iOS device then please take Match Mee for a spin (it’s free) and let me know what you think. At its core is a simple and fun game mechanic that’s very easy to pick up but pretty damn hard to put down.

Hopefully we’ll use Adobe AIR again for future apps as it seems to be picking up some momentum as a mobile development platform.

Oh and if you’ve got a minute to spare then jump over to our Facebook page and give MatchMee a like. Thanks!

Bunny Vengeance Game Concept

I’ve been working with my buddie Alex on a new game idea, codenamed Bunny Vengeance. We’ve not committed to actually making anything for real yet but I thought I’d share a concept video that Alex put together. I’m hopeful that we’ll at least put together a few rapid prototypes but it really depends on the feedback we receive. So please, let me know what you guys think.

It’s always great to be working with talented people like Alex. He’s a world class animator and if you don’t believe me take a peek at his showreel below. I’m sure you’ll recognise, well, most of his work 😉

Alex has only recently started dabbling in Flash, but it’s seriously cool to see someone who’s worked for the likes of Pixar and DreamWorks applying his skills to the Flash platform. Hopefully we’ll be able to find the time to continue with this project.

Flash Pro CS6 and the Toolkit for CreateJS

Learn how to build rich HTML5 applications with content exported using Flash Professional CS6’s Toolkit for CreateJS.

What you will learn…

  • The fundamentals of the CreateJS suite of JavaScript libraries
  • How to publish Flash Professional CS6 assets for use with CreateJS
  • How to write JavaScript that utilizes your exported content

What you should know…

  • You should be comfortable working with Flash Professional
  • A familiarity with ActionScript or JavaScript is required

The ubiquity of HTML5 makes it the ideal technology for the delivery of rich web-based content across a wide range of devices and platforms. While various JavaScript code libraries and frameworks exist for the benefit of developers, there has been a serious lack of tooling to aid designers wishing to create rich expressive content. This has been particularly problematic for those accustomed to Flash Professional’s powerful illustration and animation capabilities. Just how do you create equivalent content when targeting HTML5?

With the release of Flash Professional CS6, Adobe has solved this problem by providing the Toolkit for CreateJS – an extension that takes animated content created in Flash and exports it to HTML5. Once exported, developers can write JavaScript to manipulate and add interactivity to the content by taking advantage of the popular CreateJS framework.

This tutorial will take you through the entire designer-developer workflow. You’ll learn how to export the contents of a FLA to HTML5, before adding interactivity to it using JavaScript and the CreateJS framework. We’ll be creating an underwater scene complete with animating air bubbles (Figure 1) that rush towards the surface. We’ll also add a little interactivity, allowing the user to pop any of the bubbles by clicking on them. The major difference being that this time we’ll be targeting HTML5 within the browser rather than the Flash runtime.

Figure 1. Designed in Flash but running in HTML5.

Getting Started

You’ll need Flash Professional CS6 to work through this tutorial. A trail version can be downloaded from www.adobe.com/downloads.

The Toolkit for CreateJS is a complimentary extension for Flash Professional CS6 that can be downloaded from www.adobe.com/go/downloadcreatejs. Once downloaded, simply double-click the .zxp file to install it through Adobe Extension Manager CS6. Adobe are committed to updating the toolkit’s capabilities on a quarterly basis, so check the CreateJS Developer Center from time to time for any new versions.

For development work you’ll need a suitable code editor or IDE. I’ll be using Sublime Text 2, a trial version of which can be downloaded from www.sublimetext.com/2.

Finally, a FLA has been prepared for you to work with. Download it from www.yeahbutisitflash.com/downloads/toolkit-for-create-js-tut/bubbles.fla and open it within Flash Professional CS6.

Creating Assets within Flash Professional CS6

Let’s begin by taking a look at the FLA. It contains a mixture of vector and bitmap content that’s used to represent our underwater scene.

Sitting on the stage is a movie clip with an instance name of background. The movie clip itself contains a bitmap that represents the underwater scene’s background image.

The rest of our content doesn’t sit on the stage, but can instead be found in the library. If you move to the Library panel you’ll find a symbol named Bubble that will be used for each of the scene’s bubbles. Double-click the symbol to move to its timeline.

Its timeline consists of 48 frames of animation. It’s a fairly conventional animation that uses classic tweening to skew the bubble, giving the illusion of it changing shape while underwater. The bubble itself consists of vector artwork making it scalable without the loss of fidelity. This is useful as we’d like to add bubbles of varying sizes to the scene at runtime.

In order to add bubble instances at runtime, we’ll need to provide the Bubble symbol with a linkage class name. To do that, simply right-click on the Bubble symbol within the library and select Properties from the context menu (Figure 2). From the Symbol Properties panel, ensure that the Advanced section is expanded and click the Export for ActionScript checkbox (Figure 3). Doing so will provide the Bubble symbol with a default class name of Bubble. It’s this class name that we’ll use within our JavaScript code to dynamically create instances of the bubble at runtime.

Figure 2. Moving to the symbol's Properties panel.

Now click the OK button to close the panel. If an ActionScript Class Warning panel appears, simply press its OK button to dismiss it. The warning panel is simply informing us that the Flash IDE cannot find a class named Bubble and that it will automatically create one for us. This is fine and is exactly what we want.

Figure 3. Adding a class linkage to the Bubbles symbol.

It’s worth bearing in mind that while we associated an ActionScript linkage class to our bubble, when exporting our content to HTML5, this linkage class name will be available to the programmer as a JavaScript class.

With that we’re now ready to export our FLA’s contents to HTML5. First save your work.

Publishing for CreateJS

Publishing to HTML5 is actually very simple and is taken care of by the Toolkit for CreateJS panel. You can open the panel by selecting Window | Other Panels | Toolkit for CreateJS from Flash Professional CS6’s drop-down menu. For easy access, feel free to dock the panel.

The panel (Figure 4) allows you to adjust various publish settings. While we’ll stick to the defaults, some are worthy of our attention before proceeding.

Figure 4. The Toolkit for CreateJS panel.

Near the panel’s bottom-right is the Hosted libs checkbox. After publishing to HTML5, the generated HTML file will require the use of various JavaScript libraries from the CreateJS suite. To save the developer having to download and host these libraries, the HTML file, by default, will use versions of the libraries that are hosted on a remote content delivery network.

There’s also an Include hidden layers checkbox, which is used to export HTML5 for any content sitting on guided layers. While I’d normally encourage you to uncheck this, for this tutorial there’s no need as our FLA has no hidden layers.

The panel also contains various publish paths, including where the generated output files will be written to. By default, the FLA’s root folder is used. Again, this is fine for the purpose of this tutorial.

Now go ahead and click the panel’s Publish button to export your FLA’s content as HTML5. After a brief moment, your default web browser will launch and you’ll see the contents of your FLA’s stage sitting within the browser. While you’d normally expect this content to be running within the Flash Player, this time it’s actually using HTML and JavaScript. You can confirm this by right-clicking within the browser window (Figure 5). There will be no mention of Flash Player anywhere within the context menu.

Figure 5. Look! No Adobe Flash Player.

Effectively you’re looking at an HTML5 representation of the SWF that you’d normally publish from your FLA.

The CreateJS Output Files

At the moment, our HTML doesn’t do much. It simply shows the bitmap image that was sitting on our stage. We’ll address that soon enough by writing some JavaScript to bring our underwater scene to life, but first let’s take a look at what was generated during publication (figure 6).

Figure 6. The files generated by the Toolkit for CreateJS panel.

You should see that the following two sub-folders and two files were created within your FLA’s root folder:

images – Any bitmap images used by your FLA are kept here.
sounds – Any sound files used by your FLA are kept here.
bubbles.html – An HTML file that is created to allow you to preview your output in the browser.
bubbles.js – This file contains the JavaScript required to represents any symbols sitting on your stage and within the library.

If you’d unchecked the Hosted libs checkbox then a third sub-folder named libs would have been created to house each of the required CreateJS libraries.

What Exactly is CreateJS?

As we’ve just seen, the contents of our FLA’s library are magically represented within a JavaScript file named bubbles.js. But how is this possible?

Well, it’s made possible by CreateJS, which provides a suite of JavaScript APIs that can be used to represent the complex artwork that is created within the Flash Professional IDE. The generated bubbles.js file simply contains calls to these APIs in order to recreate each of your library’s assets.

CreateJS consists of the following libraries:

EaselJS – Enables rich graphics and interactivity with HTML5 Canvas.
TweenJS – A tweening library that integrates with EaselJS.
SoundJS – Provides audio playback functionality.
PreloadJS – Manages and co-ordinates the loading of assets.

When you’re developing your own applications, it’s likely that you’ll make use of the CreateJS suite to further manipulate and interact with the content exported from your FLA.

This tutorial will really just scratch the surface of these powerful libraries but I encourage you to spend as much time as possible exploring the documentation on the official CreateJS website at www.createjs.com.

Understanding the Published JavaScript

Each time you publish using the Toolkit for CreateJS panel, an HTML and JavaScript file will be generated. The HTML file is the entry point and when opened within your browser, will play any content placed on your stage. The JavaScript file, as has already been explained, will contain the actual code necessary to represent that content.

Let’s take a look at that JavaScript file. Open bubbles.js within a text editor and examine the code.

You should notice that an object named lib is created, and that each property of that object is a class that represents a symbol from your FLA’s library. For example, here’s the JavaScript that defines the Bubble movie clip symbol from your library:

(lib.Bubble = function(mode,startPosition,loop) {
  this.initialize(mode,startPosition,loop,{},true);

  // Layer 1
  this.instance_2 = new lib.BubbleVector();
  this.instance_2.setTransform(0,0,0.4,0.4);

  this.timeline.addTween(
    cjs.Tween.get(this.instance_2).to({scaleY:0.4,skewX:3.3},11).to(
    {skewX:-3.1},24).to({scaleY:0.4,skewX:0},12).wait(1));

}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(-157,-157,314.1,314.1);

The code itself is very readable. You can see an instance of BubbleVector (The BubbleVector class itself is defined earlier in the file) being added to the Bubble movie clip’s timeline:

this.instance_2 = new lib.BubbleVector();
this.instance_2.setTransform(0,0,0.4,0.4);

Followed by the definition of the tweening operations that are to be applied between the timeline’s keyframes:

this.timeline.addTween(
  cjs.Tween.get(this.instance_2).to({scaleY:0.4,skewX:3.3},11).to(
  {skewX:-3.1},24).to({scaleY:0.4,skewX:0},12).wait(1));

Quickly revisit the Bubble movie clip within your FLA’s library. Look at its timeline while reading over the code listed above and it should start to make a lot of sense.

Essentially, everything within your FLA’s library will be accessible via the lib object defined by the bubbles.js file. You can use the new keyword to create instances of these symbols then add them to the display list. Here’s an example:

var myBubble = new lib.Bubble();
stage.addChild(myBubble);

You could be forgiven for thinking that you’re looking at ActionScript, but the two lines of code above are in fact JavaScript. The CreateJS framework does a really great job of providing an API that should feel very familiar to Flash developers.

Take a final look through the code. You should see the following library symbols being declared: bubbles, Bubble, Background, background, and BubbleVector. All can be instantiated and added to your display list using JavaScript. Some are in fact instantiated within bubbles.js and used as child instances. You’ve already seen this in action, with BubbleVector being added to the display list of Bubble.

Understanding the Published HTML

Now that you’ve familiarized yourself with the bubbles.js file, let’s take a peek at the generated HTML file, bubbles.html. It’s within this file that your stage is created and updated.

At the top of the HTML file, you’ll see that the various libraries required from the CreateJS suite are loaded. Additionally, the bubbles.js file, which is the JavaScript version of your FLA’s library, is also included:

<script src="http://code.createjs.com/easeljs-0.5.0.min.js"></script>
<script src="http://code.createjs.com/tweenjs-0.3.0.min.js"></script>
<script src="http://code.createjs.com/movieclip-0.5.0.min.js"></script>
<script src="http://code.createjs.com/preloadjs-0.2.0.min.js"></script>
<script src="bubbles.js"></script>

At the bottom of the HTML file is an HTML5 canvas element, which is used to render your stage:

<body onload="init();" style="background-color:#D4D4D4">
  <canvas id="canvas" width="640" height="480"
   style="background-color:#ffffff"></canvas>
</body>

As you can see from the HTML snippet above, when the page is loaded, an init() function is called. Within this function, any image and sound resources are loaded using the PreloadJS library. If you can remember, our FLA’s stage had a movie clip that contained a bitmap image of our underwater scene. You can see the init() function below with the bitmap’s source path being listed within a manifest array, which is eventually passed to the preloader:

function init() {
  canvas = document.getElementById("canvas");
  images = images||{};
 
  var manifest = [
    {src:"images/background.png", id:"background"},
    {src:"images/flashlogo.png", id:"flashlogo"}
  ];
 
  var loader = new PreloadJS(false);
  loader.onFileLoad = handleFileLoad;
  loader.onComplete = handleComplete;
  loader.loadManifest(manifest);
}

The final chunk of work takes place within the handleComplete() function, which is called once all image and sound resources are loaded:

function handleComplete() {
  exportRoot = new lib.bubbles();
 
  stage = new createjs.Stage(canvas);
  stage.addChild(exportRoot);
  stage.update();
 
  createjs.Ticker.setFPS(30);
  createjs.Ticker.addListener(stage);
}

Three things take place here.

Firstly, a top-level container clip named lib.bubbles is instantiated and assigned to the exportRoot global variable. This container simply holds all the content that was originally sitting on your FLA’s stage.

Secondly, a JavaScript class that represents the stage is instantiated and exportRoot is added as a child. A call to the stage’s update() method forces its content to be drawn to the screen.

Finally, a static Ticker class is used to regulate the frame rate. The stage is added as a listener, which will ensure that its internal tick() method is called on every frame update, forcing a redraw.

You may also have noticed that several global variables are declared at the top of the HTML file:

var canvas, stage, exportRoot;

This permits access to these objects from anywhere within your code. The JavaScript version of your library can be accessed in a similar manner via the global lib object, which was defined within your bubbles.js file.

We’ll make good use of both the lib, canvas and stage objects throughout the remainder of this tutorial.

Getting Ready for Development

Now that you’ve familiarized yourself with the bubbles.js file, I think it’s about time we started writing some code. You could be tempted to simply start adding your JavaScript to the existing bubbles.html file, but there’s a problem with that approach. Every time you make alterations to your FLA and republish, your bubbles.html file will be overwritten.

Let’s get round this problem by creating a new HTML file to work from. Simply create a duplicate copy of the bubbles.html file and rename it BubblesDev.html. Test your BubblesDev.html file by opening it within a web browser. From now on, when developing, this is the file that you’ll use when testing your latest changes.

With that done we can finally start writing the JavaScript required to bring our underwater scene to life.

Creating a Main Loop

Every application requires a main loop. A main loop should be executed on every frame update and is an ideal location for handling an application’s high-level logic. To achieve this, we’ll create a custom tick() function for the static Ticker class to call, as opposed to it calling the stage’s internal tick() function. Think of this function as your stage’s ENTER_FRAME event handler.

Open BubblesDev.html within your text editor and add the following at the end of its script block:

function tick() {
  stage.update();
}

We’ll add more code to this function as we progress but for the time being it simply forces the stage to be redrawn.

We’ll also need to make a slight alteration within the file’s handleComplete() function. Change its final line of code from:

createjs.Ticker.addListener(stage);

to:

createjs.Ticker.addListener(window);

This will ensure that your custom tick() function is called instead of the stage’s.

Adding a Bubble

Although we now have a custom main loop, if you run BubblesApp.html within the browser, you won’t actually see anything different yet. Let’s rectify this by adding a bubble from our library onto the stage.

Add the following function at the end of your JavaScript block:

function setupBubbles() {
  var bubble1 = new lib.Bubble();
  bubble1.x = canvas.width / 2;
  bubble1.y = canvas.height / 2;
 
  stage.addChild(bubble1);
}

Its code should look fairly familiar and isn’t that dissimilar to the equivalent ActionScript. First off, an instance of the library’s Bubble symbol is created using the new keyword. Then the bubble1 instance is positioned in the center of the stage.

To center the bubble, we need to know the stage’s width and height. Unfortunately the global stage object does not provide width and height properties. However, we can retrieve this information from the global canvas object instead – this is the HTML5 canvas element that is used to represent our stage.

Finally, with the bubble’s position set, it is added to the stage’s display list using the stage object’s addChild() method.

Now all that’s required is to call the setupBubbles() function from a suitable location within your code. Add the call to the end of your handleComplete() function:

  createjs.Ticker.setFPS(30);
  createjs.Ticker.addListener(window);
 
  setupBubbles();
}

Now save your BubblesDev.html file and refresh your browser window. You should see an instance of the Bubble movie clip animating in the center of the stage (Figure 7). It really is quite impressive. You’re actually looking at a full HTML5 representation of your symbol’s vector artwork and timeline animation.

Figure 7. An HTML5 representation of your bubble movie clip.

Adding Another Bubble

Just like ActionScript, your CreateJS display objects can be scaled horizontally and vertically using the scaleX and scaleY properties. Let’s place a second bubble on the stage, and also apply a scale factor to both it and the previous bubble.

Figure 8. Positioning and scaling bubble instances.

While we’re at it, let’s also use each bubble’s width to position it away from the center of the stage. We’ll push the first bubble over to the left and the second bubble to the right (Figure 8). Make the following alterations to your setupBubbles() function:

function setupBubbles() {
  var bubble1 = new lib.Bubble();
  bubble1.scaleX = bubble1.scaleY = 0.6;
  bubble1.x = canvas.width / 2 - (bubble1.nominalBounds.width * bubble1.scaleX);
  bubble1.y = canvas.height / 2;
 
  var bubble2 = new lib.Bubble();
  bubble2.scaleX = bubble2.scaleY = 0.4;
  bubble2.x = canvas.width / 2 + (bubble2.nominalBounds.width * bubble2.scaleX);
  bubble2.y = canvas.height / 2;
 
  stage.addChild(bubble1);
  stage.addChild(bubble2);
}

The JavaScript above scales the first bubble to 60 percent of its original size. It then measures the width of the bubble, and pushes the bubble to the left of the stage’s center by that amount. Here are the two lines of code from the listing above that accomplish this:

bubble1.scaleX = bubble1.scaleY = 0.6;
bubble1.x = canvas.width / 2 - (bubble1.nominalBounds.width *  
  bubble1.scaleX);

If you look closely you’ll notice that obtaining the bubble’s width isn’t as straightforward as you might expect. CreateJS’s display objects do not possess a width or height property. This is because calculating a display object’s bounds can be very expensive, especially when dealing with complex vector shapes or containers with transformations on children.

We can however, manually perform these calculations for our bubble instances thanks to the fact that our bubble’s original dimensions are available via a nominalBounds property. Here’s the code used to calculate the width of the first bubble after it has been scaled:

bubble1.nominalBounds.width * bubble1.scaleX

It’s hardly rocket science. The bubble’s original width is obtained from the nominalBounds.width property, and is then multiplied by the bubble’s current scale factor. In order for this to work, you must remember to apply the new scale factor first, before performing the calculation.

A similar procedure is performed for the second bubble, only it’s scaled by 40 percent then moved to the right of the stage’s center.

We’ll make use of the scaleX, scaleY, and nominalBounds properties again later on in this tutorial.

Creating a Custom Bubble Class

In order to create a convincing underwater scene, we’re going to need a considerable number of bubbles. Also, we’ll need to size each bubble, continually monitor and update its position to provide movement, and also apply some alpha transparency to give the illusion of distance.

To manage all this, it makes sense to encapsulate our bubble code within its own custom class, otherwise the BubblesDev.js file could become quite messy. We can do this by extending EaselJS’s Container class and placing your library’s bubble within it.

Create a new file and name it Bubble.js. Add the JavaScript shown below to your file and save it.

function Bubble(scale, speed, alpha) {
  this.initialize();
 
  this.bubble = new lib.Bubble();
  this.addChild(this.bubble);
}
Bubble.prototype = p = new createjs.Container();

We’ll add some more functionality to this class in a moment but first let’s explore what’s currently there.

The class’ constructor is defined by the Bubble() function and accepts three parameters. The first is a scale factor used to size the bubble; the second will be used to assign a vertical speed to the bubble; and the third represents the amount of alpha transparency to be applied. Essentially all three are used to customize each of the scene’s bubbles, ensuring that there is plenty of variety. Your class currently doesn’t make use of any of these parameters yet, but we’ll get onto that in a moment.

Inside the constructor, we perform two important tasks. The first is to call the initialize() method, which is inherited from EaselJS’s Container class. The second is to create an instance of the library’s Bubble symbol and add it to the container’s display list.

For the time being, our custom Bubble class doesn’t really give us any advantage over lib.Bubble. Let’s address that by adding some additional functionality to it. We’ll start by fleshing out the constructor function.

Add the following code at the end of the constructor function:

// Set the scale, speed and alpha.
this.scaleX = this.scaleY = scale;
this.speed = speed;
this.alpha = alpha;

The code snippet above takes each of the three parameters and sets various properties of the class. The first sizes the custom bubble by setting its scaleX and scaleY properties. The second declares and sets a member variable named speed, which will be used to move the bubble upwards on each frame update. The third sets the bubble’s alpha property.

Let’s now create a custom width and height property for the bubble using the nominalBounds property we covered earlier. Add the following two lines of JavaScript to your constructor.

// Store the bubble's dimensions.
this.width = this.bubble.nominalBounds.width * scale;
this.height = this.bubble.nominalBounds.height * scale;

Finally, we need to place the bubble on the stage. We’d like a random position for each bubble, so let’s add a few more lines of code at the end of the constructor to do that:

// Setup the bubble's initial position.
this.x = -(this.width / 2) + ((canvas.width + this.width) * Math.random());
this.y = -(canvas.height / 2) + ((canvas.height * 2) * Math.random());

The bubble will now be placed randomly on the stage, and can even appear above and below the stage area. This will be ideal for creating a realistic spread of bubbles in our underwater scene.

The final piece of functionality we’d like to add is the ability to move the bubble vertically upwards. We can achieve this by writing a method that updates the bubble’s position each time it is called. Add the following update() method at the end of your Bubble.js file:

Bubble.prototype.update = function() {
  this.y -= this.speed;
  if(this.y < -(this.height / 2))
  {
    this.x = -(this.width / 2) + ((canvas.width + this.width) *
      Math.random());
    this.y = canvas.height + (this.height / 2) + (this.height *
      Math.random());
  }
}

As you can see, it uses your class' speed member variable to change the bubble's y-position. The remainder of the code checks to see if the bubble has moved off screen. If it has then it's randomly positioned below the stage, ready to float back in. This update mechanic helps to ensure that there's a continuous flow of bubbles by re-using a bubble once it has drifted above the stage's visible area. Also, notice that we use the width and height properties that were created in the constructor throughout our update() method.

Testing your Custom Bubble Class

Before moving on, save your Bubble.js file and move back to BubblesDev.html. Let's update its setupBubbles() function to use your custom Bubble class rather than creating a bubble instance directly from the global lib object.

First, include your Bubble.js file by adding the following highlighted line within the BubblesDev.html file:

<script src="http://code.createjs.com/easeljs-0.5.0.min.js"></script>
<script src="http://code.createjs.com/tweenjs-0.3.0.min.js"></script>
<script src="http://code.createjs.com/movieclip-0.5.0.min.js"></script>
<script src="http://code.createjs.com/preloadjs-0.2.0.min.js"></script>
<script src="bubbles.js"></script>
<script src="Bubble.js"></script>

We'll also need to declare a global variable to hold a reference to our custom bubble instance. Add the following highlighted line of code directly underneath the other global variable declarations:

<script>
var canvas, stage, exportRoot;
var bubble;

Now within setupBubbles(), remove the previous code you'd written and replace it with the following:

function setupBubbles() {
  bubble = new Bubble(0.5, 4, 0.75);
  stage.addChild(bubble);
}

The code above will create a bubble instance that is scaled by 50 percent, has a vertical speed of 4 pixels per second, and has its alpha value set to 75 percent opacity.

To actually move the bubble instance we'll need to call its update() method from within our application's main loop. Add a line of code within the tick() function to do this:

function tick() {
  stage.update();
  bubble.update();
}

Save your file and then refresh your browser window. You should see an instance of your custom bubble drifting up the screen. Once it has moved off the top of the screen, it will re-appear at the bottom.

By creating a custom Bubble class, we have kept its internal workings hidden from our BubblesDev.html file. Scan back through the HTML file and look at how little code is required to get a single bubble instance up and running.

Now we need to get this working for multiple Bubble instances.

Adding Multiple Bubbles

Let's put the finishing touches to our code by instantiating multiple bubbles to give a greater sense of realism and depth to our underwater scene. We'll do this by creating four layers of bubbles stacked on top of one another. The farthest back layer's bubbles will be the smallest, with the top most layer's bubbles being the largest.

To achieve this we'll use an array to hold all the bubbles. Within your BubblesDev.html file, declare the following highlighted global variable:

var canvas, stage, exportRoot;
var bubble;
var bubbles;

While you're at it, remove the bubble global variable that's highlighted below as we will no longer have a need for it:

var canvas, stage, exportRoot;
var bubble;
var bubbles;

Now write a function that creates the first layer of bubbles. These bubbles will be the smallest and will have relatively low speeds to give the impression that they are far off in the distance. The speed, size, and opacity of each bubble will also be random to add a little more variety and realism. Here's the code:

function setupSmallBubbles() {
  var BUBBLES = 25;
  var SCALE = 0.2;
  var SCALE_VARIANCE = 0.1;
  var SPEED = 1.3;
  var SPEED_VARIANCE = 1.0;
  var ALPHA = 0.2;
  var ALPHA_VARIANCE = 0.2;
 
  var bubble;
  for(var i = 0; i < BUBBLES; i++)
  {
    bubble = new Bubble(
      SCALE + (Math.random() * SCALE_VARIANCE),
      SPEED + (Math.random() * SPEED_VARIANCE),
      ALPHA + (Math.random() * ALPHA_VARIANCE)
    );
    bubbles.push(bubble);
    stage.addChild(bubble);
  }
}

As you can see, each bubble is instantiated then added to the bubbles array and to the stage's display list.

Now move back to the setupBubbles() function and replace its existing code with the following:

function setupBubbles() {
  bubbles = [];
  setupSmallBubbles();
}

Now all that's left to do is to update each bubble's position within your update loop. Make the following changes to the tick() function allowing it to walk through your array of bubbles and call each one's update() method:

function tick() {
  stage.update();
  for(var i = 0; i < bubbles.length; i++)
  {
    bubbles[i].update();
  }
}

Save your latest changes and test your code by refreshing your browser. You should see 25 randomly sized bubbles drifting up the screen.

Adding the remaining three layers is easy. We'll need to write a setupMediumBubbles(), setupLargeBubbles() and setupSmallBubbles() function. Each will create slightly larger and faster moving bubbles than the previous. Here's the code for each function:

function setupMediumBubbles() {
  var BUBBLES = 12;
  var SCALE = 0.3;
  var SCALE_VARIANCE = 0.1;
  var SPEED = 1.9;
  var SPEED_VARIANCE = 1.1;
  var ALPHA = 0.4;
  var ALPHA_VARIANCE = 0.3;
 
  var bubble;
  for(var i = 0; i < BUBBLES; i++)
  {
    bubble = new Bubble(
      SCALE + (Math.random() * SCALE_VARIANCE),
      SPEED + (Math.random() * SPEED_VARIANCE),
      ALPHA + (Math.random() * ALPHA_VARIANCE)
    );
    bubbles.push(bubble);
    stage.addChild(bubble);
  }
}
 
function setupLargeBubbles() {
  var BUBBLES = 6;
  var SCALE = 0.5;
  var SCALE_VARIANCE = 0.2;
  var SPEED = 3.1;
  var SPEED_VARIANCE = 1.5;
  var ALPHA = 0.7;
  var ALPHA_VARIANCE = 0.3;
 
  var bubble;
  for(var i = 0; i < BUBBLES; i++)
  {
    bubble = new Bubble(
      SCALE + (Math.random() * SCALE_VARIANCE),
      SPEED + (Math.random() * SPEED_VARIANCE),
      ALPHA + (Math.random() * ALPHA_VARIANCE)
    );
    bubbles.push(bubble);
    stage.addChild(bubble);
  }
}
 
function setupHugeBubbles() {
  var BUBBLES = 1;
  var SCALE = 1.0;
  var SCALE_VARIANCE = 0.2;
  var SPEED = 6;
  var SPEED_VARIANCE = 6;
 
  var bubble;
  for(var i = 0; i < BUBBLES; i++)
  {
    bubble = new Bubble(
      SCALE + (Math.random() * SCALE_VARIANCE),
      SPEED + (Math.random() * SPEED_VARIANCE)
    );
    bubbles.push(bubble);
    stage.addChild(bubble);
  }
}

Once written, all three functions should be called from within your setupBubbles() function. Here's how the final version of the function should look:

function setupBubbles() {
  bubbles = [];
  setupSmallBubbles();
  setupMediumBubbles();
  setupLargeBubbles();
  setupHugeBubbles();
}

Once again, save your changes and refresh the browser. You'll now see all four layers of bubbles smoothly moving up the screen.

Adding Interaction

As a final exercise, let's add some interactivity, allowing the user to pop a bubble by clicking on it. We'll add this functionality directly to your custom Bubble class. Open Bubble.js into your text editor and place the following lines of code at the end of its constructor function:

// Setup an onPress event handler.
this.bubble.onPress = this.bubbleClicked;

The onPress event is triggered when the user presses their mouse over the bubble. In response to the onPress event, a method named bubbleClicked() will be called to handle it.

Add the bubbleClicked() method to the end of your Bubble.js file:

Bubble.prototype.bubbleClicked = function(e) {
  e.target.visible = false;
}

When the onPress event is triggered it passes an event object to its designated event handler. In our case, the event object will be passed to our bubbleClicked() method. From this event object we can obtain a reference to the target instance that the event was fired from. In other words, we can obtain a reference that points back to the bubble instance that was clicked. This is ideal as it allows us to hide the bubble from view, giving the illusion that it has burst.

As a final step, we'd like the bubble to eventually become visible again. Add the following highlighted line of code to the Bubble class' update() method to do this:

Bubble.prototype.update = function() {
  this.y -= this.speed;
  if(this.y < -(this.height / 2))
  {
    this.x = -(this.width / 2) + ((canvas.width + this.width) * Math.random());
    this.y = canvas.height + (this.height / 2) + (this.height * Math.random());
    this.visible = true;
  }
}

The bubble will now become visible again when it has wrapped back round to the bottom of the screen. This ensures that we continue to have a stream of visible bubbles over time.

Now save your changes and view the final version of your underwater scene within your browser. Click on the bubbles to pop them. Take a look at the code in Listing 1 to see the final version of the BubbleDev.html file. You can also see the final version of the Bubble.js class in Listing 2.

Final Statement

Hopefully this introduction to CreateJS and JavaScript, will give you the confidence to create and deliver high-quality HTML5 content, while taking advantage of Flash Professional as a design tool. JavaScript may not possess many of the language features of ActionScript 3, but with the right libraries at hand you can write extremely sophisticated web-based content that will run across a wide range of desktop and mobile browsers. And to be honest, writing rich, interactive games and applications is always a lot of fun no matter what technology you opt to use.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CreateJS export from bubbles</title>
 
<script src="http://code.createjs.com/easeljs-0.5.0.min.js"></script>
<script src="http://code.createjs.com/tweenjs-0.3.0.min.js"></script>
<script src="http://code.createjs.com/movieclip-0.5.0.min.js"></script>
<script src="http://code.createjs.com/preloadjs-0.2.0.min.js"></script>
<script src="bubbles.js"></script>
<script src="Bubble.js"></script>
 
<script>
var canvas, stage, exportRoot;
var bubbles;
 
function init() {
  canvas = document.getElementById("canvas");
  images = images||{};
 
  var manifest = [
    {src:"images/background.png", id:"background"},
    {src:"images/flashlogo.png", id:"flashlogo"}
  ];
 
  var loader = new createjs.PreloadJS(false);
  loader.onFileLoad = handleFileLoad;
  loader.onComplete = handleComplete;
  loader.loadManifest(manifest);
}
 
function handleFileLoad(o) {
  if (o.type == "image") { images[o.id] = o.result; }
}
 
function handleComplete() {
  exportRoot = new lib.bubbles();

  stage = new createjs.Stage(canvas);
  stage.addChild(exportRoot);
  stage.update();

  createjs.Ticker.setFPS(30);
  createjs.Ticker.addListener(window);

  setupBubbles();
}
 
function tick() {
  stage.update();
  for(var i = 0; i < bubbles.length; i++)
  {
    bubbles[i].update();
  }
}
 
function setupBubbles() {
  bubbles = [];
  setupSmallBubbles();
  setupMediumBubbles();
  setupLargeBubbles();
  setupHugeBubbles();
}
 
function setupSmallBubbles() {
  var BUBBLES = 25;
  var SCALE = 0.2;
  var SCALE_VARIANCE = 0.1;
  var SPEED = 1.3;
  var SPEED_VARIANCE = 1.0;
  var ALPHA = 0.2;
  var ALPHA_VARIANCE = 0.2;
 
  var bubble;
  for(var i = 0; i < BUBBLES; i++)
  {
    bubble = new Bubble(
      SCALE + (Math.random() * SCALE_VARIANCE),
      SPEED + (Math.random() * SPEED_VARIANCE),
      ALPHA + (Math.random() * ALPHA_VARIANCE)
    );
    bubbles.push(bubble);
    stage.addChild(bubble);
  }
}
 
function setupMediumBubbles() {
  var BUBBLES = 12;
  var SCALE = 0.3;
  var SCALE_VARIANCE = 0.1;
  var SPEED = 1.9;
  var SPEED_VARIANCE = 1.1;
  var ALPHA = 0.4;
  var ALPHA_VARIANCE = 0.3;
 
  var bubble;
  for(var i = 0; i < BUBBLES; i++)
  {
    bubble = new Bubble(
      SCALE + (Math.random() * SCALE_VARIANCE),
      SPEED + (Math.random() * SPEED_VARIANCE),
      ALPHA + (Math.random() * ALPHA_VARIANCE)
    );
    bubbles.push(bubble);
    stage.addChild(bubble);
  }
}
 
function setupLargeBubbles() {
  var BUBBLES = 6;
  var SCALE = 0.5;
  var SCALE_VARIANCE = 0.2;
  var SPEED = 3.1;
  var SPEED_VARIANCE = 1.5;
  var ALPHA = 0.7;
  var ALPHA_VARIANCE = 0.3;
 
  var bubble;
  for(var i = 0; i < BUBBLES; i++)
  {
    bubble = new Bubble(
      SCALE + (Math.random() * SCALE_VARIANCE),
      SPEED + (Math.random() * SPEED_VARIANCE),
      ALPHA + (Math.random() * ALPHA_VARIANCE)
    );
    bubbles.push(bubble);
    stage.addChild(bubble);
  }
}
 
function setupHugeBubbles() {
  var BUBBLES = 1;
  var SCALE = 1.0;
  var SCALE_VARIANCE = 0.2;
  var SPEED = 6;
  var SPEED_VARIANCE = 6;
 
  var bubble;
  for(var i = 0; i < BUBBLES; i++)
  {
    bubble = new Bubble(
      SCALE + (Math.random() * SCALE_VARIANCE),
      SPEED + (Math.random() * SPEED_VARIANCE)
    );
    bubbles.push(bubble);
    stage.addChild(bubble);
  }
}
</script>
</head>
 
<body onload="init();" style="background-color:#D4D4D4">
  <canvas id="canvas" width="640" height="480" style="background-color:#ffffff">
  </canvas>
</body>
</html>

Code Listing 1. Final version of the BubblesDev.html file.

function Bubble(scale, speed, alpha) {
  this.initialize();

  this.bubble = new lib.Bubble();
  this.addChild(this.bubble);

  // Set the scale, speed and alpha.
  this.scaleX = this.scaleY = scale;
  this.speed = speed;
  this.alpha = alpha;

  // Store the bubble's dimensions.
  this.width = this.bubble.nominalBounds.width * scale;
  this.height = this.bubble.nominalBounds.height * scale;

  // Setup the bubble's initial position.
  this.x = -(this.width / 2) + ((canvas.width + this.width) * Math.random());
  this.y = -(canvas.height / 2) + ((canvas.height * 2) * Math.random());

  // Setup an onPress event handler.
  this.bubble.onPress = this.bubbleClicked;
}
Bubble.prototype = p = new createjs.Container();

Bubble.prototype.update = function() {
  this.y -= this.speed;
  if(this.y < -(this.height / 2))
  {
    this.x = -(this.width / 2) + ((canvas.width + this.width) * Math.random());
    this.y = canvas.height + (this.height / 2) + (this.height * Math.random());
    this.visible = true;
  }
}

Bubble.prototype.bubbleClicked = function(e) {
  e.target.visible = false;
}

Code Listing 2. Final version of the Bubble.js class.

How To Make Better Games

I don’t get out anywhere near enough these days, so my boss sent me off to the Edinburgh International Technology Festival. I must admit, there was a great mix of presentations over the two days, but it was the gaming related talks that I found of most interest, and I’d like to share some of what I learned.

Over the last year or so at WeeWorld, we’ve become increasingly focussed on mobile games development, and I was curious to see if our approach to development was at all similar to what others do. So I was pleasantly surprised to hear from CEO of Denki, Colin Anderson, who gave a great overview of the process that they used when writing their hit iOS game, Quarrel. Reassuringly, it looks like my current project is following a similar path to Denki’s. There was also a huge number of great points from the many other speakers, which I’ll attempt to summarise along with Colin’s suggestions.

90% of games revenue is generated by less than 10% of releases

It’s a sobering thought, but the reality is that very few games actually make any money. There’s nothing more frustrating than spending 6-9 months writing a game that doesn’t sell. Even simple games are expensive to make, so it’s important that you do everything in your power to ensure you create a game that stands a fighting chance of actually recouping it’s costs and then some.

Find fun first

It may seem obvious, but when you hit upon an idea you have to make sure that its core element is fun. Be it in the real world or digital, making games starts with play. It’s a concept we’re all familiar with, as playing and having fun is something we all did as children. And we all invented our own games by making up rules as we played. Of course, some attempts were more successful than others, but games that didn’t engage or entertain us were quickly discarded and forgotten about.

Creating video games is really no different. Latch onto a simple concept that’s fun and then apply some rules. And remember, your ultimate goal is to design something for other people. So don’t be selfish; invent with others in mind. And if your idea isn’t fun from the beginning, then it probably never will be.

Fail fast but fail small

The quality of your game doesn’t guarantee success but it’s safe to assume that the better your game, the more chance it has of succeeding. Therefore, if it looks like you’re working on a stinker then it’s better to know this as soon as possible and move onto a different idea. Again think back to when you were a kid. You ever spend months refining a game idea that wasn’t working? Of course not, kids are pretty unforgiving and just quickly move onto something else. Games developers really should do the same.

Companies such as Denki takes this very approach. They evaluate their project at various key points and identify as early as possible whether or not their idea is worth continuing with. Here’s roughly how Denki went about developing Quarrel for iPhone:

  1. Started with a simple concept image and statement.
  2. Produced concept art
  3. Developed an internal prototype
  4. Developed an external prototype
  5. Game production

This approach provides ample opportunity to bail out if the idea isn’t working. Early steps in the process are fairly inexpensive compared to the later steps and also take considerably less time to complete.

I’m a great believer in rapid prototyping so it was great to see Denki working on two prototypes of Quarrel before committing to the final game. How a player will interact with your game in the real world will be entirely different to what they will do in your head. This point alone makes prototyping critical as you can relatively quickly determine whether it’s worth continuing with your idea. It also gives invaluable feedback that can be used to improve the final game or a second prototype if you choose to continue.

Creatives love to talk more than they like to listen

An audience member had stated that he’d worked with many excellent creative directors over the years, and that not one of them had managed to create a decent game. Speaker, Mark Sorrell, responding to this by saying rather controversially that “Creatives love to talk more than they like to listen”. There’s a lot of truth in what Mark said, but I think it extends to all of us.

It’s really important that you aren’t precious with your ideas. If something isn’t working then don’t be afraid to drop it, or at the very least attempt to change it. Of course, when you’re so close to a project, it’s not always easy to tell if something isn’t working, that’s why you really need to listen to others. You’ll get nowhere if you, or your team, decides to work in isolation.

At WeeWorld we’ve been making changes to our prototypes based on invaluable user feedback. For our earlier prototype that feedback was purely from those within the company. However, we’ve gradually opened that up to external play testers, which has lead to significant changes being made.

User testing is vital, but you still need to make sure you take that feedback on board. It’s all too easy to collect valuable information from user testing and then simply ignore it because it will lead to more work. You also need to learn how to sift through the noise. This is particularly important when you have performed a large number of user tests. You’ll need to focus and identify the common complaints rather than trying to address everything.

Ultimately don’t be afraid to admit when an idea of your own isn’t working. The worst thing you can do is push through an idea that negatively impacts a project. I know it sounds like common sense, but it’s something that most of us are guilty of.

It’s not about ideas. It’s about teams

This may sound surprising, but a project’s success is based more on the team that work on it rather than the idea. If you don’t believe me then ask Pixar’s John Lasseter who firmly believes in the power of team work and the importance of having the right people within your team. I also think it was Lasseter who also said he’d rather work with an A team with a B idea, than a B team with an A idea.

Angry Birds is a great example of this. The concept isn’t new and has been done so many times before, but the team at Rovio took the concept and expertly crafted it into something more. A less talented team may not have been able to apply the same level of execution and creativity to it.

It’s amazing what a great team can do with a relatively simple and straightforward game concept.

Conclusion

So there you have it, plenty of food for thought. To be honest what I’ve covered here is only a fraction of what was covered during the gaming session at the Edinburgh International Technology Festival. I’m sure however that even these morsels can help your write better games.

So does this mean that my current project will go onto be a success? Of course not, but through rapid prototyping, user testing, and working in a great team environment, we have at least guaranteed that what we have now is significantly better than what we started with. And believe it or not, many companies who don’t follow these simple guidelines won’t be guaranteed of that, and will instead choose to work blind for their project’s duration.