Jan 12, 2012
Posted on Jan 12, 2012 in Hints and Tips | 10 comments
Stop using static menus! Most players immediately base their initial impression of a Flash game on the menu that they see when they load it. Stand out from the crowd with an active menu!
This tutorial was first posted in December 2011, but has since been updated with extra steps that explain how to make the code more flexible!
Final Result Preview
Introduction: Static vs Active
The word “static” essentially means lacking in change. The majority of menus we see throughout web games are lacking in change, you simply press Play and the game starts. Menus like that are overused and show little creativity or innovation.
To make a menu “active” we must continuously cause change. So in this tutorial that is exactly what we are going to accomplish: a menu that continuously changes.
Step 1: Setting Up
The first thing we are going to need to create is a new Flash File (ActionScript 3.0). Set its width to 650px, its height to 350px, and the frames per second to 30. The background color can be left as white.
Now save the file; you can name it whatever you please, but I named mine menuSlides.fla.
In the next section we will create the nine MovieClips used in the menu. For reference, here is a list of all the colors used throughout the tutorial:
- White – #FFFFFF
- Gold – #E8A317
- Light Gold – #FBB917
- Blue – #1569C7
- Light Blue – #1389FF
- Green – #347235
- Light Green – #3E8F1B
- Red – #990000
- Light Red – #C10202
- Matte Grey – #222222
Step 2: Creating the Slide MovieClips
To start with we will create the slides used in the transitions, but before we begin let’s turn on some very useful Flash features.
Right-Click the stage and select Grid > Show Grid. By default it will create a 10px by 10px grid across the stage. Next, right-click the stage again and this time select Snapping > Snap to Grid.
Now we can begin drawing! Select the Rectangle Tool and draw a Light Gold rectangle, 650px wide and 350px tall (you can Alt-click on the stage to make this easier). Now change the color to Gold and draw groups of three squares, each 20x20px, to form the shape of an L in each corner,:
Select the whole stage, right-click and choose Convert to Symbol. Name the MovieClip goldSlide and make sure that the type is MovieClip and the registration is top-left.
To save time and make things a whole lot easier, right-click the goldSlide MovieClip in the Library and select Duplicate Symbol three times to make three more copies. Change the colors in the new MovieClips to blue, green and red, then rename the MovieClips to blueSlide, greenSlide and redSlide.
Before we continue we should add some text to each slide. On goldSlide write PLAY, on blueSlide write INSTRUCTIONS, on greenSlide write OPTIONS and on redSlide write CREDITS.
Now that we have the text in place we can break it apart by right-clicking on it and selecting Break Apart twice; this will break the text down to a fill which will transition more smoothly. Plus as a bonus there will be no need to embed a font if you are just using it for the menu!
The Buttons
Now that we have drawn the 4 slides we can focus on the sideButton MovieClip that is used to move the slides either left or right.
First, draw a rectangle 30x60px with only a stroke (no fill), then draw diagonal lines 45 degrees from the top-right and bottom-right corners until they snap together in the middle of the opposite side. Now apply a Matte Grey fill to the triangle:
Next, delete the lines, then right-click the triangle and select Convert to Symbol. Name it sideButton, set the type to Button and make sure the registration is in the top-left corner.
Now insert 3 keyframes in the timeline by right-clicking the timeline and selecting Insert Keyframe. On the Up frame, select the fill of the triangle, go to the Windows tab and select Color. Change the Alpha to 50%. On the Over Frame repeat the same process, but this time set the alpha to 75%.
Now we can begin on the four numbered circle buttons, for jumping directly to a particular slide.
To start draw a white 30px circle with no stroke. Convert it to a symbol, name it circleOne, and set its type to Button and its registration point to the center. Insert three keyframes like we did before and then go to the Up frame.
Draw a black 25px circle with no stroke and center it to the middle through the coordinates or by using the Align menu. Next deselect the black circle, then reselect it and delete it. You should now have a white ring remaining. Now grab the text tool and put a white “1″ in the center of the ring. Then break this number apart until it is a fill.
Go to the Over frame and draw a black “1″. Center it and break it apart until it becomes a fill. Now deselect and reselect the fill, then delete it. Select everything on the frame and copy it, then go to the Down frame, select everything on it and hit delete. Paste in what we have copied.
Now create three more circle MovieClips, following the same process, for the numbers 2, 3 and 4.
Step 3: Positioning the MovieClips
Okay, we’re almost half-way done! First drag all of the slides onto the stage and position them with the following coordinates:
- goldSlide: (0, 0)
- blueSlide: (650, 0)
- greenSlide: (1300, 0)
- redSlide: (1950, 0)
Now drag and drop two copies of the sideButton. The first copy should be positioned at (10,145); before we can position the second copy we must first flip it!
Select the second copy and press Ctrl-T. Change the left-right to -100% and leave the up-down at 100%. Now move the second copy to (640,145).
Finally drag and drop the four circle MovieClips and position them as so:
- circleOne: (30, 320)
- circleTwo: (70, 320)
- circleThree: (110, 320)
- circleFour: (150, 320)
Your stage should now look like this:
The blue, green and red slides are hidden just off to the right of the stage. Now select everything on the stage and convert to a symbol. Name it menuSlidesMC, set the type to MovieClip and the registration to the top-left corner, and export it for ActionScript as MenuSlidesMC.
Before we finish we must give each of the MovieClips inside menuSlidesMC an instance name. Select each slide in the order they appear from the left and name them slide1, slide2, slide3 and slide4 respectively. Name the circle buttons one, two, three and four, and finally name the side buttons left and right.
Step 4: Setting Up the Classes
Now that all of our MovieClips have been created we can start setting up the two classes we are going to use.
First go to your Flash file’s Properties and set its class to menuSlides; then, create a new ActionScript 3.0 file and save it as menuSlides.as.
Now copy the following code into it; I will explain it after:
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class menuSlides extends MovieClip{
public var menuSlidesMC:MenuSlidesMC = new MenuSlidesMC();
public function menuSlides(){
addChild(menuSlidesMC);
}
}
}
Pretty basic – it’s a document class, into which we imported the MovieClips and Events we will use. Then we created an instance of MenuSlidesMC, and added it to the stage.
Now create a new ActionScript 3.0 file for the menuSlidesMC instance. Save it as MenuSlidesMC.as and copy the following code into it:
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MenuSlidesMC extends MovieClip{
public var speed:Number = new Number();
public var activeSlide:Number = new Number();
public function MenuSlidesMC(){
speed = 10;
activeSlide = 1;
addEventListener(MouseEvent.CLICK, slidesClick);
addEventListener(Event.ENTER_FRAME, slidesMove);
}
}
}
Just like last time, we imported what we are going to need, but we created two number variables. The first variable, speed, is actually how many pixels the slides are moved by each frame. (Note: this number has to evenly divide into your stage’s width to give a smooth transition). The second variable, activeSlide, tells us which slide is currently set to be on screen.
We also added two event listeners for functions we are going to create; one of them is called on a mouse click, and the other is called at the beginning of every frame.
Step 5: Creating the Event Handler Functions
To begin we will get the mouse click function out of the way. Start by creating a public function named slidesClick():
public function slidesClick(event:MouseEvent):void {
}
Next we will create some if-statements regarding the event.target.name. Basically, this property stores the name of the object that was targeted by the mouse click. We can use this to check which button is pressed:
if(event.target.name == "left"){
if(activeSlide>1){
activeSlide-=1;
}
}else if(event.target.name == "right"){
if(activeSlide<4){
activeSlide+=1;
}
}
if(event.target.name == "one"){
activeSlide=1;
}else if(event.target.name == "two"){
activeSlide=2;
}if(event.target.name == "three"){
activeSlide=3;
}else if(event.target.name == "four"){
activeSlide=4;
}
The code above goes in the slidesClick() function. The first set of if-statements are for the left and right side buttons; they increase or decrease the value of activeSlide, but never allow the value to become less than 1 or greater than 4 (since we only have four slides). The second set of if-statements are for the circle buttons; instead of just incrementing or decrementing the value of activeSlide they set it to the selected value.
Now let’s begin with the ENTER_FRAME handler function:
public function slidesMove(event:Event):void {
}
Add the slidesMove() function below your slidesClick() function and we’ll start adding some code to it. First, we’ll use a switch to check which slide should be on the screen, based on the value of activeSlide:
switch (activeSlide){
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
Now in each case we will create an if/else block that will check that slide’s current x-position, and move all of the slides either left, right, or not at all, depending on where the desired slide currently sits.
The first case looks like this:
if(slide1.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide1.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
Now all we have to do is repeat the same process for the other cases! After you are done your swtich should look like this:
switch (activeSlide){
case 1:
if(slide1.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide1.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
break;
case 2:
if(slide2.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide2.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
break;
case 3:
if(slide3.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide3.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
break;
case 4:
if(slide4.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide4.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
break;
}
And that’s it! We are all finished with the code and the menu should be working great right now.
…But wait, what if we want to add more slides or take some away?
Step 6: Adding Slides to an Array
At the moment our code isn’t very flexible due to all of those hard-coded if statements. So let’s do something bold: delete all of the code in the slidesMove() function because we will no longer be needing it, and also delete the if-statements for the circle buttons as we are going to optimize those as well.
Now declare a new variable (underneath speed and activeSlides):
public var slidesArray:Array = new Array();
The first variable, slidesArray, will be an array that contains all of our slides, which will allow us to access them by referencing an item in the array (so we can use slidesArray[2] instead of slide3).
One thing to note is that the first item in an array is given an index of 0, so we will have to make some changes to our instance names.
Select each slide in the order they appear from the left and name them slide0, slide1, slide2 and slide3, respectively. And to help us cut down on the number of lines of code we use, select each circle button in the order they appear from the left and name them circle0, circle1, circle2 and circle3, respectively.
If you are going to add more slides and buttons, now is the time to do so. Just position the extra slides at the end of the row of slides, then give them instance names following the same order. Then do the same for the circle buttons.
Now that we have the instance names correct we must add the slides to the array. Do so by adding the following code to your constructor:
slidesArray = [slide0, slide1, slide2, slide3, slide4, slide5];
Now the slides are in the array and can be accessed by their index in the array. For example, slidesArray[0] is equivalent to slide0 because that is the first item in the list.
Next, inside the “right” else-if statement, change the condition to:
if(activeSlide < slidesArray.length-1){
The value of slidesArray.length is equal to the number of elements in the array, so this new condition will now allow us to press the button and shift the slides over as long as the active slide is not the final slide.
Step 7: Handling Circle Button Presses
Now, when a circle button is clicked, we need to figure out which one it is (and which slide it refers to).
Create an array to hold all the circle buttons. First, define it, beneath the slide array:
public var slidesArray:Array = new Array();
public var circlesArray:Array = new Array();
Then, add the circle buttons to the array in the constructor:
circlesArray = [circle0, circle1, circle2, circle3, circle4, circle5];
Now, move to the slidesClick() function, underneath the whole if-else block. We’re going to check whether the button clicked is in the circle buttons array:
if (circlesArray.indexOf(event.target) != -1) {
}
The array’s indexOf() function checks to see whether an object is in the array; if it’s not, it returns -1. So, we’re checking to see whether it’s not equal to -1, which will check to see whether it is in the array.
Assuming it is, then the indexOf() function will return the index of the button within the circle buttons array – so, if circle3 was clicked, circlesArray.indexOf(event.target) will be equal to 3. This means we can just set activeSlide to 3, and we’re done!
if (circlesArray.indexOf(event.target) != -1) {
activeSlide = circlesArray.indexOf(event.target);
}
Step 8: Moving the Slides
The only thing left to do is move all of the slides. Begin by adding the same loop as we had before, in the slidesMove() function:
for(var i:int = 0; i < slidesArray.length; i++){
}
An if-else statement needs to be added now; this will use the variable activeSlide to select a slide out of the array and check where its x-position is, just like before.
if(slidesArray[activeSlide].x<0){
}else if(slidesArray[activeSlide].x>0){
}
Since activeSlide is a number, slidesArray[activeSlide] refers to one specific slide, so slidesArray[activeSlide].x is equal to that slide’s x-position.
In the first case we will add a for loop to move all of the movie clips to the right, and in the second case we will add a for loop to move all of the movie clips to the left.
Right:
for(var j:int = 0; j < slidesArray.length; j++){
slidesArray[j].x+=speed;
}
Left:
for(var k:int = 0; k < slidesArray.length; k++){
slidesArray[k].x-=speed;
}
If you test this now, you will notice that our optimised code has lead to a much zippier interface!
Step 9: Taking It Further
If you wanted to take this even further, you could use a for loop to position the slides and the circles, rather than needing to drag and drop them in the Flash IDE. For example, to position the slides, we’d first position slide0 in the constructor:
slidesArray = [slide0, slide1, slide2, slide3, slide4, slide5];
slidesArray[0].x = 0;
slidesArray[0].y = 0;
Then, we’d loop through all the other slides, starting at slide1:
slidesArray = [slide0, slide1, slide2, slide3, slide4, slide5];
slidesArray[0].x = 0;
slidesArray[0].y = 0;
for (var i:int = 1; i < slidesArray.length; i++) {
}
We can give all the slides an y-position of 0:
slidesArray = [slide0, slide1, slide2, slide3, slide4, slide5];
slidesArray[0].x = 0;
slidesArray[0].y = 0;
for (var i:int = 1; i < slidesArray.length; i++) {
slidesArray[i].y = 0;
}
…and then we can set each slide’s x-position to be 620px to the right of the slide before it:
slidesArray = [slide0, slide1, slide2, slide3, slide4, slide5];
slidesArray[0].x = 0;
slidesArray[0].y = 0;
for (var i:int = 1; i < slidesArray.length; i++) {
slidesArray[i].x = slidesArray[i-1].x + 620;
slidesArray[i].y = 0;
}
If your slides aren’t 620px wide, you can even detect their width automatically!
slidesArray = [slide0, slide1, slide2, slide3, slide4, slide5];
slidesArray[0].x = 0;
slidesArray[0].y = 0;
for (var i:int = 1; i < slidesArray.length; i++) {
slidesArray[i].x = slidesArray[i-1].x + slidesArray[i-1].width;
slidesArray[i].y = 0;
}
You can do the same thing with the circle buttons, but I’ll leave that up to you to experiment with.
The great thing about this is, you can add as many slides as you want to the menu; all you have to do is add them to the array, and they’ll be dealt with by this code.
(You can remove slides from the array, too, but they won’t be affected by any of the code, so you’ll probably need to reposition them in the Flash IDE.)
Conclusion
Thank you for taking the time to read through the tutorial, I hope it was helpful and that you learned a little something about active game menus.



View full post on Activetuts+
Dec 31, 2011
Posted on Dec 31, 2011 in Hints and Tips | 10 comments
With the year 2011 at a close, it is time to reflect upon some of the major industry events of the year. A lot happened… we’ll pick out some of the bits and pieces that will be most interesting to browser app and game developers from the world of industry, web, runtimes, operating systems, mobile, and more!
Early in the Year…
In the first part of this year, we saw the release of Android 3.0 “Honeycomb” – a tablet-specific version of the popular mobile operating system. One of the items that this version of the OS was faulted for was its initial lack of Flash Player support. This would later be remedied, but not before a lot of negativity was expressed over the omission. Now that the year is almost at its end, we have a greater understanding of what may have contributed to this delay… and it is a sad reminder that even for large enterprises, resources are far from limitless.

The year was still relatively young when March brought us more interesting developments. Adobe released a project on Labs, code-named “Wallaby”, an AIR application that converts specific FLA files to HTML-based output to perform animations in the browser when Flash is not supported (iOS/WP7), or when HTML output is desired. With Adobe now talking about HTML output directly from Flash Professional, one wonders whether that may be the end result of this prototype? The same month also brought us AIR 2.6 and Flash Player 10.2 for Android, which finally provided Honeycomb tablets with mobile Flash Player.
At this same time, Unity came out with a huge surprise announcement: future versions of the platform tools would be able to compile to SWF in order to support Stage3D in the Flash Player. This announcement opened up a whole lot of existing 3D tooling for Flash developers (especially since Adobe basically has no 3D tooling support for games), and a wider distribution market for current Unity developers as well. Both camps benefit! This was also a clear demonstration of Adobe’s initial strategy around Stage3D: allowing tooling providers and framework engineers to build higher-level components around the core Stage3D APIs.

We also saw an interesting move from Microsoft during this time, with a public effort by the company to convince users of IE6 to upgrade their browser through the ie6countdown.com website. When even Microsoft is running a campaign to get users to upgrade from IE6… well… need I say any more? The website is actually an informative little resource that tracks the decline of the much-despised browser. Here’s looking forward to 0%!
Springtime Advances…
A number of major announcements from Adobe occurred in the Spring, and seemed to center around the 360|Flex conference in Denver. First, Adobe announced Creative Suite 5.5 and an entirely revised release schedule: instead of a new version of the Creative Suite every 18 months, Adobe would be releasing a new version every year to keep tooling relevant in light of the rapid changes taking place on the web and through mobile devices. The announcement was followed a few weeks later by the availability of CS5.5 alongside major updates to Flash Builder, Flash Professional, and the Flex framework.

During 360|Flex, the Adobe Flex team took the stage to make another important announcement: the founding of a new relationship between Adobe and the community in the form of the Spoon project. While Flex had actually been an open source framework for years at this point, there was no organized way in which the community could actually contribute patches and changes in an acceptable fashion. The Spoon project would establish a modified fork (or spoon [oh, now I get it - Ed]) of the codebase that would be community driven. Patches from this fork would then be accepted and integrated into Adobe’s version of Flex as need be. Now that we sit at the close of this year, we can see how vitally important this announcement was to the current situation…
In other Adobe news, Flash Player 10.3 was released and Adobe demonstrated Flash Media Server 4.5 and the implementation of HTTP Live Streaming (HLS) – a form of streaming technology that chunks data into tiny packets for transport over the normal HTTP protocol while also allowing multi-bitrate support for varying devices and connection speeds. This enables FMS to stream video to iOS using the HTML <video> tag. Cool.

One of the bigger announcements that came out of the Google I/O conference this year was the Google Chromebook. The Chromebook is a netbook-class device that is meant to run only browser-based applications, resulting in super-fast startup times and persistent storage in the cloud. Google also announced a new update to Google TV built on Honeycomb. With this, not only would every user get the benefits of an updated Android OS, but the Android Market would be enabled on Google TV devices, allowing developers to target these systems alongside smartphones and tablets. (The lack of Market access on the original Google TV was a huge oversight, in the opinion of many developers.)
One last notable item for Spring was the release of the BlackBerry Playbook. This was a long time coming and provided customers looking for a powerful tablet device an alternative to iOS and Android, since the Blackberry Tablet OS is built upon QNX – known for its stability and overall reliability. Unfortunately, the tablet hasn’t really taken off since the device still doesn’t have a native email client, calendar, or Angry Birds*.
*Yes, I am kidding about Angry Birds. Mostly.
Summer…
A lot happened over the summer months. Flash Builder 4.5.1 was released by Adobe, adding full Flex mobile support for Android, iOS and Playbook. Prior to this, developers needed to use all sorts of tricks to compile applications for all these devices; with 4.5.1, it could all be done through the application GUI. At the same time, Adobe also released AIR 2.7 and mysteriously dropped support for AIR on Linux Desktop with the allowance that Open Screen Partner members may adopt the responsibility to get future versions of the AIR runtime on Linux distributions… although, at the time of writing, nothing has yet come of this. (What’s going on, Adobe?)

In Apple’s world, Mac OSX 10.7 Lion was released – marking what may be the first signs of iOS influence within the desktop operating system with an integrated app store and advanced gesture support. Many were taken aback by the integration of mobile-like elements and concepts into a desktop OS… but since then, Windows appears to be taking a similar path, so this is probably not going to be an isolated idea.
Google took a cue from Adobe’s “Wallaby” project and released their own Flash to HTML conversion tool called Swiffy. This tool differed from “Wallaby” in that it converted SWF files instead of FLA files, and used an entirely different output. Still, the spirit and limitations of both tools are shared: convert old Flash-based content (AS2, limited capability graphics) to something that can be read natively through web browsers.
In July Sony made news due to their joining the Open Screen Project, as well as their release of some interesting Android-based tablets. They also announced the “Adobe AIR App Challenge” to get developers interested in targeting their tablets using AIR 3 betas along with ActionScript Native Extensions (ANE) which targeted specific features of their hardware. With Adobe’s recent new focus on gaming, this was an attractive contest for developers to participate in and it gave users exposure to new possibilities with ANEs in AIR 3.
In strange tablet news, the HP TouchPad with WebOS was released – and then discontinued merely weeks later. This was notable for Flash developers since it was long expected that Adobe was working closely with Palm and then HP to get mobile Flash Player on PalmOS/WebOS devices. Obviously this was never to be. Since that time, users have been able to get Android running on the system, giving the tablet a certain post-mortem desirability.
Anyone who was at Adobe MAX last year will remember a prototype that was shown during the Sneaks called “Project EDGE” – which demonstrated an animation platform targeting HTML5, JavaScript, and CSS3. Adobe Edge Preview 1 was made available for download on Adobe Labs over the Summer and received a rather impressive number of downloads over the first week. While Edge Preview 1 was limited in functionality, it showed great promise.
Around the same time that Edge first saw the light of day, Adobe also launched a new beta resource website, called The Expressive Web. This is a project which Adobe has put together with the goal of creating both a resource and a showcase for some of the most creative and expressive features being added to the web. In addition to highlighting and providing information on 12 new HTML5 and CSS3 features, the site itself makes extensive use of new features such as CSS3 Transitions, CSS3 Transform, Web Storage and more to provide a visually compelling resource for learning about HTML5 and CSS3.
Summer also marked the end of the Adobe AIR Marketplace. The service existed for three years and was a good distribution channel for AIR applications at the time. Since then, a number of other markets have emerged on both mobile and desktop, making Adobe’s offering a bit redundant. One of the most unfortunate things about this closure is that a lot of people had links to the AIR Marketplace for app downloads… these all went dead on August 31st.
Autumn…
A few weeks before Adobe MAX, Microsoft held their BUILD conference at which they released a developer preview of Windows 8. This was the first hands-on of the new Metro interface borrowed from Windows Phone 7, and it was given mixed reviews by the press. The most startling revelation about Metro, though, was that Internet Explorer 10 running in Metro would have no support for browser plugins. Zero. No Flash Player, no Silverlight, no Java… nothing but HTML, CSS, and JavaScript. If a user wants to use any of these plugins, they must exit out of the Metro interface to bring up the “classic” version of IE10 within which plugins like Flash Player would function just as normal.

So now we have two major players in mobile – Apple and Microsoft – saying “no” to mobile Flash Player in favor of a pure HTML experience. (Unfortunately, this goes against the HTML5 spec, since the spec actually now allows <embed> as a valid element!) Even more shocking were the increased rumors that Microsoft may be scaling back hard on Sliverlight moving forward. A rough time for Silverlight developers, indeed.

October brought us Adobe MAX, at which Adobe revealed their new cloud platform, the Creative Cloud, and also a series of touch apps for tablets that aim to bring creative expression to tablet devices. While tablets are commonly seen more as consumer tools, Adobe wants to change that perspective and these tablet applications go some way toward that goal. The Creative Cloud also includes a subscription service to the Creative Suite for about $50 a license. Not too bad – but not everyone wants to be bound to a subscription model. We’ll see what the details are once this is all finalized next year.
There were also a number of new releases timed around Adobe MAX, including Flash Player 11, AIR 3, and Edge Preview 3. The Flash Runtimes included many great new features, among which is Stage3D (formerly Molehill) which allows full GPU-accelerated 3D rendering in the browser. In fact, during the Day 2 keynote, Adobe was able to show off the full Unreal engine (ported to AS3 using Alchemy) running in Flash Player 11. Pretty spectacular. It is also worth noting that practically all of the new touch apps were built with AIR 3.
Even with all of the great announcements for Flash developers, many who left MAX did so with a sense of foreboding… Adobe seemed to be talking up HTML a lot more than Flash – and if you didn’t go to any of the Flex futures sessions, you probably came away with a rather empty feeling. This would play out in the weeks ahead as Adobe made some rather dramatic decisions around the future of the platform.
Winter Falls… Hard
On November 9th, Adobe was scheduled to have its regular analyst meeting to talk about how things were going for the company and lay some groundwork for the direction of the year ahead. Also, as has become custom, everyone expected there to be a bit of restructuring and associated layoffs around the same time. What actually happened is something the industry is still reeling from.
Reports began spreading the evening before that Adobe was set to announce the end of the mobile Flash Player. There were also rumors that the entire Flash Professional team was laid off. Now, rumors are often just that and do not ever actually see the light of day. Many in the community thought that with Adobe being so strong on mobile Flash Player with so many successes that this had to be just another ugly rumor and could not possibly be true.

Unfortunately, this time, the rumor was 100% accurate. A press release and blog post the next morning confirmed that Adobe did intend to drop all future work on mobile Flash Player! Even more alarming was that statements around the dismissal of mobile Flash Player were always framed by statements declaring full support for HTML – even going so far as to point to HTML as the superior technology. This rightly upset a good number of Adobe’s strongest supporters in the Flash and Flex community. In addition, many well-known public figures at Adobe were part of a 750+ company-wide layoff. That’s 10% of the company’s total workforce. Ouch. For more information, I suggest reading Mike Chamber’s post about the situation. Fortunately, the rumor about the Flash Professional team has been declared false.
Later that week Adobe posted more information about their plans for Flex and revealed that the SDK would be contributed to the Apache Foundation and maintained by Spoon, Adobe, and the community at large. Spoon, if you recall, is an organization established in April of this year which had the goal of working with Adobe to open the Flex SDK up for greater community involvement. This is the next logical step in that process. Keep in mind that Flex has actually been open source since 2006… so this has been a lengthy process. Having all of these projects (including PhoneGap) now under Apache is a good move; the Apache Foundation is respected and established. Not only has Adobe contributed the Flex SDK, but also the new generation Falcon compiler (and an experimental version of the compiler called Flacon JS), BlazeDS, and an internal set of testing tools. Flex will not shrivel and die there – Adobe has now made some truly AWESOME contributions to the open source community!
To recap:
- Adobe is halting development on the mobile web browser version of Flash Player for Android. This effectively places future versions of Android on the same level as iOS regarding Flash Player.
- They are doing this as part of a massive reorg to shift resources to mobile AIR on Android and iOS. They are also focusing on tooling and contributions to open web standards. This is a good thing, overall.
- IMPORTANT: Flash through mobile AIR on iOS, Android, Blackberry is going nowhere and is being given more resources. Again, this is what most developers have been working with – not mobile Flash Player in the browser.
- Mobile Flash Player 11 is not going away on Android – but if Android handsets want to continue with new versions, they must license the source and compile it for their customers. It will remain available for download and use in the meantime.
- Mobile Flash Player source is being licensed to those who wish to compile for their own platforms (like Blackberry does now). So mobile Flash Player may not be going away at all. It depends on the partners.
- Adobe is also furthering efforts in HTML through projects like Dreamweaver, jQuery and WebKit contributions, Apache CallBack (PhoneGap), and notably their HTML/CSS/JS motion and interactivity solution Adobe Edge.
- Flex is being placed under the Apache Foundation (where PhoneGap will also reside) and will recieve continued (hopefully envigorated) support by the Spoon project, Adobe itself, and possibly other corporate contributors.
- An update for mobile Flash Player 11 will be provided for users of Android 4.0 (ICS) and Adobe will continue to support the runtime through security patches and bug fixes.
- A mix of good and bad news – the good was absolutely ruined by the way the bad was communicated.

Android 4.0 “Ice Cream Sandwich” was finally released in November. One of the great things about this announcement is that Google has released the source to both ICS and Honeycomb! All of the Android tablet manufacturers out there can finally take advantage of this resource. Even though Flash Player does not currently function with ICS, Adobe has committed to providing an update on Android that will get this working on the new OS.
In Flash runtimes news, a lot of Stage3D resources and demos have been popping up on the web. For a good resource on using Stage3D for games, I would recommend having a look at Adobe Flash 11 Stage3D (Molehill) Game Programming Beginner’s Guide by Christer Kaitila. Amazingly enough, even renounced console publishers such as Square-Enix are having a serious look at Stage3D and have begun demonstrating some games built with these technologies. Flash Player 11.1 and AIR 3.1 were released as well. For those who want a concise, FREE resource to what is new in each of these runtimes; I suggest you check out a set of books published by O’Reilly as part of the Adobe Developer Library: What’s New in Flash Player 11 and What’s New in Adobe AIR 3. (Okay, yes, I am the author of these books but I do not get any royalties from them since they are free!)
The web standards community set up movethewebforward.org which aims to get individuals involved in learning and contributing to standard web technologies in their own way. It’s a particularly good resource for those who may need some guidance along the current web landscape, though it does look like there’s something for everyone here.
In a surprise move by HP, WebOS is going to be contributed to the open source community. It appears that the OS is far from dead, and HP hasn’t ruled out the manufacture of new devices which utilize the WebOS platform. Never count anyone out.
Adobe hosted a small “Flex Community Summit” in San Francisco with 20 Flex developers from the community to discuss the future of the Flex framework. The stated goal of the Summit is to “fix the confusion, provide clarification, and rebuild trust.” Some of the most important takeaways from this discussion include:
- There were robust apologies from Adobe executives around how the messaging was handled.
- “For years to come Flex is going to be the best way to make applications for the web and desktop.” -Danny Winokur (Adobe)
- Adobe’s involvement in future Flex will include “dozens of people”.
- Apache Flex will target release runtimes.
- AIR, Flex, and Flash Player (non-mobile) will continue to be supported.
- “Flash isn’t just focused on gaming and video. Gaming helps push the envelop, but everyone can benefit from the improvements.”
- “Adobe is committed to building applications with both Flex and HTML5, not just HTML5.”
- “We have every interest that our runtime technology [Flash/AIR] is supported across as many platforms possible.”
- Flash Catalyst has been discontinued. Design View in Flash Builder is slated for removal.
- The new “Falcon” compiler will be ready for AS3 compilation in 2012. MXML compilation may be 2013.
- Falcon is built to allow many back-end compilers such as FalconJS – the idea being that a developer can write in AS3/MXML and compile the code using Falcon, then cross-compile the output for JavaScript or other languages.
- There was a great overview of the Apache Software Foundation process by Roy Fielding, an ASF founder.
- Adobe will no longer sign RSLs, this will be done through Apache.
- Proposal for Apache incubator is almost ready.
- A Flex whitepaper will be published in January.
There is still much to be done, but it is a good thing that things are moving forward in a positive way. 2012 will be an interesting year for sure.
We close the year with rumors that Silverlight 5 will most likely be the final version of that runtime. While Silverlight never caught on the way Microsoft originally positioned it (as a “Flash killer”), it is sad that so many developers who invested their time in the technology could be left with an abandoned runtime. Silverlight did much to spur Adobe to action – ramping up development efforts for the runtimes and tooling. Without competing technologies, there is always the possibility of complacency… and that’s good for no one.



View full post on Activetuts+
Dec 29, 2011
Posted on Dec 29, 2011 in Hints and Tips | 10 comments
In this tutorial, you will learn how to cast a field of view of a turret guarding a specific location. When an enemy is within the turret's field of view, the turret will shoot at them. Vector math will be used to help in implementing this field of view.
Final Result Preview
Let's take a look at the final result we will be working towards. Click on the turret at the bottom of stage to begin the simulation.
Step 1: Field of View
I’m sure most readers have used cameras. Every camera has a view angle, defined by the type of lens attached. There are narrow and wide view angles. View angles constrain the field of view into a sector. From a top-down position, they look like the diagram below. If you take a picture, eveything within the grayed area will be captured.
The turret's field of view in our simulation is like that of a camera. If there's an enemy within its field of view, a guard will respond (sound an alarm, take aim, shoot, etc).
Step 2: Basic Concept
The diagram above shows the field of view of turret. Usually the angle of view will be equal on both the left and the right. The radius will also be consistent throughout the sector. So to check whether an enemy is within a turret's field of view, these two mathematical conditions can be used:
- Distance between turret and enemy is less than radius.
- Angle from turret's line of sight to enemy is less than 30°.
Step 3: Define Field of View Using Vector
We shall use vector math to help us. In this case, the vectors in consideration are vLine2 and vLine3. We can:
- Compare magnitudes of vLine2 and vLine3 to validate Condition 1 from Step 2.
- Compare angle sandwiched between vLine2 and vLine3 to validate Condition 2 from Step 2.
Using the formula of dot product between Vectors, we can find the angle sandwiched between two vectors. I have included a Flash presentation above to facilitate your understanding. Click on the buttons at the bottom to scroll through the frames.
Here is the Actionscript in Vector2D (which I’ve used in previous tutorials, like this one) that does the job. Note that line 257 helps to determine whether the angle is on the negative or positive side. However, this is not going to help us much here as direction is not important. More explanations on this topic in the next part of this series.
/**
* Method to obtain the smaller angle, in radian, sandwiched from current vector to input vector
* @param vector2 A vector to bound the angle
* @return Angle in radian, positive is clockwise, negative is anti-clockwise
*/
public function angleBetween(vector2:Vector2D):Number
{
//get normalised vectors
var norm1:Vector2D = this.normalise();
var norm2:Vector2D = vector2.normalise();
//dot product of vectors to find angle
var product:Number = norm1.dotProduct(norm2);
product = Math.min(1, product);
var angle:Number = Math.acos(product);
//sides of angle
if (this.vectorProduct(vector2) < 0) angle *= -1
return angle;
}
Step 4: Implementation
I have included a presentation below that implements the concept of field of view. Feel free to click and drag the bigger gray circles around. Observe area covered by the field of view indicated by darker dots.
Step 5: Important ActionScript
If you'd like to see the ActionScript for the presentation above, feel free to open up AppFan.as from the source download – it’s commented to facilitate understanding. I shall only include here the important snippet that checks the conditions.
I've highlighted the conditional statement that each of the little dots on the stage is evaluated against it to see if its within the highlighted area.
//Calculate the magnitude and angle
var vLine2:Vector2D = new Vector2D(b2.x - b1.x, b2.y - b1.y);
var vLine3:Vector2D = new Vector2D(b3.x - b1.x, b3.y - b1.y);
var ang:Number = Math.abs(vLine2.angleBetween(vLine3)) //Eliminate directional feature of angle
var mag:Number = vLine2.getMagnitude();
for each (var item:Ball in sp) {
var vParticle1:Vector2D = new Vector2D(item.x - b1.x, item.y - b1.y);
//Checking if falls within sector
//Condition: Magnitude less than mag, angle between particle ang vLine2 less than ang
if(Math.abs(vLine2.angleBetween(vParticle1)) <ang
&& mag> vParticle1.getMagnitude()){
item.col = 0x000000;
}
//if outside of segment, original color
else item.col = 0xCCCCCC;
item.draw();
}
Step 6: Variations
To add variation to the use of field of view, we can implement far and near attenuation. In fact, we just went through far attenuation. For far attenuation, enemies that are further away (further than the far attenuation distance) cannot be seen by the turret. For near attenuation, enemies that are too close (less than near attenuation) cannot be seen by turret. This may sound irrational, but imagine the turret sitting on a high cliff while the enemy sneaks right under the cliff.
Okay, perhaps you are not convinced, so here is another example of different use. A guard carries a short sword, a bow and arrows. When an enemy is too far off, he may just want to keep a close eye on him. When the enemy comes within shooting range, he shoots arrows. When the enemy comes too close, he fights with short sword. You may even implement different types of guards: bowmen and swordsmen. Enemies within shooting range are dealt with by bowmen while those at at close range are dealt with by swordsmen.
By understanding the conditions introduced in Step 2, variations can be introduced into our simulation or game.
Step 7: Define Field of View Conditions
I’ve included a Flash presentation below to showcase different cases and their corresponding set of conditions. Click on the buttons to check out the different cases.
Step 8: Programming Field of View Conditions
The following is a snippet of code for implementing the conditions as laid out in Step 7. You may want to view the whole source code in Region2.as to check out the whole implementation.
//Checking done every frame
private function move(e:MouseEvent):void
{
//Calculate Vector from guard to enemy
var g_e:Vector2D = new Vector2D(enemy.x - guard.x, enemy.y - guard.y);
var angle:Number = r3.angleBetween(g_e);
//Conditions
var withinSector:Boolean = Math2.degreeOf(Math.abs(angle)) < sector;
var withinR3:Boolean = g_e.getMagnitude() < r3.getMagnitude();
var withinR2:Boolean = g_e.getMagnitude() < r2.getMagnitude();
var withinR1:Boolean = g_e.getMagnitude() < r1.getMagnitude();
//Difference example cases
if (example == 0) {
if (withinSector && withinR3) {
t1.text = "Within FOV"
}
else t1.text = "Beyond FOV"
}
else if (example == 1) {
if (withinSector && withinR3 && !withinR1) {
t1.text = "In between \nfar and near attenuation"
}
else t1.text = "Beyond FOV"
}
else if (example == 2) {
if (withinSector) {
if (withinR1) t1.text ="Sword attack"
else if (withinR2) t1.text = "Arrow shoot"
else if (withinR3) t1.text = "Keep observe"
}
else t1.text = "Beyond FOV"
}
}
//Swapping example cases in response to changes in context menu
private function swap(e:ContextMenuEvent):void
{
//swap example
if (e.target.caption == "Basic FOV") example = 0;
else if (e.target.caption == "Far/Near Attenuation") example = 1;
else if (e.target.caption == "Observe/Arrow/Sword") example = 2;
//Redraw region indicating detection area
drawRegion();
}
Step 9: Implementation
Here's an implementation of ideas explained in Step 6. Click on the black circle and drag it aroud the stage to check whether it’s sitting within the visible region. Right-click on stage to pop context menu out, then select from "Basic FOV", "Far/Near Attenuation" and "Observe/Arrow/Sword" to check out the different examples.
Step 10: The Scenario
Now to put into context whatever we have learnt, we are going to create a simulation. Here's the scenario:
A turret is stationed at one end of the stage. Its role is to eliminate as many troops that invade its space as possible. Of course, turret will have to see those troops (within field of view) in order to shoot lasers – and bye-bye troops. Since it can only shoot a beam of laser at any instance, it’s going to choose the closest enemy in sight.
On the other hand, troops will try to successfully cross to the other side. They will have to cross a river and, as they do, they will slow down. Now these troops are going to respawn on top of stage whenever they die or go out of stage.
Step 11: Basic Setup
The implementation of this example will be hard-coded. The basic setup is as below. On initialisation we will draw the graphics of elements (river, troops, turret) and position then nicely. On clicking on the purple turret, animation will start. On every frame we will see them animate according to the behaviours of each element.
public function Scene1() {
makeTroops();
makeRiver();
makeTurret();
turret.addEventListener(MouseEvent.MOUSE_DOWN, start);
function start ():void {
stage.addEventListener(Event.ENTER_FRAME, move);
}
}
private function move(e:Event):void {
behaviourTroops();
behaviourTurret();
}
Below are the variables of this class.
private var river:Sprite;
private var troops:Vector.<Ball>;
private var troopVelo:Vector.<Vector2D>;
private var turret:Sprite;
private var fieldOfView:Sprite;
private var lineOfSight:Vector2D = new Vector2D (0, -300); //line of sight facing north
private var sectorOfSight:Number = 20 //Actually half of sector, in degrees
Step 12: Draw and Position River
Drawing and positioning river. Pretty simple.
private function makeRiver():void {
river = new Sprite; addChild(river);
//Specify the location & draw graphics of river
with (river) {
x = 0; y = 150;
graphics.beginFill(0x22BBDD, 0.2);
graphics.drawRect(0, 0, 500, 50);
graphics.endFill();
}
}
Step 13: Draw and Position Troops
Drawing troops will be simple. However, I wanted a "V" formation on troops. So I position the troop at the bottom of "V" first, followed by troops on both sides of its wing. You may want to adjust its center position through center and the spacing between troops through xApart and yApart. Note that troops and its corresponding troopVelo share the same index. All troops are heading south.
private function makeTroops():void {
troops = new Vector.<Ball>; //Initiate troops
troopVelo = new Vector.<Vector2D>; //initiate velocity
//local variables
var center:Vector2D = new Vector2D(stage.stageWidth * 0.5, 150);
var xApart:int = 20; var yApart:int = 15;
//Locating troops & velocities
var a:Ball = new Ball; stage.addChild(a); troops.push(a);
a.x = center.x; a.y = center.y;
//troops heading south
var aV:Vector2D = new Vector2D(0, 1); troopVelo.push(aV);
for (var i:int = 1; i < 11; i++) {
var b:Ball = new Ball; stage.addChild(b); troops.push(b);
b.x = center.x + i * xApart; b.y = center.y - i * yApart;
var bV:Vector2D = new Vector2D(0, 1); troopVelo.push(bV);
var c:Ball = new Ball; stage.addChild(c); troops.push(c);
c.x = center.x - i * xApart; c.y = center.y - i * yApart;
var cV:Vector2D = new Vector2D(0, 1); troopVelo.push(cV);
}
}
Step 14: Draw and Position Turret
Here, we shall draw, position, and orient the turret and its field of view to face north towards the enemy. Note that the line of sight is facing north.
private function makeTurret():void {
//instantiate, locate, orient turret
turret = new Sprite; stage.addChild(turret);
turret.x = stage.stageWidth * 0.5,
turret.y = stage.stageHeight;
turret.rotation = -90;
turretRot = 2; //rotation speed
//Draw turret graphics
var w:int = 30; var h:int = 10;
turret.graphics.beginFill(0x9911AA);
turret.graphics.lineStyle(2); turret.graphics.moveTo( 0, -h / 2);
turret.graphics.lineTo(w, -h / 2); turret.graphics.lineTo(w, h / 2);
turret.graphics.lineTo(0, h / 2); turret.graphics.lineTo(0, -h / 2);
turret.graphics.endFill();
//Setting data for field of view's graphics
var point1:Vector2D = new Vector2D(0, 0);
var point2:Vector2D = new Vector2D(1, 0);
var point3:Vector2D = new Vector2D(0, 0);
point1.polar(lineOfSight.getMagnitude(), Math2.radianOf(sectorOfSight));
point2.setMagnitude(lineOfSight.getMagnitude()/Math.cos(Math2.radianOf(sectorOfSight)));
point3.polar(lineOfSight.getMagnitude(), Math2.radianOf(-sectorOfSight));
//instantiate, locate, orient field of view
fieldOfView = new Sprite; addChild(fieldOfView);
fieldOfView.x = turret.x; fieldOfView.y = turret.y;
fieldOfView.rotation = -90;
//draw turret's field of view
fieldOfView.graphics.beginFill(0xff9933, 0.1);
fieldOfView.graphics.lineStyle(1);
fieldOfView.graphics.moveTo(0, 0);
fieldOfView.graphics.lineTo(point1.x, point1.y);
fieldOfView.graphics.curveTo(point2.x, point2.y, point3.x, point3.y);
fieldOfView.graphics.lineTo(0, 0);
fieldOfView.graphics.endFill();
}
A little detail here on the drawing the line of sight. I’ve included image below for clarification:
Step 15: Troops' Behaviour
Troops will be animated across time. Here's their behaviour. Note that the last two lines of code are commented. If you would like dead troops to be removed from animation, you may uncomment them.
//troops' behaviour
private function behaviourTroops():void
{
//for each troop
for (var i:int = 0; i < troops.length; i++) {
//If troop reach bottom of screen, respawn on top of screen
if (troops[i].y > stage.stageHeight) {
troops[i].y = 0; troops[i].x = Math.random() * (stage.stageWidth - 100) + 100;
}
//if wading through river, slow down
//else normal speed
if (river.hitTestObject(troops[i])) troops[i].y += troopVelo[i].y*0.3;
else troops[i].y += troopVelo[i].y
//If troop is dead ( alpha < 0.05 ), respawn on top of screen
if (troops[i].alpha < 0.05) {
troops[i].y = 0; troops[i].x = Math.random() * (stage.stageWidth - 100) + 100;
troops[i].col = 0xCCCCCC; troops[i].draw(); troops[i].alpha = 1;
//stage.removeChild(troops[i]); troops.splice(i, 1);
//troopVelo.splice(i, 1);
}
}
}
Step 16: Turret’s Behaviour
The turret will guard its post by panning its field of view around, but within certain angles. Here, I’ve defined the panning angle to be between -135 and -45 (using Flash angles). If there's an enemy within sight, it will attack it. But if there's more than one enemy, it's going to choose the closest to attack.
//turret's behaviour
private function behaviourTurret():void
{
//rotate turret within boundaries of -135 & -45
if (turret.rotation > -45) turretRot = -2
else if (turret.rotation < -135) turretRot = 2
//shoot closest enemy within sight
graphics.clear();
if (enemyWithinSight() != null) {
//closest enemy in sight
var target:Ball = enemyWithinSight();
target.col = 0; target.draw(); //turns to black &
target.alpha -= 0.2; //health deteriorates
//orient turret towards enemy
var turret2Target:Vector2D = new Vector2D(target.x - turret.x, target.y - turret.y);
turret.rotation = Math2.degreeOf(turret2Target.getAngle());
//draw laser path to enemy
graphics.lineStyle(2); graphics.moveTo(turret.x, turret.y); graphics.lineTo(target.x, target.y);
}
//no enemy within sight, continue scanning
else { turret.rotation += turretRot }
//turn field of view and line of sight of turret according to turret's rotation
fieldOfView.rotation = turret.rotation;
lineOfSight.setAngle(Math2.radianOf(turret.rotation));
}
Step 17: Getting Closest Enemy
The turret will locate the closest enemy in its field of view and react by shooting a laser at it. To see how it finds the closest enemy, check out the ActionScript implementation below.
//return the closest enemy within sight
private function enemyWithinSight():Ball {
var closestEnemy:Ball = null;
var closestDistance:Number = lineOfSight.getMagnitude();
for each (var item:Ball in troops) {
var turret2Item:Vector2D = new Vector2D(item.x - turret.x, item.y - turret.y);
//check if enemy is within sight
//1. Within sector of view
//2. Within range of view
//3. Closer than current closest enemy
var c1:Boolean = Math.abs(lineOfSight.angleBetween(turret2Item)) < Math2.radianOf(sectorOfSight) ;
var c2:Boolean = turret2Item.getMagnitude() < lineOfSight.getMagnitude();
var c3:Boolean = turret2Item.getMagnitude() < closestDistance;
//if all conditions fulfilled, update closestEnemy
if (c1 && c2&& c3){
closestDistance = turret2Item.getMagnitude();
closestEnemy = item;
}
}
return closestEnemy;
}
Step 18: Launching Simulation
You may now press Ctrl + Enter in FlashDevelop and observe this simulation. Click the turret to start the demo below.
Step 19: A Step Further
We can make use of this understanding to:
- Implement a field of view for enemies.
- Implement more turrets.
- Introduce variation to the field of view as explained in Step 9.
…and so on.
Hopefully, this will spark some ideas and perhaps help in your next simulation or game.
Conclusion
Thanks for reading. As usual, do drop a comment to let me know if this has been helpful to you. I'll be writing the next tutorial to check out how enemies can stay out of turret's field of view by "hiding" behind obstacles. Stay tuned.



View full post on Activetuts+