Flash Games Programmer - FFD issue #4 (2/2009)

Page 1




Editor’s Note Dear FFD Readers,

A

t the beginning of the new year we made a promise to you to improve, improve, improve... And, that is what we are doing! We have already started making improvements in Flash & Flex and your are ultimately the winner. Even during the economic crisis that is spreading over the globe, we are not letting it effect us or you - our community. We have added 14 additional pages to the magazine and two additional issues per year! Just that good news alone should pull the world out of recession. So, sit back in your favorite reading chair and read the great articles that we hand picked just for you in this issue. Let’s take a peak inside to see what is in this issue. First, set your calendar for June 7th through the 10th and attend the Flashbelt Conference. Read Dave Shroeder’s Interview on page 8, who is the founder and producer of the conference. Give yourself a fresh dose of Flash & Flex learning material. Check out the article on the new features of Flash - CS4 - Bone Tool - on page 18. You will learn how to use Bone Tool to create (IK) animations. Are you a Nintendo Wii fan? FFD has a great tutorial on how to connect your Wii using Flash on Page 22. Ever want to know more about Model-View-Controller (MVC)? How about Cairngorm? Then check out Page 40, to fulfill your cravings for this knowledge. Flip through and read the rest of the articles and I’m sure you will find something to pique your interest. A little dessert is nice after a big meal, so check Page 86, to read how to become a Flash game programmer. There is also a great interview with Lee Brimelow, on Page 92. Don’t miss it. Also, check out our advertisers and visit their sites and consider purchasing their products. They help support the magazine, so we can produce it for you. I hope that you find the articles in this issue interesting and stimulating. As the FFD magazine’s Editor-in-Chief, I am proud to be part of this incredibly successful publication and the community it has created. This position is educational, very challenging, exciting, and equally rewarding as it is demanding. Ultimately, it is you, the reader, that creates this stellar magazine with your feedback, comments and article suggestions. That is the greatest reward that I can receive, along with the members of our Editorial Board. I hope FFD magazine continues to evolve to exceed your expectations. Special Thanks to our Beta Testers and Proofreaders, who have helped me with this special issue. Without their assistance there would not be an FFD magazine.

Ewa Samulska ewa.samulska@ffdmag.com

Editor in Chief: Ewa Samulska ewa.samulska@ffdmag.com Executive Editor: Ewa Dudzic ewa.dudzic@ffdmag.com Junior Editor: Marta Kobus marta.kobus@ffdmag.com DTP Team: Ireneusz Pogroszewski ireneusz.pogroszewski@software.com.pl Przemysław Banasiewicz przemyslaw.banasiewicz@software.com.pl Art Director: Agnieszka Marchocka agnieszka.marchocka@software.com.pl Senior Consultant/Publisher: Paweł Marciniak Production Director: Marta Kurpiewska marta.kurpiewska@software.com.pl Subscription: customer_service@software.com.pl Publisher: Software Wydawnictwo Sp.z.o.o 02-682 Warszawa, ul. Bokserska 1 Poland Worldwide Publishing

Business addres: Software Media LLC 1521 Concord Pike, Suite 301 Brandywine Executive Center Wilmington, DE 19803 USA Tel: 1 917 338 3631 Tel: 1 866 225 5956 www.ffdmag.com

Software Media LLC is looking for partners from all over the World. If you are interested in cooperating with us, please contact us by e-mail: cooperation@software.com.pl

Distributed in the USA by: Source Interlink Fulfillment Division, 27500 Riverview Centre Boulevard, Suite 400, Bonita Springs, FL 34134 Phone: 239-949-4450. Whilst every effort has been made to ensure the high quality of the magazine, the editors make no warranty, express or implied, concerning the results of content usage. All trade marks presented in the magazine were used only for informative purposes. All rights to trade marks presented in the magazine are reserved by the companies which own them.

To create graphs and diagrams we used company.

program by

The editors use automatic DTP system Mathematical formulas created by Design Science MathType™

ATTENTION!

Selling current or past issues of this magazine for prices that are different than printed on the cover is – without permission of the publisher – harmful activity and will result in judicial liability.

DISCLAIMER!

The techniques described in our articles may only be used in private, local networks. The editors hold no responsibility for misuse of the presented techniques or consequent data loss.

Printed in Poland by: 101 Studio, Firma Tęgi

4

02/2009 (4)



Contents Special Report 8 Flashbelt Conference

FLASHBELT Interview with Dave Schroeder about Flashbelt Conference

Tools 10 SecureSWF Professional CHETAN AKARTE

12 Wildform Flair COLBY DEVITT

14 Wix web publishing platform ALLON BLOCH

CHRISTOPHER W.ALLENPOOLE From this article you will learn about Flash JavaScript API.

52 SWX: The Native Data Format for Adobe Flash

R.JAN MACDONALD In this article you will learn how to move data between your serverside code and Flash using SWX.

56 An introduction to Flickr in Flash

JASSA AMIRLANG In this article Jassa presents the basic steps needed to get started with the AS3 Flickr Library.

62 Flash video and AS3

16 Bannersnack BANNERSNACK.COM

CHAIM SAJONVSKY You will learn about the three elements in a Flash video: NetConnection, NetStream and the video object.

For Beginners

Server Side Interaction

18 Working With Flash CS4 New Features: Inverse kinematics (IK) With Bone Tool

66 WebORB tricks

CHETANKUMAR You will learn about recent updates to Flash CS4. Work with Flash CS4 Bone Tool.

VITALIY MORARIAN This article will walk you through hidden issues of WebORB.

70 Multi-user Applications in haXe

ActionScript Developement

LEE MCCOLL SYLVESTER This article takes a look at how you can easily develop a powerful multi-user server and Flash client using haXe language.

22 Connecting the Wii to Flash

Sound and Animation

ALMONG KOREN Almong Koren is going to show you how to connect your Wii's remote to your computer and how to implement basic Flash code.

24 Tracking Time with Screenweaver HX

LEE MCCOLL SYLVESTER In this article Lee McColl Sylvester will demonstrate that you do not have to be a hardcore programmer to develop rich desktop applications.

30 Using all the different components within CS4 to built a complete site – part one

JUSTIN P. JUNDA This tutorial will give you a basic understanding of how to use components and implement them into your work flow.

40 Model View Controller – What's the Secret Sauce..?

ANTON KRASNOSHCHOK Anton explains what the Model-View-Controller Pattern is and how to use View and Controller together.

6

46 JSFL Quirks

76 Achieving a retro-style look in Flash

TEM TUPAC AGUERRE In this tutorial you will lear how to achieve a late 70's – early 80's look using nothing but Flash.

88 Secrets of professional Flash game programmer

TOM RASSWEILER Practical tips for designing your Flash games to be flexible, versatile and more cost effective.

Interview 92 Interview with Lee Brimelow FFD TEAM

Books Review 94 Reviews of two great books

02/2009 (4)



Special Report

Flash Flex developer interview with Dave Schroeder about the Flashbelt Conference by FFD Magazine

.

0

JUN

N

ow in it's 6th year, Flashbelt is the annual conference that serves the midwest Flash community. It takes place every June in Minneapolis, Minnesota. By all accounts it presents the same high profile speaker rosters as other Flash conferences like FITC, Flash on the Beach and FlashForward. However, attendance is limited to just 400 seats, sold for under $400, making for a notably different conference experience. FFD caught up with Dave Schroeder, the founder and producer of the event, to talk about the event.

1 E7

9 200

our thing. I want people to make connections, and attendees to be able to access the speakers throughout the conference. That's why we limit the number seats to 400. It allows us to keep the event personable, and that keeps it fun. I always say We keep it small to keep it cool.

How did it start? Since 2000 I've been running Pilotvibe, which specializes in music and sound design for interactive media. Almost all of the people I work with use Flash, and I've always been a

NN I M

E

O AP

L

M I S,

N

big fan of what the platform makes possible. There were always lots of people and agencies doing great things with it in the midwest, but the community was fragmented at best. It didn't really have a place or way to connect and so Flashbelt came about as an event to foster some community building. The first year it was a one-day event, and I was really lucky to get some great speakers to agree to participate. Since then it's just grown. I'm still amazed at how often people thank me for starting it and that they're looking forward to the next one. It seems to be working in terms of helping the community grow, and it keeps people excited about advancing their Flash skills.

Why should people attend Flashbelt? It's a great chance to be surrounded by people who speak your language. Whether you’re a

How does one earn a Flashbelt? (OK – what is Flashbelt?) Well, you have to attend for sure, but at this point we only have Flashbelt t-shirts and track jackets, no karate accessories. I've always wanted to get some big old blingy flashbelt buckles made. OK. The name flashbelt plays off other nicknames for the midwest like the grain-belt and rust-belt. It's 4 days of all things Flash. A day of workshops, 3 days of sessions along 3 content tracks: Design, Develop, and Engage. The goal is to educate and inspire attendees and keep them on their path towards world domination via Flash. We find people from around the world who are leading the pack and we drop them in the middle of the midwest to give sessions. Since the beginning I've wanted to create an event that would have high caliber content, and be truly valuable to attendees in terms of an opportunity to learn. At the same time I wanted a casual atmosphere where people are treated like adults. Herding isn't 8

02/2009 (4)


Flashbelt Conference

designer or a developer you can talk about your work and people understand what you're doing. Not only that, they often have ideas or solutions, or even good questions that allow attendees to grow from their conversations. Of course, being able to chat with your favorite book authors or award winners in person is really special. I know that it can be hard for a lot of people to keep up to speed with everything that's out there. This industry advances really fast. Most people are too busy with work to explore all the new cool stuff. Flashbelt gives people a chance to catch up. It provides attendees with the foundation and inspiration to learn things they've been curious about. For example, last year and attendee wrote me and said that she had been avoiding making the jump from AS2 to AS3, but at flashbelt she finally got motivated to do it. I know people have fun, but they attend because they care about their profession first and foremost. It also gets people in to new things. We have things like mini Processing workshops, or an Introduction to physical computing sessions and people love it. It gets them into something they've been curious about for a long time but haven't explored. This year were' doing a MAXmsp session that I think will really get people thinking in new ways.

What's the best thing about it? Seeing and hearing how much people enjoy the event. I like to bring people together and I like to think that Flashbelt is a special opportunity. Needless to say, putting it together takes a lot of work, and causes some sleepless nights. Every year just before the conference I usually think, Never again..never again. I'm losing my mind over this. But as soon as it's over I'm already planning for next year. The people are the motivating factor. It's a great community, full of really interesting, creative and kind people.

What's the most difficult thing about it? Putting the content together is always the hardest part. There are so many good topics to try and cover and tons of amazing work out there, but there's no way to include it all. Having too many options isn't a bad thing, but it can be hard to decide what to cover, or who to invite. The goal is to have a good balance of content across the three tracks and try to appeal to a variety of skill levels. I call it the content puzzle. It takes more energy to solve than you'd expect.

Why do you think flash conferences are important? As I mentioned earlier, it's great way to catch up on the latest things going on around the Flash world. I think people who take the software and try to make it do what they wish it could do have always driven the Flash community.

That's how it really advances. Adobe builds in many of the capabilities, but individuals tend to be the best at taking advantage of those capabilities. They also come up with some of the best solutions to common problems. I'm lucky enough to get guys like Geoff Stearns back every year. He created SWFObject. He's made life so much easier for so many people. Or Robert Reinhardt. Does anyone know more about Flash Video? His books and websites are full of really useful, original formulas and tables. The opportunity to learn directly from people like this is invaluable. By the same token we bring in people doing amazingly creative work. Robert Hodgin, Joshua Davis, Jeremy Thorp, Andre Michelle...I could go on and on. The inspiration that people get from seeing these guys speak is amazing. That inspiration is a big part of keeping your work fresh and maintaining the drive to keep exploring. One of my favorite feedback comments last year was something like It's the annual kick-in-the-Flashbrain-pan I need.

What's the plan for 2009? With CS4 there's a lot of new things to talk about. There's going to be a nice amount of fresh info and plenty of projects to look at being made with the new tools. I'm also excited to have several speakers for 2009 that I've been hoping to bring for a few years. Fortunately, over the years Flashbelt has developed a reputation as a pretty cool event, and that helps make it possible to bring people that might not otherwise participate in a conference it's size. And frankly the budget for bringing more people in from overseas has improved thanks to sponsors. Flashbelt has some great sponsors who really understand the character of the event. Of course, we'll end the conference with a party at Nye's, the best bar in America. 02/2009 (4)

9


Tools

secureSWF by Chetankumar Akarte

I

n the world of web development security plays an important role. Now the day's Flash applications are easy to reverse engineer. Once that happens the fully unencrypted, unobfuscated code is in plain view. This may affect seriously on your business. Hacker can easily track your licensing code, copy protection mechanisms. To protect your work and increase security secureSWF is the most sophisticated ActionScript obfuscation, code protection, and SWF encryption solution for Adobe's Flash and Flex. It makes code confusing and harder to understand. Obfuscation removes context from compiled code that humans (and decompilers) would use to decipher the code's meaning. The trick is to remove this context from evil intentions while retaining complete execution integrity with the original program. The goal of obfuscation is to make the process of reverse engineering extremely time consuming and painful so that

Product: secureSWF Version: Version 3.1 Platforms: Windows, Mac OS X, and Linux (Requires Java VM 1.5 or later.) Manufacturer: Kindisoft LLC Website: http://www.kindisoft.com Cost: Perpetual license: Personal $99, Standard $199, Professional $400

it is not worth the effort. The goal is to stop all casual hackers and as many serious hackers as possible. Kindisoft's products have accomplished this completely – your program will produce the same results as it did before obfuscation but the code is far more difficult to reverse-engineer. secureSWF also provides Encrypted Domain Locking mechanism. You can use the Encrypted Domain Locking feature to specify a number of domain names for your SWF files to work under. Restrict you application to get launched offline or from another website which prevent others from copying your Flash application and using it on other websites or offline. The secureSWF apply code optimizing techniques which optimize swf size and make lighter to play. secureSWF take care of: • • • • • •

Code obfuscation Code Optimization Code Transformation Literal Strings Encryption Encrypted Domain Locking Identifiers renaming

Figure 1. Identifiers Renaming

Figure 2. Project Files

10

Using secureSWF secureSWF provide GUI as well as CLI interface. Command-line interface (CLI) allows features like batch execution and builds process integration. Us of CLI may vary from OS to OS but the flexibility and usability always same. secureSWF has a handy Graphical User Interface consists of four main sections; Project Files, Identifiers Renaming, Protection Options, and Operations' Summary. Project Files – allows you to quickly add protection to any file. Click on the Add button and select the SWF file(s) that you wish to protect. Select one of the Protection Presets available to protect your file. Even you can define your own preset to protect your file(s). Identifiers Renaming – secureSWF rename identifier in your SWF file from variables and functions names to frame labels and symbol names in addition to AS3 and AS2 classes. Not only that, but also secureSWF automatically determines the identifiers that are safe to rename and the identifiers that are not. You are free to add your own rules of Identifiers Renaming. To do all this you need to make sure that the Rename Identifiers checkbox is checked. Protection Options – secureSWF offers four different methods to protect your source code from reverse engineering. Also offer optimization to reduce size of swf and enhance the execution speed. You can also Encrypted Domain Locking here. Fully functional evaluation copy of secureSWF Professional edition is available for download at http://www.kindisoft.com/.

Figure 3. Protection Options

02/2009 (4)



Tools

Cut your costs and increase your profits without compromising your clients by using Wildform Flair by Colby Devitt

W

hen a real estate agent hired Tim Vondrell, owner of Visionary Video Productions, to shoot and produce video for a five-story house in town, he leapt at the chance. The house has a special place around here. It is a huge, gorgeous, extremely unique house designed by a physician who was tragically hit and killed by an oil tanker before he ever got to live in his dream house. He left behind a wife and eight children and they need to sell it. All of us in town have a soft spot for the family and we want to help them out.

The Project As Tim was shooting the video for the house, he thought about the process that he and his wife went through when they bought their own house a few years ago. As real estate shoppers they viewed a lot of online real estate tours and both he and his wife always had one complaint: they could never tell from the videos where each room in the house was. Room flow and layout were very important to us, Tim said, especially to my wife. Tim got the idea to have a virtual tour that was linked to a floor plan so that potential buyers could click on a room in the floor plan and the video of that room would start to play. I also wanted to be able to let people scrub through the video so that they wouldn’t have to watch the whole thing from beginning to end, he says. Tim knew that what he wanted to make would be incredibly valuable to real estate agents who were hankering for ways to stand out among their competition and move their properties. He realized that creating interactive video presentations for real estate agents was a potential new niche market for his business. The key would be to create an interactive video real estate presentation template which he could customize for each agent. Tim pitched his idea to the real estate agent, Rae Beasely. The good news was that Rae Beasely loved the idea. The bad news was that neither Tim nor anyone on his team knew how to create what he had just pitched to her. In business since 1993, the Visionary Video Productions 12

folks were experts in video production, not web design. Tim eyed the unused books about Flash on his shelf. He wanted to get this project done quickly and did not have time to crack open the books and start learning Flash. Tim called some design firms and started pricing out the job. He learned that an interactive video presentation with a video synched to a floor plan was something that could be done in Flash or Flex. However, the initial project would costs thousands of dollars and could take several weeks to complete. Plus, he would have to pay a designer for changes to all subsequent presentations. The price quotes Tim received were too expensive. He knew that real estate agents were not inclined to pay a lot. In this economic climate he needed to find a less expensive solution and he did not want to be stuck paying for updates. Disheartened, he eyed his Flash books again and wondered if he should sign up for a Flash course. What he thought was a simple idea was

turning out to be a complicated and costly to develop. I was ready to throw in the towel on the idea, he confesses. Then Tim got an email about Flair from Wildform Software. Flair is a Flash and video presentation software that easily lets people record video, combine their PowerPoint, video, image, audio and swf files, and add quizzes to create rich media projects. Tim liked the price ($299) and Wildform’s claims that it was easy to use, so he bought the software and hired someone to develop the presentation at a fraction of the cost.

How They Did It Preparation work Prepare the floor-plan image First he created a floor plan in Photoshop and then imported it into Flair. (The Flair image importer yields good quality on the conversion to SWF, however, the scaling algorithms in a dedicated

Figure 1. Flair RE Pres screenshot

02/2009 (4)


Wildform customer case study

image editor like Photoshop are better. So when you want to reduce the dimensions of an image (i.e., scale it) it’s best to do it in Photoshop first.) Prepare the video In this case, since all the videos were separated into individual videos based on the room, the developer used Flair’s batch encoder to convert them all to SWF. Flair includes a state of the art Flash to video encoder that offers great quality and support for alpha channel transparency. He experimented with the settings to get the best look for the smallest file size. Once all the videos were encoded (in Flair) he combined them into a single Flair project by adding them all to different slides. He then went into the slide settings and changed the click next (default) slide navigation to none. In the project settings window he added a player and a preloader, then exported the video as a single SWF. Creating the floor plan He opened a new project and proceeded to import the scaled and cropped floor-plan image he created in Photoshop. He used a quality setting of 95 to keep the small type legible and added transparent rectangles over each of the 9 rooms in the house that were covered in the video. He went into the appearance tab of the object settings window and set the alpha to 50 so that they would be transparent.

Creating the project Next he created a new Flair project. This was for the final project. He imported the floor plan, then imported the video (Figure 1). Since he knew how many frames each of the individual videos was, he used that information to lay out the different floor plan highlighting rectangles along the timeline in accordance with where they were supposed to appear. For the transparent rectangles he simply used a text box. He then added a link to the blank textbox that jumps to the given frame where that section of the video begins. He also added a mouse over that creates the highlight whenever one mouses over an object. With Flair, adding interactivity and mouse events is a snap. He laid it out so that the banner is on top, the property information is on the left, the video is in the middle, the realtor info is on the right and the floor plan is on the bottom. That was basically it. Vondrell now had a template that he could use for his interactive video presentations.

The Results Vondrell was delighted with the results. You can click on any room in the floor plan and the video of the room will play instantly, he says. I’m also ecstatic that this project was turned around in twenty-four hours, Vondrell says, I’m pinching myself. I can really turn this into a business.

Flair automates a lot of Flash functions, which is appealing to both Flash novices and experts. We have a lot of customers who author all of their content in Flair, but we also have a huge number of customers who are serious developers and designers and are using Flair to supplement their work in Flash and Flex, says Jonathan Blank, CEO of Wildform.

Top 5 Ways Developers Use Flair to Supplement Their Flash Work Blank listed the top 5 time saving ways developers are using Flair to supplement Flash work. • To easily create interactive multimedia jukeboxes (video and/or audio). What would take hours or days in Flash can be done in no time in Flair. Flair is the best way to combine Flash video with any other element. • To instantly add players/preloaders to video/audio/swf's • To quickly change an existing SWF when you don't have the FLA. Unlike Flash Flair imports existing SWFs. • To supplement Flash with features not found in the Flash authoring tool including screen recording, PowerPoint to Flash conversion, chroma-key, etc. Or to use Flair to generate a quick text effect in seconds that might take hours in Flash. • To generate complex quizzes, tests and surveys and add audio/video/images etc. Flair is a real timer saver for developers, Blank says, and their clients can’t tell which part of a project was created in Flair and which was developed in Flash. Using Flair lets Flash developers increase their profit margins, because they can still charge Flash developer prices while incorporating Flair into their workflow.

Conclusion When Vondrell showed the project to his client, Rae Beasely, she was also delighted with the project. I feel good knowing that as a real estate agent I’m doing my very best to help them sell it with this top of the line presentation, Beasely says, It’s a first class house that deserves first class representation and I’m so grateful to Tim and Visionary Video Productions for helping me to do that. Colby Devitt is president of Wildform.

Readers can receive a $100 discount on their purchase Flair or the Flair Deluxe Bundle at www.wildform.com using this promotion code: FLASHFLEX in the shopping cart. Figure 2. Presentation

02/2009 (4)

13


Tools

Wix web publishing platform allows designers to expand flash design offerings by Allon Bloch

We all know that it takes a combination of time, strong creative skills and a deep knowledge of code to develop professionallooking Flash-based web sites and content.

M

ost designers would embrace the opportunity to simplify the Flash design process without compromising quality. And, now this is all possible. A new online application called Wix (www.wix.com) is a totally flexible Flash design platform that does not require knowledge of code. In addition, it’s incredibly easy to use and allows designers to increase the volume of their work – takes much less

time – as well as expand their overall Flash design offerings. By allowing designers to concentrate on design and expression instead of coding and complex HTML tagging, Wix has found that designers have responded favorably to this application. Since the launch of the open beta in the end of June 2008, Wix has grown rapidly with hundreds of thousands of monthly unique users, and thousands joining every day primarily through word-of-mouth. 14

What makes Wix unique and truly easy to use is its Drag & Drop editor that allows designers to easily create and customize their web sites – and see the results in real time online. Since there is no need to know code, designers can create professional-looking, Flash-based web sites in the matter of hours (sometimes less). In addition, Wix

does not constrict designers to staid templates, so the ability to be as creative as possible is there. Search Engine Optimization (SEO) has traditionally been a challenge for Flash-based web sites. Wix is the first Flash website platform that allows search engines to easily crawl through, facilitating the same SEO that can be achieved with HTML sites. By creating an easily indexed HTML mirror of each site on its servers, Wix automatically funnels directs hits from search engines to the Flash site. The company recently launched its new premium version, which costs $9.90 per month. This version includes several professional features including hosting, connecting to your own domain, as well as keeping the site free from advertising and promotional links. In addition, the company now has an annual subscription option for $99.00. Wix is a game-changing application that actually allows designers to expand their offerings and focus on providing creative solutions. To learn more about Wix, we recommend signing up for the premium version at www.wix.com and giving it a try. by Allon Bloch Co-CEO, Wix 02/2009 (4)



BannerSnack

BannerSnack – A quick alternative to Flash?

N

ow anyone can create complex flash content, from banner ads to flash animations and greeting cards, without even knowing what Adobe Flash is, let alone the ActionScript programming language.

• There is plenty to talk about what you can do within the BannerSnack software, but the easiest way to find out how it works is to go to BannerSnack.com and start playing with the tool for free.

What is BannerSnack?

Why should you use BannerSnack?

BannerSnack is an online software released by Smartketer LLC that lets designers, web developers, bloggers, advertisers, copywriters, junior flash developers and about anyone you can imagine, easily create flash animations that are indistinguishable from the ones created by experienced flash programmers in hours of work. • Its secret lays in its 100% visual interface along with hundreds of patterns, templates and filters that wait to be tried, adapted and tweaked. BannerSnack works pretty much like a presentation software, in which the users can create slides, add images and text and then animate everything through editable transition patterns. • Basically you can upload images and write text and then animate them using slide to slide transitions and/or build in-build out transitions. Also, you can alter your objects with static and animated filters, like blur, gradients, glowing masks and stuff like that. • When the banner is ready, you can give it a name, save it to your own banner collection, and then post it wherever you want using a Gigya widget or manually, using the auto generated embed code. Soon the BannerSnack team will release an update so the users will be able to export their banners to SWF and then download it to their hard drive. 16

• Obviously because it's quick and easy to use. Also it can help you cut some costs. The important thing about BannerSnack is that you can make banner ads, website headers, all kind of flash animations, including greeting cards, without any experience in Adobe Flash and quicker (even better) than a flash pro using the classic method – i.e. ActionScript and timeline animation.

See how is that technically possible in the following paragraph. Read on.

Technology vs. Idea Well, you probably ask yourself how is it possible to do all the things described above without having to write a single line of code. The simple answer is the technology that stands behind the BannerSnack software: the FlashEff transition engine. • To be accurate, the idea for a flash banner maker that would require no flash scripting came from FlashEff, a JumpeyeComponents product, launched in June 2008. Just for the record, JumpeyeComponents is also a subsidiary of Smartketer LLC.

Figure 1. BannerSnack

02/2009 (4)


BannerSnack

and Amazon Simple Storage Service (S3). So it's pretty much a mashup software.

Start now, it's free Because it can be used by very different people seeking to achieve very different results, BannerSnack comes in three versions: Free, Premium and Premium Plus. The difference between the three versions is determined by their feature assortments.

Figure 2. BannerSnack

• But what is FlashEff? FlashEff is a Flash CS3 ActionScript 3.0 component created for easing the job of flash animators. It comprises a collection of over 140 patterns that enable flash juniors and seniors to create cool animations and interactive actions on visual objects and texts. To make it clear, FlashEff is more like a plugin for Adobe Flash, because it cannot run individually – you must have Adobe Flash installed. • Soon after the FlashEff's launch, the Smartketer team thought about a way to create an application that will use FlashEff but it would run independently. They were aware of the wide range of

applications the FlashEff could be used for; they only had to choose what they thought it would be the best. So they came up with the idea of an online software that would allow any Internet user to create flash content: flash banner ads, social networking banners, animated greeting cards, flash animations for blogs, website headers and so on. • In order to make the application work online and for their target, they had to create an interface and adapt FlashEff to work as a transition engine for that interface. BannerSnack also uses a Gigya widget, a flash text editor component, Flex, PHP and JavaScript technologies

• The Free version of BannerSnack is designed pretty much for trial and/or personal use. Its main limitation consists in the fact that all the banners made with it will have a watermark embedded on them. However, community members and bloggers will almost surely love it. • BannerSnack Premium is intended for commercial use, being the perfect solution for those who need banner ads quickly and at a low price. By the way, the Premium version price starts at $9 for one month. • BannerSnack Premium Plus is designed for those who wish to have full control over the banner creation process, providing more features and fine tuning controls. While BannerSnack Premium is enough to carry out a professional job, you wouldn't give up the Premium Plus extra features after you get used to them. The Premium Plus package has a price starting from $99 for six months.

What comes next? We asked Raul Popa, the BannerSnack product manager, what do they plan to do next: • Being our first product release for this market, we plan to do a lot of things! We plan to revolutionize the banner advertising industry, work with Google AdWords, create a presentation software too, launch a desktop application that will beat Adobe Flash and fight against the global crisis – or was it global warming? • However, the most important thing for us in the near future is to fix bugs and constantly update our application based on our users' feedback. Of course, we plan to launch a major BannerSnack upgrade in 2009, that will enable users to create interactive banner ads and Rich Media banners. But for now it's a little premature to talk about that. We'll see.

BANNERSNACK.COM Figure 3. BannerSnack

02/2009 (4)

If you want to find out more about BannerSnack, visit www.bannersnack.com or write them an email at contact@bannersnack.com.

17


For Beginners

Working With Flash CS4 New Features:

Inverse kinematics (IK) with Bone Tool by Chetankumar Akarte

Adobe Flash CS4 comes with some great new features. Recent updates to Flash made it a powerful tool for animation and a platform for rich internet applications. What you will learn...

What you should know...

• What is Inverse Kinematics • To use the Bone Tool for Creating (IK) animations

• Basic Flash CS4 • Basic AS 3.0

Level of difficulty

F

lash CS4 introduces various tools to made application development as simple as possible. Here we are going to use the Bone tool for creating inverse kinematic (IK) animations. First of all we must be familiar with inverse kinematic. Inverse kinematics (IK) is a method for animating an object or set of objects in relation to each other using an articulated structure of bones. Let’s take a look what Wikipedia defines the inverse kinematic.

Inverse kinematics is the process of determining the parameters of a jointed flexible object (a kinematic chain) in order to achieve a desired pose. Inverse kinematics is a type of motion planning. Inverse kinematics is also relevant to game programming and 3D animation, where a common use is making sure game characters connect physically to the world, such as feet landing firmly on top of terrain. The Bone Tool allows you to quickly link several objects together to create a chainlike effect. Means Inverse kinematics lets you create natural motion such as arms, legs, and facial expressions much more easily. You can use IK in Flash in two ways. The first is to articulate a series of symbol instances by adding bones to connect each instance

to another instance. The bones allow the chain of symbol instances to move together. For example, you might have a set of movie clips that each represents different parts of a human body like you can create a realistically moving arm or legs, and the head. The second way to use IK is to add an armature to the interior of a shape object. The shape can be created in merge drawing mode or object drawing mode. The bones allow you to move and animate parts of the shape without the need to draw different versions of the shape or create a shape tween. For example, you could add bones to a simple drawing of a snake to enable the snake to move and curve realistically. A chain of bones is called an armature. The bones in an armature are connected to each other in a parent-child hierarchy. An armature can be linear or branched. Branches of an armature that originate at the same bone are called siblings. The point where one bone connects to another is called a joint.

Inverse kinematics with Shapes So, let us start. Open your flash CS4 and create a new flash. To use inverse kinematics, you have to create a FLA file with ActionScript 3.0. Select Rectangle tool and draw a rectangle. Now with selection tool select the shape you

Figure 2. Draw your shape

Figure 1. Select the Rectangle tool to draw your shape

18

Figure 3. Duplicate your shape

Figure 5. Frame 5

Figure 4. Apply bone tool selection on your shape (Frame 0)

Figure 6. Frame 15

02/2009 (4)


Inverse kinematics (IK) with Bone Tool

have drawn. Press Ctrl and make the copies of the shape you have drowned (Figure 1-3). Using the Bone Tool, click and drag from one Movie Clip to another, repeating this procedure for each additional Movie Clip (Figure 4). With selection tool you can add animate tools as you wish. Select frame 5 and press [F5] and rotate you shape as you wish. I have repeated the same procedure on Frame 10 and 15 as follows. Just save and export your movie to see the animation you have done with bone tool (Figure 5) and (Figure 6).

Inverse kinematics with Human Body Create a new project and draw a human body with Pencil Tool. I have tried to draw a human, as I am not a great artist. Model which I have drowned is as follows (Figure 7). Using the Bone Tool, draw structure. My model looks like as: see (Figure 8). Now I want my model have to punch in air, so I am going to add a Key frame on Frame 30 and going modify my model shape. And do same procedure at frame 60. With the armature selected, the Properties panel is updated to reflect several options. You can enable constraints for joint rotation using simple check boxes and hot text sliders. This is very useful in situations where character animations are rigged with the Bones Tool. You can specify how far individual limbs can rotate based on anatomical accuracies. The Properties panel also provides X and Y constraints in the same fashion. Individual custom constraint parameters can be set for each individual Bone in the chain (Figure 9) and (Figure 10). Now save your file and take a look at output. It made an animating model for me which going to punch in air. When you add bones to symbol instances or shapes, Flash moves the instance or shape and the associated armature to a new layer in the Timeline. This new layer is called a pose layer. Each pose layer can contain only one armature and its associated instances or shape. Flash includes two tools for working with IK. You add bones to symbol instances and shapes

Figure 8. Model after applying bone tool

with the Bone Tool. You use the Bind tool to adjust the relationships between individual bones and control points of shape objects. You can animate armatures and their associated symbols or shapes either in the Timeline or with ActionScript 3.0. You animate in the Timeline by defining different poses for the armature in different frames. Flash interpolates the positions of the armature in the frames in between. Steps to Adding Bone to Symbol • You can add IK bones to movie clip, graphic, and button instances. To use text, convert it to a symbol first. • Select the Bone Tool from the Tools panel; click the symbol instance that is to be the root or head of the armature. Then drag to a separate symbol instance to link it to the root instance.

Figure 10. Final Model position for punch (Frame 60)

• To add another bone, drag from the tail of the first bone to the next symbol instance you want to add to the armature. • To create a branched armature, click the head of an existing bone where you want the branch to begin and drag to create the first bone of the new branch. • Once you have created an armature and all of its associated symbol instances; you are ready to create your animation. Steps to Adding Bone to shapes • Create a filled shape or shapes on the Stage. • Select the entire shape on the stage. • With the Bone tool, click inside the shape and drag to another location within the shape. • To add another bone, drag from the tail of the first bone to another location in within the shape. • To create a branched armature, click the head of an existing bone where you want the branch to begin and drag to create the first bone of the new branch. • Once you have created an armature and all of its associated symbol instances; you are ready to create your animation.

Conclusion Flash is a great tool and new feature Bone Tool made the complex animation very easy. It’s a great tool for Game developer or character animator. The bones tool allows you to actually draw the bones that make up a full skeleton or armature. Figure 7. Sample model drown with pencil tool

02/2009 (4)

Figure 9. Initial Model position for punch (Frame 30)

19


SUBSCRIBE AND SAVE! Subscribe to Flash & Flex from just $49 Free shipping


$49

only for 6 issues □ Yes, I’d like to subscribe to Flash & Flex magazine from issue □ □ □ □ □ 1

2

3

4

5

□6 / 2009

□ Yes, I’d like to order archive □1 □1 □2 / 2008

Order information (□ individual user/ □ company) Title Name and surname address postcode tel no. email Date

3 EASY WAYS to subscribe: 1.

Phone

Order by phone:

1-917-338-3631 2.

Online

Order via credit card:

www.buyitpress.com 3.

Post or e-mail

Complete and post the form to:

Software Media LLC 1521 Concord Pike, Suite 301 Brandywine Executive Center Wilmington, DE 19803 USA or scan and e-mail the form to: subscription@software.com.pl

Company name Tax Identification Number Office position

Payment details: □ USA $49 □ Europe 39€ □ World 39€ I understand that I will receive 4 issues over the next 12 months. Credit card: □ Master Card □ Visa □ JCB □ POLCARD □ DINERS CLUB

□□□□ □□□□ □□□□ □□□□ □□□□ □□□□ Issue number □□ □□□

Card no. Expiry date Security number

□ I pay by transfer: Nordea Bank

IBAN: PL 49144012990000000005233698 SWIFT: NDEAPLP2 Cheque:

□ I enclose a cheque for $ ____________________ (made payable to Software Media LLC)

Signed Terms and conditions: Your subscription will start with the next available issue. You will receive 6 issues per year.


ActionScript Developement

Connecting the Wii to Flash by Almog Koren While there are a lot of different input devices that we can use with Flash, it seems that the Nintendo Wii has become very popular in the past year.

N

ot only is the Wii’s technology advance, but it is also very simple to set up and has great features that are good for Flash Kiosks and Flash based Wii games. I am going to show you how to connect your Wii's remote to your computer and how to implement the basic Flash code. One of the best parts is that you don’t need the whole Nintendo Wii system - just the remote.

About the Wii Before I start it would be good to understand a little bit about the Wii. As of June 2008, Nintendo has sold nearly 30 million Wii game consoles. This makes the Wii's Remote one of the most common computer input devices in the world, which has great benefits for the Flash kiosk. The Wii's remote contains a 1024x768 infrared camera with built-in hardware blob tracking of up to 4 points at 100Hz. It also contains a +/-3g, 8bit, 3-axis accelerometer, also operating at 100Hz and an expansion port for even more capability.

What you need

Now that we have the Wii hooked up to the computer we need to have it communicate with Flash. Lucky we have Wii Flash, which is a Flash package developed by Joa Ebert and Thibault Imbert. You can go to the Goggle Code project page at http://code.google.com/p/ wiiflash/ and download the WiiFlash 0.4.3.zip. After that you need to download the wiiflash_ server.zip file. This will help communicate with the Wii remote. Install both and you should see that it finds your Wii remote.

file. We will be coding in ActionScript 3.0, so first create a key frame labeled ActionScript on the first layer on the time line and lock it once you have that is completed. Open up your actions panel. The first thing we need to do import the Wii Flash package. import org.wiiflash.Wiimote;

import org.wiiflash.events.ButtonEvent;

import org.wiiflash.events.WiimoteEvent; import flash.events.*;

ActionScript

Then we are going to create a new Wii remote.

Now that we have the Wii remote hooked up we need to start coding and create the Flash

var myWiimote:Wiimote = new Wiimote();

Listing 1. Syncing the Wii remote var WiiSynchronize:Synchronize = new Synchronize(); addChild(WiiSynchronize ); WiiSynchronize.x = (stage.stageWidth - WiiSynchronize.width) / 2;

WiiSynchronize.y = (stage.stageHeight - WiiSynchronize.height) / 2

Listing 2. Wii Movement

One Wii remote and one Bluetooth device on your computer.

function onUpdated ( pEvt:WiimoteEvent ):void

Connecting the Wii

{

Let’s get started. The first thing you are going to want to do is install your Bluetooth device if it has not already been installed. You can use your Windows stack for the Bluetooth device, but it seems that this does not always work. Also, certain Bluetooth devices just do not work with the Wii. So this might be a trial and error. Once your Bluetooth is active you need to put your Wii remote into the discover mode. To do this press both the 1 and 2 buttons at the same time and once you have established a connection you should see Nintendo RVL-CNT-01. 22

Starting with Flash

sensor_txt.htmlText += "Sensor X : " + String ( pEvt.target.sensorX ) + "<br>Sensor Y : " + String ( pEvt.target.sensorY );

sensor_txt.htmlText += "Pitch : " + String ( pEvt.target.pitch ) + "<br>Roll : " + String ( pEvt.target.roll );

sensor_txt.htmlText += "Yaw : " + String ( pEvt.target.yaw ); sensor_txt.htmlText += "Battery level : " + String ( pEvt.target.batteryLevel ); }

02/2009 (4)


Listing 3. Wii button actions myWiimote.addEventListener( ButtonEvent.A_PRESS, onAPressed );

myWiimote.addEventListener( ButtonEvent.A_RELEASE, onAReleased);

myWiimote.addEventListener( ButtonEvent.LEFT_PRESS, onLeftPressed );

myWiimote.addEventListener( ButtonEvent.LEFT_RELEASE, onLeftReleased); myWiimote.addEventListener( ButtonEvent.RIGHT_PRESS, onRightPressed );

myWiimote.addEventListener( ButtonEvent.RIGHT_RELEASE, onRightReleased); myWiimote.addEventListener( ButtonEvent.UP_PRESS, onUpPressed );

myWiimote.addEventListener( ButtonEvent.UP_RELEASE, onUpReleased);

myWiimote.addEventListener( ButtonEvent.DOWN_PRESS, onDownPressed );

myWiimote.addEventListener( ButtonEvent.DOWN_RELEASE, onDownReleased); myWiimote.addEventListener( ButtonEvent.B_PRESS, onBPressed );

myWiimote.addEventListener( ButtonEvent.B_RELEASE, onBReleased);

myWiimote.addEventListener( ButtonEvent.MINUS_PRESS, onMinusPressed);

myWiimote.addEventListener( ButtonEvent.MINUS_RELEASE, onMinusReleased); myWiimote.addEventListener( ButtonEvent.PLUS_PRESS, onPlusPressed);

myWiimote.addEventListener( ButtonEvent.PLUS_RELEASE, onPlusReleased); myWiimote.addEventListener( ButtonEvent.HOME_PRESS, onHomePressed);

myWiimote.addEventListener( ButtonEvent.HOME_RELEASE, onHomeReleased); myWiimote.addEventListener( ButtonEvent.ONE_PRESS, onOnePressed);

myWiimote.addEventListener( ButtonEvent.ONE_RELEASE, onOneReleased); myWiimote.addEventListener( ButtonEvent.TWO_PRESS, onTwoPressed);

myWiimote.addEventListener( ButtonEvent.TWO_RELEASE, onTwoReleased);

Now that we have done that we need to connect to the Wii's remote via the Wii Sever and add an event listener to listen for the connection.

Now that we all the event listeners added, all we need to do is create individual functions. For each button I will show only one example and you can take it from there.

myWiimote.connect ();

function onAPressed ( pEvt:ButtonEvent ):

myWiimote.addEventListener( Event.CONNECT, onWiimoteConnect );

We have imported the packages, created the new Wii remote and connected to it. We now want to sync the Wii's remote to the X and Y coordinates so that we can track the movement on screen (see Listing 1) Let's go ahead and test it, but before we can we do need to create an event listener that will also check to see if we have any movement or if any of the buttons are pressed. myWiimote.addEventListener(

WiimoteEvent.UPDATE, onUpdated );

Once we have this we can go ahead and add a dynamic text field to a new layer on the time line. Give it an instance name of sensor_txt. In the actions layer we want to add a function that will run on the Wii's remote update event listener and when it does it will show where the X and Y coordinates are (see Listing 2). Now you can publish the Flash file and see if it works. We still need to check the buttons to see if they are pressed, so we will create another event listener for them (see Listing 3). 02/2009 (4)

void

{

}

Your actions here

Overview That is pretty much it for a very fast and easy way to hook up the Wii's remote to Flash. This is only the beginning and there are a lot of other possibilities with this. I would recommend that you visit the Wiiflash site and look into the demos and documentation for more advance features. Another site is Johnny Chung Lee Wii projects, which is a really great site with open source code and much more. In the near future, I will be posting some advance tutorials on Wii Flash, PaperVision and Head Tracking for Desktop VR Displays. So check out my site at www.almogdesign.net.

ALMOG KOREN He’s an 28 year old Israeli / American Flash Developer and designers working for Tamooz Marketing Communication, multimedia department. Graduated from Kinneret Collage in Israel with an associates degree in Interactive Communications. www.almogdesign.net-almong

23


ActionScript Developement

Tracking Time with Screenweaver HX by Lee McColl Sylvester Screenweaver HX is the latest and most flexible version of Screenweaver to date, providing functionality that enables Flash developers to expand their development potential into the desktop application realm.

What you will learn...

What you should know...

• When to use Screenweaver HX over Flash Projectors • How to access a database with no SQL knowledge • How to use Neko in collaboration with Flash • How to perform synchronous communication between the Flash and desktop layers

• Basic ActionScript knowledge is preferred, but not essential • The desire to take Flash where no person has taken Flash before!

Enter haXe Level of difficulty

T

his article will demonstrate that you do not have to be a hardcore programmer to develop rich desktop applications. Flash ActionScript has often been portrayed as a designer's programming language. Having started off as a vector animation tool for web enthusiasts, little has altered within the Flash IDE to warrant changing that paradigm, even though the Flash scripting language, ActionScript, has evolved into a powerful object oriented language capable of producing outstanding interactive visuals. Macromedia, now Adobe, was strongly aware of this, and produced Flex in the hope that it would entice seriously hardcore internet programmers to the Flash scene, which it has not failed to do. However, in doing so, the more design-centric Flash users who are often disinclined to use programming IDE’s or learn a new language, in the case of MXML, have been clearly left with no choice but to make the huge leap into the world of programming or remain tinkering with the Flash IDE. 24

When Nicolas Cannasse, designed haXe, he did so with the intention of producing a rich language that would close the rift that exists between the various factions of development and design. Nicolas's idea was not new, as Microsoft and Sun Microsystems has spent many years, and large sums of money trying to perform just that. However, what was new about Nicolas's idea was the intention of targeting the haXe language at existing platforms and runtimes, rather than inventing new ones. In theory, haXe provides the premise to unify development teams by supplying a

single language for most tasks required in applications development, thus merging and gently blurring the boundaries that often exist between them. The greatest part of all for Flash developers, though, is that haXe is based on the ActionScript language, so if you already know ActionScript, you can now take that knowledge and apply it to many other different types of applications development, even if ActionScript is all you know! In this article, I will demonstrate how haXe can be used to construct a desktop application using Flash as the presentation tier. I will also show how you can utilize a database in your application without having to use a single line of SQL language.

Getting Started For this demonstration, we are going to build a simple time tracking application. As anyone can attest I am terrible about keeping time and I am sure I am not alone, so we might as well build something we can all use. When building any application it often helps to first decide on what data your application will use. This way you can design your classes

Table1. Projects database table layout TimeLog Field Name

Type

Not Null?

PK?

Inc?

id

INTEGER

Default

Tick

Tick

Tick

projectName

TEXT

Tick

PK

Inc?

Table 2. TimeLog database table layout Projects Field Name

Type

date

DATE

Default

Not Null? Tick

time

DATETIME

Tick

projectId

INTEGER

Tick

02/2009 (4)


Tracking time with Screenweaver HX

around your data. We are going to be using a SQLite database for this example and as I promised not to use a single line of SQL code. But, we will cheat a little and use a SQL Management tool to build your database. Don’t worry, you will only have to do this the once and it really is not that hard. The tool I use is called, SQLite 2008 Pro, and can be downloaded absolutely free from http:// osenvistasuite.com/?xp=3 Once you have installed this software open it up and create a new database called data.db3, making sure to save it to the directory you wish to build your application. You can do this with the icon on the far left of the SQL Manager toolbar. Once this is done, you can then use the fifth icon to begin creating your tables. We will need two tables for this application; the first table will be called Projects, and will be used to store the names of the tasks you work on, while the second table will be called TimeLog, and will be used to store the timestamps of when you start and finish each task during the day. When you click on the Create Table icon you will be presented with a dialog asking you to enter the table name and columns. Make sure you start the table name with a capital letter, and each field name using a lower case letter, as this will be important later. For the table columns, enter the data in tables 1 and 2. Next, click on the Projects table icon in the navigation tree on the left. In the bottom panel click on the Table Data tab, then right click and select Insert. When the dialog appears enter 0 (zero) for the id field and Stop work! for the projectName field, and then click Okay. This will be the task used when you stop working. Now click on the save icon and you are done.

our benefit, though you can name the class anything you like. The content of the class then contains the variables representing the data in our Projects table, as well as three other values that all SPOD classes must provide. TABLE_ NAME and TABLE_IDS should be quite self explanatory. TABLE_NAME is the name of the database table this class maps to, while TABLE_IDS is an array of the column names that make each record unique. Sometimes, when working with database tables, a single id field is used to identify each record, while at other times the uniqueness is specified using two or more columns combined. The final value specifies the manager class for this table. For most simple projects you can simply provide the standard Manager class, as in this example, and be done with it. Sometimes, though, you will want to provide your own bespoke manager, as this can allow you to add your own custom functionality. The class used for the TimeLog table, as shown in Listing 2, is very similar to the Projects class. You will notice, though, that an extra parameter is used, as well as the function RELATIONS. RELATIONS is a specific method one would add to a SPOD class to provide details on how other table classes relate to the current class. The reason one would add this information is to be able

02/2009 (4)

The Desktop Layer So, we have our table mapped classes and now need to provide the logic to allow our Flash presentation tier to access and manipulate this data. We do this using a class which we will eventually compile to

Listing 1. The Projects database table class map class Projects extends neko.db.Object { public var id : Int;

public var projectName : String; static var TABLE_NAME = "Projects";

Using the haXe SPOD Library In order to refrain from using SQL language in our application, we are going to use the haXe SPOD library. SPOD stands for Simple Persistent Objects Database, and is what we haXe developers like to use to reduce the number of SQL strings that appear in our application. The great thing about SPOD is that you can often get away without writing any SQL whatsoever, while the more complex applications will still need some. You won’t have to worry about that for this application though. To use SPOD we need to create a class for each of our database tables. The way SPOD works is that we would interact with class versions of our tables, calling and changing data as we see fit, while the hidden internals of the SPOD framework seamlessly manages the database in real time to reflect our data changes. Pretty cool, huh? So, how do we do this? Well, if you take a look at Listing 1, you will see the class used to map to the Projects table. As you can see, the class is named Projects. This is purely for

to retrieve data from the related class from within the current class. For example, upon retrieving records from the TimeLog table, I might find the need to display the name of the associated project. Unfortunately, the TimeLog class only provides the id of the associated project, so using relationships will allow me to get at the associated Project record and thus the project name. The RELATIONS method must always return an object providing the parameters prop, key and manager. prop is the name, as a string, of the new parameter we added to this class, which provides access to an instance to the related class. key provides the name of the field in the current class which maps to the identifier field in the related class, and manager provides the class used as the related classes manager. As the object providing these values is passed within an array you can provide multiple objects of this type to reference other tables with other relationships, if you wish.

static var TABLE_IDS = ["id"];

}

public static var manager = new neko.db.Manager< Projects >( Projects );

Listing 2. The TimeLog database table class map class TimeLog extends neko.db.Object { public var date : Date; public var time : Date;

public var projectId : Int; static var TABLE_NAME = "TimeLog"; static var TABLE_IDS = ["time"]; static function RELATIONS() {

return [ { prop : "project", key : "projectId", manager : untyped

}

Projects.manager } ];

public var project( dynamic, dynamic ) : Projects; }

public static var manager = new neko.db.Manager< TimeLog >( TimeLog );

25


ActionScript Developement

Listing 3a. The Neko layer application class

_trayHook.setNekoCallback( trayClickHook );

import systools.win.Tray;

import systools.win.Menus; import systools.win.Events;

_tray = new Tray( _window, "swhx_16x16.ico", "Time

private static function trayClickHook() : Int {

if ( Std.string( _trayHook.p2 ) == Std.string(

class MainSWHX {

Events.RBUTTONUP ) )

private static var _conn : neko.db.Connection; private static var _flash : swhx.Flash;

private static var _server : haxe.remoting.Context; private static var _window : swhx.Window;

private static var _databaseUrl = "data.db3";

Tracker" );

}

handleTrayOption( _menu.showPopup( _window.handle ) ); }

return 0;

private static function handleTrayOption( option : Int ) { switch( option ) {

private static var _menu : Menus;

case 1:

private static var _projectSubmenu : Menus;

showWindow( true );

private static var _tray : Tray;

case 4:

private static var _trayHook : swhx.MessageHook;

default:

public static function main() { }

public function new() { initialize();

}

swhx.Application.loop();

private function initialize() { openDB();

swhx.Application.init(); setupFlash(); }

if ( option > 4 )

var inst = new MainSWHX();

setupTray();

private function setupFlash() : Void {

_window = new swhx.Window( "Time Tracker", 300, 220 );

}

_flash = new swhx.Flash( _window, _server ); _flash.setAttribute( "src", "ui.swf" ); _flash.start();

showWindow( false );

closeDB();

_tray.dispose(); }

_window.minimized = !show;

}

_conn = neko.db.Sqlite.open( _databaseUrl ); neko.db.Manager.cnx = _conn;

}

neko.db.Manager.initialize();

private static function closeDB() : Void { neko.db.Manager.cleanup();

}

_conn.close();

public static function addProject( name : String ) : Void { var record = new Projects(); record.projectName = name; record.insert();

return false;

record.sync();

_projectSubmenu.addItem( record.projectName, record.id

private function setupTray() { _menu = new Menus( true );

_menu.addItem( "Open Controls", 1 ); _projectSubmenu = new Menus( true );

var list : List < Projects > = Projects.manager.all(); for ( i in list )

_projectSubmenu.addItem( i.projectName, i.id + 1000 ); _menu.addSubmenu( _projectSubmenu, "Change Task", 2 ); _menu.addDivider( 3 );

_menu.addItem( "Exit", 4 ); _trayHook = _window.addMessageHook( untyped Events.TRAYEVENT );

26

_window.visible = show;

private static function openDB() : Void {

showWindow( false );

}

swhx.Application.cleanup();

private static function showWindow( show : Bool ) {

_window.onClose = function() {

}

logTask( option - 1000 );

private static function cleanup() {

_server = new haxe.remoting.Context();

_server.addObject( "SWHX", MainSWHX );

}

}

+ 1000 );

public static function getProjectHoursWorked( date : Date ) : Dynamic < Float > {

Projects.manager.all();

var list : List < TimeLog > = TimeLog.manager.search( { date : date }, true );

var timeCounter : Dynamic = {};

var previousTime : TimeLog = null; for ( i in list ) {

i.time = Date.fromString( Std.string( i.time ) ); i.date = Date.fromString( Std.string( i.date ) ); if ( previousTime != null ) {

if ( previousTime.projectId != 1 ) {

var time : Float = ( ( ( i.time.getTime() -

previousTime.time.getTime() ) / 1000 ) / 60 )

02/2009 (4)


Tracking time with Screenweaver HX

Listing 3b. The Neko layer application class / 60; var project = previousTime.project.projectName; if ( !Reflect.hasField( timeCounter, project ) ) Reflect.setField( timeCounter, project, time ); else

Reflect.setField( timeCounter, project, Reflect.field( timeCounter, }

} }

project ) + time );

previousTime = i;

return timeCounter;

public static function logTask( projectId : Int ) : Void { var record = new TimeLog(); var now = Date.now();

record.date = new Date( now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0 );

record.time = now;

record.projectId = projectId;

}

}

record.insert();

Listing 4a. The Flash layer class import flash.Lib; import flash.display.Sprite;

import flash.display.MovieClip; import flash.text.TextField;

import flash.text.TextFieldType;

import flash.text.TextFormatAlign; import flash.text.TextFormat;

import flash.events.MouseEvent; class MainSWF extends Sprite {

private var _reportButton : MovieClip;

private var _projectSubmitButton : MovieClip; private var _dayField : TextField;

private var _monthField : TextField; private var _yearField : TextField;

private var _outputField : TextField;

private var _projectNameField : TextField; private var _dayLabel : TextField;

private var _monthLabel : TextField; private var _yearLabel : TextField; private var cnx : swhx.Connection; public static function main() { }

var inst = new MainSWF();

public function new() { super();

var stage = Lib.current;

cnx = swhx.Connection.desktopConnect(); var now = Date.now();

_dayField = GUIHelper.createField( Std.string( now.getDate() ), 60, 10, 50, 20, true );

02/2009 (4)

use with the Neko virtual machine. Listing 3 provides the code for this class. It is pretty big, but don’t worry too much, as I will walk you through it. The first method, main, is the entry point to the application. It is this method that is first called and from which we instantiate the class so that the application can run. When instantiation occurs the new method is called. I have broken this method up into several methods so that the naming can be used to better identify what is happening. Essentially, when the class is instantiated the first thing to occur is the initialization functionality. This includes tasks such as opening our database, initializing Screenweaver HX, and creating a connection to the Flash layer. Much of this code will be tasks that you will repeat time and time again for other Screenweaver HX applications, though the content of the method setupFlash may differ depending on the features you wish to include. Let’s take a look at the setupFlash method, so we can see what is happening. We use three main static member variables, here, which are values that we want to exist throughout the lifetime of our application. The first one, _window, will store the reference to the visible window that will appear on your desktop. To create this window, we instantiate the Screenweaver Window class, and pass the name of the window that will appear on its frame and its width and height. The next variable, _server, will maintain the connection between the Neko desktop layer and the Flash presentation layer. With this connection, we can provide Flash with the access it needs to manipulate the database. Finally, the _flash variable is a reference to the actual Flash movie. Here we specify the file name of our Flash SWF file and associated it with the Neko to Flash connection. We then start the movie running. The last part of our initialization entails hiding our window so that it does not show straight away when the application is executed, and a method handler for the close event of the window. When the user clicks the close icon on the window frame, we do not actually want the window to close. Instead, we will simply hide it from view. If we were to let the window close, then our application would exit, as it would no longer have a window reference to maintain the application loop. That is it for our window initialization. Now, we need to setup our tray icon, and the menu system that appears when the user right clicks the icon. To do this we instantiate the Menu class. At present, native operating system menus are only supported on Windows for Screenweaver HX. It should be possible to provide the same functionality on Mac and Linux using 27


ActionScript Developement

Listing 4b. The Flash layer class

stage.addChild( _dayField ); _monthField = GUIHelper.createField( Std.string(

now.getMonth() + 1 ), 60, 35, 50, 20, true );

stage.addChild( _monthField );

_yearField = GUIHelper.createField( Std.string(

Listing 5. The GUI helper class import flash.display.MovieClip; import flash.text.TextField;

import flash.text.TextFieldType;

import flash.text.TextFormatAlign; import flash.text.TextFormat; class GUIHelper {

now.getFullYear() ), 60, 60, 50, 20, true

public static function createButton( text : String, x :

Int, y : Int, width : Int, height : Int,

);

color : Int )

stage.addChild( _yearField );

_dayLabel = GUIHelper.createField( "Day : ", 10, 10, 50,

var button : MovieClip = new MovieClip();

stage.addChild( _dayLabel );

button.y = y;

20 );

button.x = x;

_monthLabel = GUIHelper.createField( "Month : ", 10, 35,

button.graphics.beginFill( color );

50, 20 );

button.graphics.drawRoundRect( 0, 0, width, height, 5,

stage.addChild( _monthLabel );

5 );

_yearLabel = GUIHelper.createField( "Year : ", 10, 60, 50, 20 );

button.graphics.endFill(); button.buttonMode = true;

stage.addChild( _yearLabel );

button.useHandCursor = true;

_reportButton = GUIHelper.createButton( "Get Report!",

button.mouseChildren = false;

115, 10, 175, 70, 0xff0000 );

var lblWidth = Math.floor( ( width - 100 ) / 2 );

_reportButton.addEventListener( MouseEvent.CLICK,

var lblHeight = Math.floor( ( height - 20 ) / 2 );

onReportButtonClick );

var label : TextField = createField( text, lblWidth,

stage.addChild( _reportButton );

lblHeight, 100, 20, false, CENTER );

_outputField = GUIHelper.createField( "", 10, 85, 280, 100, true );

button.addChild( label );

stage.addChild( _outputField );

return button;

_projectNameField = GUIHelper.createField( "", 10, 190,

}

stage.addChild( _projectNameField );

public static function createField( text : String, x :

195, 20, true );

Int, y : Int, width : Int, height

_projectSubmitButton = GUIHelper.createButton( "Add

: Int, ?editable : Bool, ?align :

Project!", 210, 190, 80, 20, 0xff0000 );

TextFormatAlign ) : TextField {

_projectSubmitButton.addEventListener( MouseEvent.CLICK,

if ( align == null ) align = RIGHT;

onProjectSubmitButtonClick );

}

var tf = new TextField();

stage.addChild( _projectSubmitButton );

tf.x = x;

private function onReportButtonClick( event : MouseEvent ) :

tf.y = y;

Void {

tf.width = width;

var date = new Date( Std.parseInt( _yearField.text ),

tf.height = height;

Std.parseInt( _monthField.text ) - 1,

tf.text = text;

Std.parseInt( _dayField.text ), 0, 0, 0 );

if ( editable ) {

var timeLog : Dynamic< Float > = cnx.SWHX.getProjectHoursW

tf.background = true;

orked.call( [ date ] );

tf.backgroundColor = 0xffffff; tf.border = true;

_outputField.text = "";

tf.borderColor = 0x999999;

for ( i in Reflect.fields( timeLog ) )

_outputField.text += i + " = " + Std.string( Math.round(

}

else

Reflect.field( timeLog, i ) * 100 ) / 100 )

}

+ "\n";

tformat.align = align;

tf.setTextFormat( tformat );

MouseEvent ) : Void {

}

28

}

tf.selectable = false;

var tformat : TextFormat = new TextFormat();

private function onProjectSubmitButtonClick( event : cnx.SWHX.addProject.call( [ _projectNameField.text ] );

tf.type = TextFieldType.INPUT;

}

}

return tf;

02/2009 (4)


Tracking time with Screenweaver HX

the GTK bindings for Neko, but that is out of scope for this article. The tray menus are created using two instances of the Menu class; one for the main menu and one for the project submenu. Each menu item accepts a label parameter and an id, which we will use to decide which item was selected by the user. The menus then need to be assigned to the _window instance, which is the application anchor along with an instance of the Tray class for the tray icon. When creating your tray icon, make sure to pass a URL to a valid .ico icon file, otherwise your icon will never actually appear. You can find one of these within the samples that come with Screenweaver HX. The methods trayClickHook and handleTrayOption deal with handling the item selected from the menu. We do not have much functionality here. If the user clicks the option to Open Controls, then the window's visibility is set to true and the window is displayed. Alternatively, if a project is selected then it is logged in the TimeLog table in our database, while clicking the Exit option ends our application. When exiting the application the Screenweaver Application.loop method is exited and the tasks following are called. At such a point in our application, we are only concerned with tidying up, which includes tasks such as closing the database and disposing of the tray and window functionality. The final methods in our class deal with calls from the Flash layer. This is where our SPOD classes are used and calls to the database are made. As you can see there is not a single SQL string in sight, simply calls to the Projects and TimeLog classes. To get our data out of these classes we use one of two methods of the class manager; all and get. all, essentially returns a list of every record within the table as objects of the table class. Thus calling TimeLog.manager.all() will return a list of TimeLog classes containing our data. As we saw when looking at our SPOD classes doing this also provides access to a project property in the TimeLog objects

that allow us to access the related Projects record also. When modifying data in the SPOD objects we can then update the database by calling update or if the object was instantiated directly, insert.

The Flash Layer The Flash layer is described in Listing 4. To make things simple I have included some helper functions in a class called GUIHelper (see Listing 5), which will provide simple features such as buttons, labels and fields. When you create your own applications you may prefer to use one of the more feature rich GUI libraries to provide this functionality instead. Flash is a presentation tier so any calculations that can be provided for in the Neko layer should be provided in the Neko layer. As you can see our Flash class begins much like the Neko layer class by using a static main method where the class is instantiated and a new method for the functionality. I have kept the code pretty contained here. The new method simply concerns itself with creating the connection object to the Neko layer, as well as creating the buttons and fields that will allow the user to view a report of how many hours were spent for each task on any given day. Also, a field and button that will allow new tasks to be added to the tray menu is also provided. Once the Flash elements are created and displayed the onReportButtonClick and on ProjectSubmitButtonClick methods provide event handling for the two buttons. It is here that the connection to the Neko layer is used and the necessary function called. The connection object, which in this case is called cnx, exposes properties for each server object in the Neko layer. If you recall, the server object was given a reference name of swhx in its constructor, thus we can now access this object from the cnx object. Next, within this swhx object we have direct access to the static methods, or functions, of the Neko class and can call them at will. Calls to functions in a Neko layer are done by using their call function, and passed an array

Listing 6. The compile.hxml file content -main MainSWHX -lib swhx

-neko timetracker.n --next

-main MainSWF -swf-version 9

-swf-header 300:220:30:CCCCCC -swf ui.swf

Figure 1. The TimeTracker application in action

02/2009 (4)

containing a list of the necessary parameters. The parameters must be of the correct type and in the correct order for the function call to succeed.

Compiling the Application That is all there is to the coding. To compile the application, you will need to create a file with an .hxml extension. I often call mine compile.hxml, so I can spot it easily in a large project. Within this file enter the contents of Listing 6. Next, open a command window and navigate to the directory containing your source files. Then enter haxe compile.hxml and press return. This will compile the application and created a file called timetracker.n, which you can run with the Neko virtual machine. To make things easier, though, enter nekotools boot timetracker.n in the command window and press return, which will convert your .n file into a fully functioning executable file. Go ahead. Give it a try!

Conclusion In this article we managed to build a complete desktop application, complete with Flash graphical user interface, tray and menu support, and backend database connectivity without any SQL. With a little bit of effort, this application could easily be extended to provide new and complex features suitable for any commercial product. What we have done here is to provide the necessary foundation to building any successful desktop application using Screenweaver HX and the haXe language. Where you go from here is up to your imagination.

LEE MCCOLL SYLVESTER Lee McColl Sylvester is a haXe and Neko evangelist and author of the Professional haXe and Neko book, published by Wiley and Sons. He is an expert ActionScript developer as well as a seasoned master in systems integration. A student in Visual Communications, he evolved his career specializing in advanced animation and graphical interface development, as well as games development, information management systems, database architecture and hardware communications implementation, producing applications for organisations all over the world. Lee currently works for Bluetube Interactive (www.bluetubei.com) producing Enterprise and RIA applications in Flex, Flash and haXe, while spending much of his free time promoting haXe at conferences and work environments, as well as contributing where possible to the multitude of haXe libraries. The most successful of these include the haXe ODBC and PostgreSQL drivers, the NME platform (Neko Media Library), and the nMagick ImageMagick bindings library.

29


ActionScript Developement

Using all the different components within CS4 to built a complete site Component Tutorial – Part One by Justin P. Junda

Components can be very useful and can complement ones design if used correctly. However, components do tend to get abused in designs and if not used correctly they can make for an eyesore of an application or website. This tutorial will help to get you started using components successfully. What you will learn...

What you should know...

• This tutorial will give a basic understanding of how to use components and implement them into your work flow. (Part 1 1st article) • The second part (next article) you will take everything you learning from part one and start to build a complete website / application from what you previous learned.

• You should have a basic understanding of the Flash interface, and understand some minimal coding knowledge and techniques.

Level of difficulty

C

omponents will allow you to easily build ActionScript applications with a consistent behavior and appearance. This tutorial will cover a basic overview of components using Flash CS4. You can use Flash AS3, if you don't have CS4 yet. In Part Two of the Component Tutorial series, I

Now I will switch my default layout preset from the ESSENTIALS preset to the DEVELOPER preset see (Figures 3,4). The reason for this is because the components panel defaulted to the bottom left corner see (Figure 5). You don’t have to use the DEVELOPER layout, alternately you could go to the file menu under the Window pull down Components

will demonstrate some good examples of components currently found on the web, and I will show you how to tie all of the components together to make a complete website or an application using nothing but components.

UI Component Overview First launch Flash CS4. Then, open a Flash AS3 file by selecting Flash File (ActionScript 3.0) see (Figure 1). Set stage size to any value you like. I will use a stage size of 400w x 300h, with stage color of white see (Figure 2).

Figure 2. DocumentProperties Panel

Figure 3. Essential

Figure 4. Developer

Figure 1. Flash AS3

30

Figure 5. Component Panel

02/2009 (4)


Different components with CS4

Figure 9. Actions Panel

Listing 1. ComponentsButton.fla // imports the button for use in app. import fl.controls.Button; //creates a new instance of the button

Figure 6. Library

var myButton:Button = new Button(); //adds button to stage addChild(myButton); //sets button label

Figure 7. Component Inspector1

myButton.label = "FFD Mag"; // sets the button toggle on myButton.toggle =true; // moves the button to the coordinates that correspond to 125 x, 100 y myButton.move(125, 100); //Listens for the button click to occur, once this user event occurs the // buttonClickHandler function (method) is run. myButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); // The event listener fires the buttonClickHandler function (method) // and corresponding action occurs. function buttonClickHandler(event:MouseEvent):void {

// trace statement that displays the button is infact being clicked.

}

trace("Mouse Event type: " + event.type);

Figure 8. Component Inspector2

02/2009 (4)

31


ActionScript Developement and the Component Inspector to get the panels you need. For the sake of this tutorial from here on out I will stick with the DEVELOPER layout.

UI BUTTON

Figure 10. Button

Figure 11. Button Output

The first UI component is the button. If you wanted to visually layout the components on the stage feel free to do so. However, I will use ActionScript to place the UI components on the stage directly from the library. By placing the UI button component on the stage this will automatically add the instance of the button component to the library.

Note: Not adding the UI component to the library is a common problem new users have when accessing components using only ActionScript at runtime. So make sure that you place an instance in the library for each different UI component that you decide to use see (Figure 6). If you want to access components parameters visually you would use the Component

Listing 2. ComponentsCheckBox.fla

// imports Checkbox and RadioButton

//sets the no radio button to false this means the button will not be enabled //initially

import fl.controls.CheckBox;

import fl.controls.RadioButton;

noRb.enabled = false;

// Creates instance of Checkbox

// sets the no radio button width and label

var myCheckBox:CheckBox = new CheckBox();

noRb.width = 220;

//Creates instances of RadioButton

noRb.label = "Not so much"; // sets the yes radio button to it position

var yesRb:RadioButton = new RadioButton();

// adds checkboxes and radiobuttons to stage

yesRb.move(120, 150); //sets the yes radio button to false this means the button will not be enabled //initially

addChild(myCheckBox);

yesRb.enabled = false;

addChild(noRb);

addChild(yesRb);

//

set the width of the yes radio button

// assigns a group name in order to group the radio buttons together so only one // radio button can be selected at once.

yesRb.width = 120; // sets the label of the yes radio button remember the width

noRb.groupName = "value";

above must be long

yesRb.groupName = "value";

// to hold the length of the label.

// Moves to the position

yesRb.label = " Yes!!! I LOVE FFD MAG ";

myCheckBox.move(100, 100);

// sets the event listener for the check box

//sets the width of the checkbox, if the width is not long

myCheckBox.addEventListener(MouseEvent.CLICK, clickHandler);

enough the checkbox //label will clip.

// function (method) responds to listeners dispatched event. myCheckBox.width = 220; // sets a label to the checkbox

function clickHandler(event:MouseEvent):void { // enables the corresponding radio checkbox

myCheckBox.label = "Do you like FFD Mag";

noRb.enabled = event.target.selected;

// set the no radio button into position noRb.move(120, 130);

32

}

yesRb.enabled = event.target.selected;

02/2009 (4)


Different components with CS4

Inspector. You do this by going to the RGB blocks located in the lower right of the

properties inspector see (Figures 7 and 8). You should now see the Component Inspector pop

Listing 3. ComponentsColorPicker.fla // imports color picker and Text Area and Events import fl.controls.ColorPicker;

up. You can choose from a variety of parameters to pass to the button component or whatever component you have selected on the stage. Now, since you should have a basic understanding of how to access components visually, we will start to access them quickly using AS3. First you need to delete the buttons of the stage. Then open the actions panel in whatever

import fl.controls.TextArea;

import fl.events.ColorPickerEvent; // creates instances of color picker, text area, and text format var myColorPicker:ColorPicker = new ColorPicker(); var myTextArea:TextArea = new TextArea();

var myTextFormat:TextFormat = new TextFormat(); // sets position of color picker myColorPicker.move(100, 50); // add more colors by adding more hex values to the end of the list

Figure 12. CheckRadio Output

myColorPicker.colors = [0xff0000, 0x00ff00, 0x0000ff,0x990000,0x333333,0x123456]; // creates listener which dispatches the CHANGE event as it relates to the color // picker myColorPicker.addEventListener(ColorPickerEvent.CHANGE, changeHandler); // sets the text for the text area just type whatever you want in between the // quotes. myTextArea.text = "The first ACM SIGGRAPH Conference and Exhibition on Computer

Graphics and Interactive Techniques in Asia opens in Singapore on 10 December 2008.";

Figure 13. PickerTextArea Output

// sets the text area size, this must large enough to hold all the text entered // above in the .text property

// moves the text area into it position on the stage myTextArea.move(130,50); // adds color picker and text area to stage addChild(myColorPicker); addChild(myTextArea);

Figure 15. DataGrid_Output.jpg

// Listens for the event of the color picker to be dispatched, then executes the // function (method) that then uses the TextFormat to stylize the text area with // its new color value function changeHandler(event:ColorPickerEvent):void { if(TextFormat(myTextArea.getStyle("textFormat"))){ }

myTextFormat = TextFormat(myTextArea.getStyle("textFormat"));

myTextFormat.color = event.target.selectedColor; }

myTextArea.setStyle("textFormat", myTextFormat);

Figure 16. Label Output

02/2009 (4)

33


ActionScript Developement ActionScript editor your developing in. Place the following code into your actions panel. This will create an instance of the button component and place it on the stage. A button is a basic feature of any application. Most buttons are used for things like navigation, forms or when your want to trigger a user

event. Below I commented the code so you can understand each operation see (Figure 9). If you would like to follow along go to the ComponentsButton.fla located in the files folder see (Listing 1). When you click the button, the output panel should display see (Figures 10 and 11). You could make better use

of the button by setting it to navigate to a URL or frame instead of a simple trace statement.

Figure 17. List Output

Figure 18. NumericStepper Output

Figure 19. ScrollPane Output

UI CHECKBOX and UI RADIOBOX A Checkbox is a square box that can be selected or deselected. You can add a text label to a Checkbox and place it to the left, right, above,

Listing 4. ComponentsComboBox.fla

// imports the combo box, data provider and navigateToURL this will allow

myCb.move(50, 50); // sets a default prompt

// you to complete your URLRequest (link out to the websites) import fl.controls.ComboBox;

myCb.prompt="select your search engine";

import fl.data.DataProvider;

// creates the Data Provider and then passes in the

// creates an Array name searchEngines, the label will be

myCb.dataProvider=new DataProvider(searchEngines);

import flash.net.navigateToURL;

displayed in the

searchEngines Array

// creates event listener to detect a change in the Combo Box // combo box visually, while the data is what will be passed and executed. var searchEngines:Array = new Array(

{label:"google", data:"http://www.google.com"},

// adds the Combo Box to the stage

{label:"Yahoo.com", data:"http://www.yahoo.com"},

addChild(myCb);

{label:"Live", data:"http://www.live.com"},

// function executes once it receives the listeners request

{label:"MSN", data:"http://www.msn.com"},

);

myCb.addEventListener(Event.CHANGE, changeHandler);

{label:"dogpile", data:"http://www.dogpile.com"}

// then loads the data property into a URL request to access the search // engines websites.

// creates a new instance of the combo box var myCb:ComboBox = new ComboBox();

function changeHandler(event:Event):void {

var request:URLRequest = new URLRequest();

request.url=ComboBox(event.target).selectedItem.data; navigateToURL(request);

// assigns a drop down width to the combo box this will only apply to the // drop down items

// the selectedIndex is used to reset the combo box to the

myCb.dropdownWidth=190;

// it wasn’t used the last selected item would take the place

// assigns a width to the default combo box

// prompt.

default prompt, if

myCb.width=200; // moves the combo box into position

34

of the default

}

myCb.selectedIndex=-1;

02/2009 (4)


Different components with CS4

or below the Checkbox. The same applies to the Radio Buttons. A Checkbox can be used with Radio Buttons to determine different events and outcomes. These types of components are often seen in poll questions, forms and applications with multiple selections. Place the following code into your actions panel, this will create an instance of a Checkbox and a Radio Button components and place them on the stage. If you like to follow along go to the ComponentsCheckBox.fla located in the files folder see (Listing 2). The output of this code should look like this see (Figure 12).

Figure 20. Slider Output Listing 5. ComponentsDataGrid.fla // imports the data grid and data provider import fl.controls.DataGrid; import fl.data.DataProvider; // creates a new data grid instance

Figure 21. TextInput Output var myDg:DataGrid = new DataGrid(); // adds data grid to stage addChild(myDg); // sets the column headers if you wanted to add more columns just add them to the list myDg.columns = [ "Company", "Product" ]; // sets the size of the data grid myDg.setSize(250, 120);

Figure 22. TileList Output

// moves the data grid to the correct position myDg.move(50, 50); // creates a new array var myDP_array:Array = new Array(); // by using .push this will add values to the end of the array

Figure 23. Loader Output

myDP_array.push({Company:"Adobe", Product:"Master Collection"}); myDP_array.push({Company:"Microsoft", Product:"Silverlight"}); myDP_array.push({Company:"FFD", Product:"FFD Mag"});

myDP_array.push({Company:"ESPN", Product:"ESPN The Mag"}) // data provider receives the array myDg.dataProvider = new DataProvider(myDP_array); // sets the row count equal to the length myDg.rowCount = myDg.length;

02/2009 (4)

Figure 24. ScrollBar Output

35


ActionScript Developement

Listing 6. ComponentsLabel.fla

// adds label to the stage

The Color Picker can be used to enhance the look and feel of a website or an application. The Color Picker can pass its color value to other objects in the application and is not just limited to the Text Area. The Text Area has many different uses and can be used to receive text input, display text, render HTML and much more. If you like to follow along go to the Compone ntsColorPicker.fla located in the files folder see (Listing 3). The output of this code should look like this( see Figure 13).

addChild(myLabel);

UI COMBOBOX

// imports label import fl.controls.Label; // creates new instance of label var myLabel:Label = new Label();

// HTML text can be used to modify the look and feel of the label myLabel.htmlText = '<font face="sans" color="#00ff00" size="18">Buy FFD Mag Today</ font>';

// sets position of the label myLabel.x = 100; myLabel.y = 50;

// sets width and height of the label, make sure the width is wide enough // for your text or it will clip myLabel.width = 225; myLabel.height = 22;

Listing 7. ComponentsList.fla // import list import fl.controls.List;

The Combo Box is a personal favorite of mine. I have found numerous uses for the Combo Box. It allows a user to make a selection from a drop down list of values. These values can contain a URL to send the user to, pass a value to a database and much more. If you are new to using components you will come to realize that many components are built off of other components. What I mean by that is, for example, the Combo Box is actually made of sub-components featuring the BaseButton, TextInput, and List components. Also, in this example we will learn to create an Array to pass to the Data Provider, which will help populate the Combo Box with values. If you like to follow along go to the ComponentsComboBox.fla located in the files foldersee (Listing 4). The output of this code should look like this see (Figure 14).

UI DATA GRID

myList.addItem({label:"Snow", data:"Park City"});

The Data Grid Component allows the user to display data in a grid of rows and columns. These columns can be editable and sortable. I personally have found the Data Grid Component to work very well with server side scripting. Besides server side scripts, the Data Grid can also retrieve its data from an XML file or an Array. If you like to follow along go to the ComponentsDataGrid.fla located in the files folder see (Listing 5). The output of this code should look like this see (Figure 15).

// sets size of the list

UI LABEL

// creates new instance of the list component var myList:List = new List(); // adds items to the list myList.addItem({label:"Surf", data:"Hawaii"}); myList.addItem({label:"Skate", data:"L.A."});

myList.setSize(160, 80); // moves list in to position myList.move(100,100); // places the list on the stage addChild(myList); // A event listener is set to listen for a change event myList.addEventListener(Event.CHANGE, changeHandler); // When the Listener dispatches the change event the function (method) below is run function changeHandler(event:Event):void { }

36

UI COLORPICKER and TEXTAREA

trace(event.target.selectedItem.data);

A label is exactly that - a label. You can use it to label items in your application. You can also use HTML rendering to modify the look and feel of the label. If you like to follow along go to the ComponentsLabel.fla located in the files folder see (Listing 6). The output of this code should look like this see (Figure 16).

UI LIST The List component is a scrollable single/ multiple selection list box. A list can also display graphics or other components. You can also populate your list by reading an XML file or by retrieving data from a database. If you like to follow along go to the ComponentsList.fla located in the files folder 02/2009 (4)


Different components with CS4

see (Listing 7). The output of this code should look like this see (Figure 17).

UI NUMERIC STEPPER The numeric stepper can be used to keep track of scores, count various items, etc‌ A common use of a numeric stepper is birth date applications. Your favorite web-based liquor company or tobacco company may use these to monitor the age of its visitors in order to prevent underage users from accessing there site. At this point in time I am going to start weaning you off of long commented explanations, even if you are new to components. If you have worked through everything so far you should

be getting the hang of components. Once you get familiar with a few components all of them should become familiar. If you like to follow along go to the Compon entsNumericStepper.fla located in the files folder see (Listing 8). The output of this code should look like this see (Figure 18).

UI PROGRESS BAR The Progress Bar can be used to monitor all different type of loading events. I will not touch on the Progress Bar until we build our app/site, since it is best used in pre-loading our application. For example purposes I have included a generic example

in the files accompanying this tutorial, ComponentsProgessBar.fla located in the files folder.

UI SCROLLPANE The Scroll Pane can be another really useful component since it is simple to use and can hold movie clips, JPEG, PNG, GIF and SWF files. It is great if you have an image or a file that is too large for a predefined space. If you like to follow along go to the ComponentsScrollPane.fla located in the files folder see (Listing 9). The output of this code should look like this see (Figure 19).

Listing 8. ComponentsNumericStepper.fla

// imports labels and numeric stepper import fl.controls.Label;

import fl.controls.NumericStepper; // creates new labels for numeric stepper fields var dobPrompt:Label = new Label(); var moPrompt:Label = new Label();

var dayPrompt:Label = new Label();

// creates instances of numeric steppers var moNs:NumericStepper = new NumericStepper();

var dayNs:NumericStepper = new NumericStepper(); var yrNs:NumericStepper = new NumericStepper(); // adds the labels and steppers to the stage addChild(dobPrompt); addChild(moPrompt);

addChild(dayPrompt); addChild(yrPrompt);

moPrompt.text = "Mo."; moPrompt.move(95, 50);

// set properties / values for the days prompt and stepper dayNs.move(125, 50);

dayNs.setSize(40, 22); dayNs.minimum = 1;

dayNs.maximum = 31; dayNs.stepSize = 1; dayNs.value = 1;

dayPrompt.setSize(25, 22); dayPrompt.text = "Day";

dayPrompt.move(170, 50); // set properties / values for the years prompt and stepper yrNs.move(200, 50); yrNs.minimum = 1900; yrNs.maximum = 2006; yrNs.stepSize = 1; yrNs.value = 1980;

addChild(moNs);

yrPrompt.setSize(30, 22);

addChild(yrNs);

yrPrompt.move(260, 50);

addChild(dayNs);

yrPrompt.text = "Year";

// sets properties for the date of birth prompt

Listing 9. ComponentsScrollPane.fla

dobPrompt.setSize(65, 22);

import fl.containers.ScrollPane;

dobPrompt.text = "Date of birth:"; dobPrompt.move(30, 20);

var mySp:ScrollPane = new ScrollPane(); // source to the image or file you want to load into the pane

// set properties / values for the month prompt and stepper

you can load // you can load other components in the pane as well

moNs.move(50, 50);

moNs.setSize(40, 22);

mySp.source = "http://www.justinjunda.com/FFD/images/

moNs.maximum = 12;

mySp.setSize(350, 150);

moNs.minimum = 1;

moNs.stepSize = 1; moNs.value = 1;

moPrompt.setSize(25, 22);

02/2009 (4)

ffdSnapShot.jpg";

mySp.move(20, 50); addChild(mySp);

37


ActionScript Developement UI SLIDER The slider can be a useful interactive feature to enhance the visuals within you app or web site. You can create things like 3D

rotations of images by using the slider to manipulate the image. You can also do things like control sound and video and variety of other things to achieve nice looking visual

effects. If you like to follow along go to the ComponentsSlider.fla located in the files folder see (Listing 10). The output of this code should look like this.

Listing 10. ComponentsSlider.fla

myLoader.rotationX = event.value * 1;

// note* I have changed my stage size so you can see all of

myLoader.rotationY = event.value * 1;

the image and rotations. import fl.controls.Slider;

}

import fl.containers.UILoader;

Listing 11. ComponentsTextInput.fla

sliderLabel.width = 120;

import fl.controls.Label;

import fl.controls.Label;

var sliderLabel:Label = new Label(); sliderLabel.text = "Rotate The Image"; sliderLabel.move(350, 350);

// creates new instance of the slider var mySlider:Slider = new Slider(); // sets the width of the slider mySlider.width = 200;

// set the snap interval the small the value more control you will have // the larger the value the less control you will have // however you must divide the snap interval by the maximum value // to determine how many intervals you will have mySlider.snapInterval = 10; // This is how many tick marks you will see displayed in the top // of the slider bar mySlider.tickInterval = 10; // maximum value amount for the slider, can be over 100 if you like mySlider.maximum = 100;

// This will determine where the slider starts 0 = far left, 100 = far right mySlider.move(300, 330);

// UI Loader loads in image from server, if you need more help with this skip // down to the section regarding UI Loader var myLoader:UILoader = new UILoader();

myLoader.source = "http://www.justinjunda.com/FFD/images/ ffdSnapShot.jpg";

myLoader.scaleContent = false; myLoader.x = 110

addChild(sliderLabel);

var addressTi:TextInput = new TextInput(); var tf:TextFormat = new TextFormat(); addChild(addressLabel); addChild(addressTi);

addressTi.restrict = "A-Z .a-z .0-9"; tf.font = "Arial";

tf.color = 0xFF0000; tf.size = 16;

addressLabel.text = "Address: " ; addressLabel.setSize(100, 25); addressLabel.move(50,100);

addressLabel.setStyle("textFormat", tf); addressTi.move(160, 100);

addressTi.setSize(200, 25);

addressTi.setStyle("textFormat", tf);

Listing 12. ComponentsTileList.fla import fl.controls.CheckBox;

import fl.controls.ColorPicker; import fl.controls.NumericStepper; import fl.controls.TileList; import fl.data.DataProvider;

var myCb:ComboBox = new ComboBox(); var myTl:TileList = new TileList();

{label:"ComboBox", source:myCb},

addChild(myLoader);

mySlider.addEventListener(SliderEvent.CHANGE, changeHandler); function changeHandler(event:SliderEvent):void {

// once the event handler detects a change this function will run and will // cause the instance of myLoader to rotate on the X and Y, depending on the If you want you can un-comment the z rotation to move on the // Z axis.

var addressLabel:Label = new Label();

{label:"Mike", source:""},

addChild(mySlider);

// slider values.

import fl.controls.TextInput;

var dp:Array = [

myLoader.y = 100

The default anchor point is in the top left of the loader.

38

//myLoader.rotationZ = event.value * 1;

import fl.events.SliderEvent;

{label:"Laurie", source:""}, {label:"Sam", source:""}, ];

myTl.dataProvider = new DataProvider(dp); myTl.columnWidth = 110; myTl.rowHeight = 100;

myTl.setSize(350,150); myTl.move(25, 50);

myTl.setStyle("contentPadding", 5); myTl.sortItemsOn("label"); addChild(myTl);

02/2009 (4)


Different components with CS4

UI TEXTINPUT

Listing 13. ComponentsUILoader.fla

the Text Area component. If you like to follow along go to the ComponentsTextInput.fla located in the files folder see (Listing 11). The output of this code should look like this see (Figure 21).

import fl.containers.UILoader;

UI TILE LIST

A Text Input component is a single line text input for a typical text field in the Flash

environment. You can access all of the properties of a text field using this input. However, if you need a multi-line text input you should use

myLoader.x = 100;

The Tile List component is made up of rows and columns, populated by the data provider. An item is data that is stored in a cell in the Tile List. Server side code can be used or you can create any Array to populate the Tile List. If you like to follow along go to the ComponentsTileList.fla located in the files folder see (Listing 12). The output of this code should look like this see (Figure 22).

addChild(myLoader);

UI LOADER

var myLoader:UILoader = new UILoader(); // Loads whatever file or image you specify as the source.

It can load

// most images and all swf files. myLoader.source = "http://www.justinjunda.com/FFD/images/ffdSnapShot.jpg"; myLoader.scaleContent = false; myLoader.y = 100;

// listens for the loader to complete the loading of the image.

Then

// it launchs the completeHandler function which display how many bytes were loaded myLoader.addEventListener(Event.COMPLETE, completeHandler); function completeHandler(event:Event) { }

trace("Number of bytes loaded: " + myLoader.bytesLoaded);

Listing 14. ComponentsUIScrollBar.fla import flash.net.URLLoader;

import fl.controls.UIScrollBar; import flash.events.Event;

var myTxt:TextField = new TextField(); myTxt.border = true; myTxt.width = 200; myTxt.x = 200; myTxt.y = 150; var mySb:UIScrollBar = new UIScrollBar(); mySb.direction = "horizontal";

// Size it to match the text field. mySb.setSize(myTxt.width, myTxt.height); // Move it immediately below the text field. mySb.move(myTxt.x, myTxt.height + myTxt.y); // put them on the Stage addChild(myTxt); addChild(mySb);

The UILoader component is essentially a container it can display SWF, JPEG, progressive JPEG, PNG and GIF files. You can retrieve content from a remote server and pull it into a Flash application. These are good for quickly adding images to apps and displaying photos. If you like to follow along go to the ComponentsUILoader.fla located in the files folder see (Listing 13). The output of this code should look like this see (Figure 23).

UI SCROLLBAR The ScrollBar component lets you to add a scroll bar to a text field. This is great for anytime you have a predefined space and not enough room for a lot of text. The ScrollBar component also can scroll HTML content if the Text Area is set to contain HTML content. If you like to follow along go to the Compo nentsUIScrollBar.fla located in the files folder see (Listing 14). The output of this code should look like this see (Figure 24). This wraps up Part One of the component tutorial series. I hope you found this informative and helpful. As mention earlier in this tutorial, components are an excellent way to either enhance a site or build a site from scratch. In Part Two, I will take everything we have learned in this overview of components and put our knowledge to work. After viewing some sample sites we will build our own site, using only components.

// load text

var loader:URLLoader = new URLLoader();

var request:URLRequest = new URLRequest("http://www.helpexamples.com/flash/lorem.txt"); loader.load(request);

loader.addEventListener(Event.COMPLETE, loadcomplete); function loadcomplete(event:Event) { // move loaded text to text field myTxt.text = loader.data;

// Set myTxt as target for scroll bar. }

mySb.scrollTarget = myTxt;

02/2009 (4)

JUSTIN P. JUNDA

Justin Junda is a New Media Engineer, specializing in Flash / AS2-3, Photoshop, After Effects, PHP, MySQL and a slue of other programming languages. Justin also loves to travel and has a strong passion for teaching others how to use these technical products. He currently works with a top government-contracting firm; implementing new media ideas into interactive courseware that is then delivered to the military in order to effectively train them. You can reach Justin at justin@justinjunda.com with any thoughts or concerns you have regarding this article. 39


ActionScript Developement

Model View Controller – What's the Secret Sauce... ? by Anton Krasnoshchok Business applications consist of a user interface (UI), business logic, and data models. For example, standard UI components such as buttons or checkboxes have UI elements, logic that knows how to respond to user inputs, and data models. What you will learn...

What you should know...

• What is Model-View-Controller Pattern • How to use Model, View and Controller together • What is Cairngorm • How to use Cairngorm pieces together

• Familiar with OOP in ActionScript 3.0 • Familiar with developing Flex Application • Standard Flex Components such as Datagrid, Labels, Panel etc. • Singleton pattern • Using Remote Objects in ActionScript 3.0 • Using data binding in Flex

Model View Controller Level of difficulty

M

any developers write code that combines all of these elements into one large object, rather than several small units that work together. In rich user interfaces, when UI, business logic and data are all integrated into one object, it can lead to some of the following problems:

Model – View – Controller (MVC) is an architectural pattern used in software engineering. The MVC pattern is most commonly used to create interfaces for software applications, and as the name implies, consists of three elements:

• Model: Contains the application data and logic to manage the state of the application. • View: Presents the UI and the state of the application on the server. • Controller: Handles user inputs to change the state on the application. Each element has a well-defined role. The Model manages state, the View represents state, and the Controller handles user inputs. This allows each element to be swapped out without affecting other elements. If we need a different behavior for a particular user interface in a view, we simply substitute a different Controller for it. This makes the MVC pattern very customizable and allows reuse.

����� �

• Difficult to use the data outside of the object • Hard to extend the object • Hard to change the UI, when the UI and data are locked in the same object. In this case you would have to create not only a new UI, but also transfer all the data from the old UI to the new one • Hard to use multiple views of the same data. For example you may want to display different charts styles of the same data set • Difficult to synchronize multiple view of the same data. For example, you might want to update data in different charts styles over time as the data changes. In this case you would have to update each data set in each object

����������

���� �

���������������������������������������������������������������

���������������������������������������������������

����������������������������������������

�����������������������������������������

���������������������������������������������������������������������������������

Figure 1. MVC triad

40

02/2009 (4)


Model View Controller

Using Model, View and Controller together is called the MVC triad. Figure 21, shows the graphical representation of the MVC triad. If no changes in the Model are required in the View due to user inputs, the Controller

will not request any changes to be made. Also, the Controller can, on its own, request changes in the View. Changes in the Model are always initiated by user interaction. The Model can update itself based on certain events. For example, in

an application we want to display a chart that displays user's activity. The Model would hold the user activity data and the model could set a timer to periodically update the chart from a web service. Then, whenever the Model updates its data, it would inform

Listing 1. Developing Customer Value Object class package com.uwiss.mvc.vo

import mx.collections.ArrayCollection;

{

[Bindable]

[RemoteClass(alias="com.uwiss.mvc.model.Customer")]

public final class ModelLocator implements

[Bindable]

public class Customer {

IModelLocator {

private var _id:int;

private static var instance:ModelLocator;

private var _lastName:String;

public var customerCollection:ArrayCollection;

private var _firstName:String; // and so on ………………

public function ModelLocator(access:Private) {

public function Customer(){

if ( access == null ) {

throw new CairngormError( CairngormessageCodes.SINGLE

} public function get id():int{ }

return _id;

}

{

_id=pData;

}

_firstName=pData;

public function get lastName():String{ }

return _lastName;

public function set lastName(pData:String):void{ }

_lastName=pData;

// and so on …………………………

}

}

Listing 2. Developing a singleton ModelLocator package com.uwiss.mvc.model {

import com.adobe.cairngorm.CairngormError; import com.adobe.cairngorm.CairngormMessageCodes;

instance = new ModelLocator( new Private() );

return instance;

return _firstName;

public function set firstName(pData:String):void{

if ( instance == null ){ }

public function get firstName():String{ }

instance = this;

public static function getInstance() : ModelLocator

public function set id(pData:int):void{ }

TON_EXCEPTION, "ModelLocator" );

}

}

} /**

* Inner class which restricts constructor access to Private */

class Private {}

Listing 3a. Adding service CustomerService to Cairngorm Service Locator <?xml version="1.0" encoding="utf-8"?> <cairngorm:ServiceLocator xmlns:mx="http://www.adobe.com/2006/ mxml"

xmlns:cairngorm="com.adobe.cairngorm.business.*" >

<mx:RemoteObject

id="CustomerService"

destination="amfphp"

makeObjectsBindable="true"

source="com.uwiss.mvc.service.CustomerService" showBusyCursor="true">

</mx:RemoteObject>

</cairngorm:ServiceLocator>

import com.uwiss.mvc.vo.Customer;

02/2009 (4)

41


ActionScript Developement the View that its state has changed. As you can see in the MVC triad, each of the elements has a specific type of relationship with the other elements. The Model must always remain independent of the View and

the Controller. This means that the Model cannot know about any other elements. This does not mean that the Model does not communicate with the other elements. A model can broadcast messages when the data

changes by broadcasting the message without having to know, who is listening. This use of events allows the Model to be decoupled from the other subsystems, allowing for greater flexibility.

Listing 3b. Creating service delegate CustomerServiceDelegate package com.uwiss.mvc.business {

{

import com.adobe.cairngorm.control.CairngormEvent;

import com.uwiss.mvc.vo.*;

import com.uwiss.mvc.business.*;

import mx.rpc.IResponder;

import com.uwiss.mvc.model.ModelLocator;

public class CustomerServiceDelegate {

import com.adobe.cairngorm.commands.ICommand;

import mx.controls.Alert; import mx.rpc.IResponder;

private var responder : IResponder;

import mx.rpc.events.FaultEvent;

private var service : Object;

public class GetAllCommand implements ICommand,

public function CustomerServiceDelegate(responder : IResponder ){

{

this.service = ServiceLocator.getInstance().getRemoteObject(

IResponder

public function execute(event:CairngormEvent):void{ var delegate : CustomerServiceDelegate = new

"CustomerService" );

this.responder = responder;

CustomerServiceDelegate( this );

public function getAll():void{

}

var call:Object = service.getAll();

}

}

}

public function result(data:Object):void{

var returnedData:Array = data.result as Array;

call.addResponder(responder);

var appModel:ModelLocator = ModelLocator.getInstance(); }

var faultEvt:FaultEvent = event as FaultEvent;

package com.uwiss.mvc.event import com.adobe.cairngorm.control.CairngormEvent;

}

}

Alert.show(faultEvt.fault.message);

import com.uwiss.mvc.vo.Customer;

}

import flash.events.Event;

Listing 6. Extending Cairngorm Front Controller

public class CustomerEvent extends CairngormEvent

package com.uwiss.mvc.control

{

public static const EVENT_GET_ALL_CUSTOMERS:String='getAllCu

{

import com.adobe.cairngorm.control.FrontController; import com.uwiss.mvc.command.customer.*;

stomers';

import com.uwiss.mvc.event.*;

public var customer:Customer;

public final class FController extends FrontController {

public function CustomerEvent (pType:String, pCustomer:

public function FController() {

Customer=null){

customer= pCustomer; }

super(pType);

}

}

}

this.initialize();

private function initialize() : void {

override public function clone():Event{

}

appModel.customerCollection.source = returnedData;

public function fault(event:Object):void{

Listing 4. Developing CustomerEvent class

{

delegate.getAll();

this.addCommand( CustomerEvent.EVENT_GET_ALL_

return new CustomerEvent(type, customer);

}

}

}

CUSTOMERS, GetAllCommand );

Listing 5. Create GetAllCommand package com.uwiss.mvc.command.customer

42

02/2009 (4)


Model View Controller

The most important key to the MVC pattern is that the Model must be an independent object that does not have a reference to the View or Controller. The view updates and redraws itself based on changes to the Model.

Cairgorm Framework Cairngorm is one of the primary open source frameworks for application architecture in Adobe Flex. It is specifically designed to facilitate complex state and data synchronization between the client and the server, while keeping the programming of the View layer detached from the data implementation. Cairngorm is fundamentally a methodology for breaking up an application's code into logical functions; by data, by user views, and

by the code that controls everything. This is routinely referred to as MVC, or Model, View, and Control. The Pieces of Cairngorm • Model Locator: Stores all of your application’s Value Objects (data) and shared variables, in one place • View: One or more Flex components (button, panel, combo box, Tile, etc) bundled together as a named unit, bound to data in the Model Locator, and generating custom Cairngorm Events based on user interaction (clicks, rollovers, drag-and-drop etc.) • Front Controller: Receives Cairngorm Events and maps them to Cairngorm Commands.

• Command: Handles business logic, calls Cairngorm Delegates and/or other Commands, and updates the Value Objects and variables stored in the Model Locator • Delegate: Created by a Command, which instantiates a remote procedure call (HTTP, Web Services, etc) and hands the results back to that Command • Service: Defines the remote procedure calls (HTTP, Web Services, etc) to connect to remote data stores.

Example: Customers list In this example we will build an application based on the Cairngorm framework. We will display a customer list stored on the server and also full information about the requested customer.

Listing 7. Creating the main view of the application <?xml version="1.0" encoding="utf-8"?>

[Bindable]

public var collection:ArrayCollection = new

<mx:Application

xmlns:mx="http://www.adobe.com/2006/mxml"

ArrayCollection();

private var appModel:ModelLocator = ModelLocator

xmlns:cview="com.uwiss.mvc.view.customer.*" xmlns:control="com.uwiss.mvc.control.*"

.getInstance();

xmlns:business="com.uwiss.mvc.business.*"

private function init():void{

<mx:Script>

appModel.customerCollection = collection;

var evt:CustomerEvent = new CustomerEvent(Cus

<![CDATA[

import com.uwiss.mvc.model.ModelLocator;

tomerEvent.EVENT_GET_ALL_CUSTOMERS);

[Bindable]

public var appModel:ModelLocator = ModelLocator.getIn stance();

private function initApplication():void // dispatch your first event here

]]>

]]>

}

evt.dispatch();

</mx:Script>

{

<mx:DataGrid

id="dg" width="100%" height="100%"

}

dataProvider="{collection}" doubleClickEnabled="true"> <mx:columns>

</mx:Script>

<mx:DataGridColumn dataField="id" headerText="Id" />

<control:FController id="controller"/> <business:Services id="services"/>

<mx:DataGridColumn dataField="lastName" headerText="Last

<cview:CustomerList />

</mx:Application>

</mx:columns>

Name" />

</mx:DataGrid>

Listing 8. Creating CustomerList view

</mx:Panel>

<?xml version="1.0" encoding="utf-8"?>

Listing 9. Adding getById method

<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" width="100%"

height="100%"

creationComplete="init()" title="Customers List"> <mx:Script>

<![CDATA[

import mx.events.ListEvent; import mx.controls.Alert;

import mx.containers.TitleWindow;

public function getById(id:Number):void{

var call:Object = service.getById(id);

}

call.addResponder(responder);

Listing 10. Adding new event identifier public static const EVENT_GET_CUSTOMER:String='getCustomer';

import mx.managers.PopUpManager;

import com.uwiss.mvc.model.ModelLocator; import mx.collections.ArrayCollection; import com.uwiss.mvc.vo.Customer;

import com.uwiss.mvc.event.CustomerEvent;

02/2009 (4)

43


ActionScript Developement For the first iteration of our application, shown in (Figure 2), we will show the customer list stored on the server using standard Flex component called Datagrid. The Full sources structure can be seen in Figure 3. Let’s develop a Customer Value Object class (Listing 1). Next step is to develop a singleton ModelLocator (Listing 2). It will include the Customer's List (customerCollection). To get the data from server we need to add a service (CustomerService) to the Cairngorm Service Locator (Listing 3a) and create service delegate (CustomerServiceDelegate) (Listing 3b). In this application, I used PHP + AMFPHP 1.9, on server side (The sources are on the CD), but I would have prefered to use JAVA + WebORB, since I prefer JAVA over PHP. The next step is to develop a CustomerEvent class (Listing 4).

Figure 2. First iteration of the application

Listing 11. Creating GetByIdCommand package com.uwiss.mvc.command.customer {

import com.adobe.cairngorm.commands.ICommand;

import com.adobe.cairngorm.control.CairngormEvent; import com.uwiss.mvc.business.*; import com.uwiss.mvc.event.*;

import com.uwiss.mvc.model.ModelLocator; import mx.controls.Alert;

import mx.rpc.IResponder;

import mx.rpc.events.FaultEvent; public class GetByIdCommand {

implements ICommand, IResponder

public function execute(event:CairngormEvent):void { var evt:CustomerEvent = event as CustomerEvent;

var delegate : CustomerServiceDelegate = new CustomerServiceDelegate( this ); }

delegate.getById(evt.customer.id);

Figure 3. Full sources structure

public function result(data:Object):void {

var appModel:ModelLocator = ModelLocator.getInstance();

}

appModel.fullCustomerInfo.source = [data.result];

public function fault(event:Object):void {

var faultEvt:FaultEvent = event as FaultEvent;

}

}

}

Alert.show(faultEvt.fault.message);

Listing 12. Adding command to FController this.addCommand( CustomerEvent.EVENT_GET_CUSTOMER, GetByIdCommand);

Figure 4. Second iteration of the application

44

02/2009 (4)


Model View Controller

Listing 13. Creating CustomerInfo view

ame}" />

<mx:Label text="Email Address: {customer.getItemAt(0

<?xml version="1.0" encoding="utf-8"?>

).email}" />

<mx:TitleWindow

<mx:Label text="Street Address 1: {customer.getItemA

xmlns:mx="http://www.adobe.com/2006/mxml"

t(0).address1}" />

xmlns:vo="com.uwiss.mvc.vo.*"

<mx:Label text="Street Address 2: {customer.getItemA

height="360"

<mx:Label text="City: {customer.getItemAt(0).city}"

title="Customer info">

<mx:Label text="State: {customer.getItemAt(0).state

width="300"

t(0).address2}" />

creationComplete="init()"

/>

<mx:Script>

}" />

<![CDATA[

<mx:Label text="Zipcode: {customer.getItemAt(0).zip

import mx.managers.PopUpManager;

<mx:Label text="Country: {customer.getItemAt(0).cou

import com.uwiss.mvc.model.ModelLocator;

<mx:Label text="Phone: {customer.getItemAt(0).phone

import mx.collections.ArrayCollection;

code}" />

import mx.controls.Alert;

ntry}" />

import com.uwiss.mvc.vo.Customer;

}" />

import com.uwiss.mvc.event.CustomerEvent;

<mx:Label text="Fax: {customer.getItemAt(0).fax}"

[Bindable]

private var customer:ArrayCollection = new

</mx:VBox>

ArrayCollection();

<mx:HBox horizontalAlign="center" width="100%">

private var appModel:ModelLocator = ModelLocator.getInsta

<mx:Button label="Close" click="closeWindow()" />

nce();

private function init():void{

</mx:HBox>

</mx:VBox>

appModel.fullCustomerInfo = customer;

</mx:TitleWindow>

var evt:CustomerEvent = new

CustomerEvent(CustomerEvent.EVENT_GET_CUSTOMER,

Listing 14. Adding show full info method to CustomerList view

evt.dispatch();

private function showFullInfo(evt:ListEvent):void{

appModel.selectedCustomer);

var selectedCustomer:Customer = new Customer();

private function closeWindow():void{ }

/>

selectedCustomer.id = dg.selectedItem.id;

PopUpManager.removePopUp(this);

appModel.selectedCustomer = selectedCustomer;

var popup:CustomerInfo=CustomerInfo(PopUpManager.create

]]>

PopUp(this,CustomerInfo,false));

</mx:Script>

<mx:VBox width="100%" height="100%">

}

<mx:VBox height="100%">

PopUpManager.centerPopUp(popup);

<mx:Label text="Id: {customer.getItemAt(0).id}" />

<mx:Label text="First Name: {customer.getItemAt(0).first Name}" />

<mx:Label text="Last Name: {customer.getItemAt(0).lastN

As you can see we have an event (getAll Customers) to get the customers list, next create the GetAllCommand, which will be executed on this event (Listing 5). Next step is to extend Cairngorm Front Controller to create a controller of our application which will connect events and commands – FController class (Listing 6). Let’s create the main view of our application (Listing 7) and the CustomerList view (Listing 8). For the second iteration of our application shown in Figure 4, we will display the full information about the requested customer.

First we need to add selectedCustomer and fullCustomerInfo variables to the ModelLocator. We need it because we have to store information about customer. Then we have to add getById method (Listing 9) to created service delegate CustomeServiceDelegate (Listing 3b). After that we need to add new event identifier (Listing 10) to CustomerEvent (Listing 4) and create GetByIdCommand (Listing 11). Next step is to add command (Listing 12) to our FController (Listing 6). Then let’s create CustomerInfo view (Listing 13) and add show

On the 'Net • •

http://en.wikipedia.org/wiki/Model-view-controller http://en.wikipedia.org/wiki/Cairngorm_(Flex_framework)

02/2009 (4)

full info method (Listing 14) to CustomerList view (Listing 8).

Conclusion The MVC pattern provides a clear framework for design. The separation of responsibilities among the Model, View and Controller elements allows easy substitution of elements without any disruptions to the overall application. This lets us easily expand applications based on the MVC pattern to meet changing requirements.

ANTON KRASNOSHCHOK Anton Krasnoshchok is a Dutch Flex developer working for U-wiss in the Ukraine. He likes to develop complex business applications using Flex and JAVA. http://www.linkedin.com/in/antonkrasnoshchok

45


ActionScript Developement

JSFL Quirks by Christopher W. Allen-Poole Often, a project in Flash will become, well, tedious. One particular aspect is repeated a hundred different ways a hundred times. Fortunately, the past several generations of the Flash IDE have included two tools to help with such a task. What you will learn...

What you should know...

• Some easy techniques to make building a Flash extension easier • Several quirks that you may encounter in Flash's JavaScript API • Hacks to get around these limitations

• How to create a component • Some JavaScript • A rudimentary knowledge of JSAPI/JSFL (to recognize functions)

Level of difficulty

abbreviation\Configuration\WindowSWF) then Flash needs to be closed and restarted.

This is tedious, to say the least. It can be made easier by having JSFL file which only calls the function fl.reloadTools(), but this still requires that the swf is either dragged into or published in the WindowSWF directory. The purpose of a loader swf is to make this as short as possible. With a loader, the Panel swf remains the same, so Flash does not need to reload it. (The code to accomplish this is found in (Listing 1)). All that one needs to do now is close and re-open the panel

Listing 1. The loader swf

F

irst there is something called the Flash JavaScript API (called JSFL after the file extension) and second there is the ability to create custom menus from swf's. Both of these can be incredibly useful, but they can be confusing as well, especially when combined. Before we begin, it is probably a good idea to create a good testing environment. This means that you will probably want to create a JSFL file even if you eventually hope to make a new Flash Panel – it is much easier to test things through a JSFL file in the Commands menu than it is through a swf. The file should be saved to the Commands folder in the Configuration directory (on a PC this is C: \Documents and Settings\name of the user\ Local Settings\Application Data\Adobe\Flash CS3\language abbreviation\Configuration\ Commands). I very strongly suggest that you create a loader swf. This is simply something for the testing environment which will make life far simpler. Any time that a panel is updated, it means that a swf needs to be moved from wherever it is published into the WindowSWF directory (C:\Documents and Settings\name of the user\Local Settings\ Application Data\Adobe\Flash CS3\language 46

var urlReq:URLRequest = new URLRequest('file:///c:/path_to_your_swf.swf'); var loader:Loader

= new Loader();

loader.load(urlReq); addChild(loader);

Listing 2. The Panel File Flash: import flash.events.MouseEvent

ClickMe.addEventListener(MouseEvent.CLICK, create) public function fire(o:* = null){ }

Flex: <?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" <mx:Script>

width="118" height="68">

<![CDATA[

import adobe.utils.MMExecute private function fire(){

}

]]>

</mx:Script>

<mx:Button x="21.5" y="23" label="Click Me!" click="fire()"/> </mx:Application>

02/2009 (4)


JSFL Quirks

to have the latest version of the swf Panel. (If this process seems excessively long, it is relatively simple to create either a button or a EventListener which will allow you to load the latest version without closing the window). The next step is the creation of the files which will eventually become the panel. I have provided the necessary Flex and Flash code to create such a swf, all that needs to

be done, for those using Flash, is to create a button named, ClickMe. (Listing 2). Eventually, this will trigger JSFL code, but there are some important things to note first. The most important advise that can be given, at this point, is that that putting long Strings into MMExecute (the command which translates for JSFL) is a bad idea and should be avoided at all costs. The Flash IDE

Listing 3. Flex wrappers

var myXML:XML = <script><![CDATA[fl.t race(“foo�)]]></script>.

The better news is that this means that this means that it is possible to do most of the work in a much

// addNewText with the same arguments

/**

//that this function received.

* Returns whether the JavaScript window.location.href property

doc.selectAll();

var txt = doc.selection[0]; //This is the object we're

exists. if it does, that means this

* function is being fired within a browser and therefore in Flex's

looking for.

Debug mode. Otherwise, (as

doc.selectNone();

if(orig) doc.selection = orig; // re-assign the original

* ExternalInterface does not call anything as a Flash extension), it returns false.

**/

function isDebug():Boolean{

return Boolean(ExternalInterface.call("window.location.href .toString"));

}

selection.

}

return txt;

function addItemToDocumentFixed(position, namePath){

var orig = doc.selection; // Copy the original selection. lib.addItemToDocument.apply(this, arguments); doc.selectAll();

var obj = doc.selection[0]; //This is the object we're

/** * If in the Flash IDE, this will call MMExecute, otherwise it

looking for.

will simply return null.

**/

doc.selectNone();

if(orig) doc.selection = orig; // re-assign the original selection.

function MMExecuteWrap(js:*):String{ if(isDebug()) return null;

return MMExecute(js); // MMExecute will return whatever the JavaScript is supposed to return

}

}

return obj;

Listing 6. Create component function dupeComponent(newname){

/**

var libname = 'dummyComponent'; // Replace with the name of

* Calls MMExecute(fl.trace(param)) if in the Flash IDE, trace if

the object in the library

outside.

lib.duplicateItem(libname);

lib.renameItem(newname); // rename it to make sure that

function traceWrap(str:*):void{

the copy

MMExecuteWrap('fl.trace("'+str+'")');

}

will not provide line numbers for JavaScript errors and forgetting a semicolon could mean hours and hours of work lost. The good news is that, while the documentation for MMExecute does not mention this, it will still accept XML objects with this format:

// doesn't overwrite the original.

trace(str);

Listing 4. Useful code

}

// Place this code in an MMExecute somewhere before the first function call. var doc

= fl.getDocumentDOM();

var time

= function (){return fl.getDocumentDOM().getTimeline

var lib

lib.editItem(newname);

function sync(templateObj, newObj){

var template = lib.items[lib.findItemIndex(templateObj)]; var target

= lib.items[lib.findItemIndex(newObj)];

target.linkageExportForAS = template.linkageExportForAS;

= doc.library; ();}

sync(libname, newname);

}

target.linkageBaseClass = template.linkageBaseClass;

Listing 5. A better addItemToDocument and addNewText function addNewTextFixed(boundingRectangle, text){

var orig = doc.selection; // Copy the original selection.

doc.addNewText.apply(this, arguments) // This simply calls the function

02/2009 (4)

47


ActionScript Developement faster, more legible, and more forgiving manner than simply using incredibly long Strings. If the extension is being written in Flex, then it is imperative that the functions from (Listing 3) are used. This is because while Flash will allow MMExecute without throwing an error, Flex will not – this means that any time MMExecute fires, Flex will crash the swf.

Putting a simple wrapper around MMExecute and trace will allow continued output even when operating outside of the Flash IDE. Now that a good testing environment is established, it would probably be a good idea to go over some of the behavior of JSFL. First, it is important to note that while much of the syntax is the same as JavaScript's, there are some very substantial differences between

Listing 7. Up to this point

how JavaScript might behave on a web-page and how it behaves in Flash. This has both to do with the differences in the Document Object Model and the particular functions which have been created for Flash. That said, functions are still functions, variables are still variables, and a knowledge of JavaScript should certainly not be discredited, as it is very useful.

]]></script>

MMExecute(variables);

// Call init either as initialize="{init()}" in Flex or as part of the constructor in Flash. // If in Flex, replace MMExecute with MMExecuteWrap

// Now Flash has the variables and functions stored in memory.

private function init():void{

var variables:XML = <script><![CDATA[ var doc

= fl.getDocumentDOM();

var time

= function (){return fl.getDocumentDOM().getTime

var lib

= doc.library;

} private function fire(a:* = null):void{

MMExecute("dupeComponent('myNewComponent')"); // MMExecute with a String.

var newCommands:XML = <script><![CDATA[

line();}

]]></script>;

lib.editItem();

var functions:XML = <script><![CDATA[

var txt = addNewTextFixed({top:0, left:0, right:100,

function dupeComponent(newname){

bottom:100}, "this is JSFL");

var libname = 'myComponent';

txt.setTextAttr("italic", true); // a command sent to a

lib.renameItem(newname);

doc.setElementTextAttr("bold", true); // the same done

sync(libname, newname);

lib.selectNone();

lib.duplicateItem(libname);

Text object

lib.editItem(newname); }

through doc.

lib.editItem();

]]></script>

function sync(templateObj, newObj){

var template = lib.items[lib.findItemIndex(templateObj)]; var target

target.linkageExportForAS target.linkageExportForRS target.linkageBaseClass

= template.linkageExportForAS; = template.linkageExportForRS;

ss;

}

= template.linkageBaseCla

MMExecute("var myComponent = addItemToDocumentFixed({x:0, y:0}, 'myNewComponent')");

}

Listing 8. An Array Parameter // First way

function addNewTextFixed(boundingRectangle, text){ var orig = doc.selection;

doc.addNewText.apply(this, arguments); doc.selectAll();

doc.selection[0].parameters["array"].insertItem(0,

"something", "somethingelse", "String");

var txt = doc.selection[0];

doc.selection[0].parameters["array"].removeItem(1);

if(orig) doc.selection = orig;

// In a loop.

doc.selectNone();

}

MMExecute(newCommands); // MMExecute with XML.

= lib.items[lib.findItemIndex(newObj)];

return txt;

var valueArray = new Array("foo", "bar", "baz");

var targParam = doc.selection[0].parameters["array"];

function addItemToDocumentFixed(position, namePath){

var orig = doc.selection; // Copy the original selection. lib.addItemToDocument.apply(this, arguments); doc.selectAll();

var obj = doc.selection[0]; //This is the object we're

for(var i = 0; i < valueArray.length; i++){ targParam.insertItem(i, valueArray[i],

}

valueArray[i],"String");

targParam.removeItem(i + 1);

looking for.

doc.selectNone();

if(orig) doc.selection = orig; // re-assign the original selection.

}

48

return obj;

02/2009 (4)


JSFL Quirks

One noticeable difference between JavaScript and JSFL is scope. Not only do variables and functions created either through MMExecute or a command from a JSFL file will continue to exist so

long as Flash remains open (as opposed to JavaScript which is often has a pagespecific context), but they are all defined globally. This makes a number of tasks much simpler, especially as it allows the

Listing 9. A final Flex project

doc.selectNone();

if(orig) doc.selection = orig;

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"

}

width="118" height="68" initialize="{init()}">

var orig = doc.selection;

<![CDATA[

import adobe.utils.MMExecute

lib.addItemToDocument.apply(this, arguments); doc.selectAll();

function isDebug():Boolean{

var obj = doc.selection[0];

return Boolean(ExternalInterface.call("window.location.href

doc.selectNone();

if(orig) doc.selection = orig;

.toString"));

}

function MMExecuteWrap(js:*):String{ if(isDebug()) return null;

}

}

trace(str);

MMExecuteWrap(variables); }

var newCommands:XML = <script><![CDATA[ lib.editItem();

var txt = addNewTextFixed({top:0, left:0, right:100,

var variables:XML = <script><![CDATA[ var lib

var time ]]></script>;

bottom:100}, "this is JSFL");

txt.setTextAttr("italic", true);

= fl.getDocumentDOM();

doc.setElementTextAttr("bold", true);

= doc.library;

= function (){return fl.getDocumentDOM().getT

lib.selectNone();

imeline();}

lib.editItem();

]]></script>

var functions:XML = <script><![CDATA[ function dupeComponent(newname){

var myVal:String

var libname = 'myComponent';

MMExecute("var myComponent = addItemToDocumentFixed({x:

lib.renameItem(newname);

0, y:0}, 'myNewComponent');"+

lib.editItem(newname);

sync(libname, newname);

function sync(templateObj, newObj){

var template = lib.items[lib.findItemIndex (templateObj)];

var target = lib.items[lib.findItemIndex(newObj)]; target.linkageExportForAS = template .linkageExportForAS;

= "thisWillBeSentToJSFL";

MMExecute(newCommands);

lib.duplicateItem(libname);

}

MMExecuteWrap(functions);

private function fire(){

private function init():void{ var doc

return obj;

]]></script>

return MMExecute(js);

function traceWrap(str:*):void{

return txt;

function addItemToDocumentFixed(position, namePath){

<mx:Script>

}

shortcuts in (Listing 4) (strangely enough both doc and lib variables will continue to work regardless of which document one is in while doc.getTimeline() has to be called any time JSFL moves into or out of a

"myComponent.parameters['array'].insertItem(0, '"+ myVal }

+"','"+ myVal +"','String')");

]]>

</mx:Script>

<mx:Button x="21.5" y="23" label="Click Me!" click="fire()"/ >

</mx:Application>

target.linkageExportForRS = template .linkageExportForRS;

}

target.linkageBaseClass0 = template.linkageBaseClass;

function addNewTextFixed(boundingRectangle, text){ var orig = doc.selection;

doc.addNewText.apply(this, arguments); doc.selectAll();

var txt = doc.selection[0];

02/2009 (4)

49


ActionScript Developement symbol). It should also be noted that (unlike in regular JavaScript) modifying an object's prototype (ie. Library.prototype.foo = function(){}) does not always work and can yield very inconsistent results. While there can be some modifications made, it is a much better and safer idea to simply create external objects than to modify the classes provided. There are other types of quirks which the JSFL programmer needs to watch out for. Perhaps the most bizarre and confusing example has to do with addressing objects which are added to the stage through JavaScript. The functions doc.addNewText and lib.addItemToDocument do not return anything, which means that the only way to find the object which was just placed on the stage is through calling doc.selectAll and then getting the first object in the doc.selection array. (Listing 5 has two functions which do the same thing, but return the object which was created). Actually, the very nature of the property arrays (doc.selection, lib.items, etc.) is a bit strange. One would expect doc.selection.push to work as it would with another array. Sadly, this is not the case. The array cannot be directly manipulated. It can, however, in a very indirect way, be re-assigned if the line doc.selectNone() is included. Thus doc.selection.pop() does not work, but var select

=

doc.selection;

doc.selectNone(); select; will work.

select.pop();

doc.selection

=

And, if that were not confusing enough, much of the time the means by which one modifies many of the properties of objects which have been added to the stage is not by accessing the object, but either making sure that it is the first item in the document.selection Array or that it was the last item created. For example, setTextRectangle (the function which defines the size and shape of a text object) is a function found on the Document object and there is no equivalent on the Text object. In general, if a desired command cannot be found on a particular object or class, then it is a good idea to check the parent object. If it cannot be found in the Elements

class, check the Frame class. If it cannot be found there, check the timeline class (it is an interesting fact that there are no functions associated with the layer class at all) and then on the Document Object Model itself. Unfortunately, there are some cases when the desired function is not available anywhere. The largest case of the JSFL demonstrating such a weakness is in the automation of the creation of components. And while it is not possible to make that process completely run by machine, it is certainly possible to make the process faster. The first step is the creation of an empty component. Create a symbol in the library and name it dummyComponent. Right click on it and select Component Definition. For the purposes of this demonstration, it would be best to create several parameters – a list parameter named list, an array parameter named array and a String parameter named string. (Listing 6) shows the function which creates the new component. It is fairly simple. It merely creates a duplicate of the above dummy component which means that it now has all of the same component properties of the original. The sync function then copies all necessary linkages from the original object. To edit this item, simply call MMExecute('l ib.editItem()') (Listing 7). is a re-write of the fire function from (Listing 2), including everything talked about up until this point. The next step is customizing the settings for the parameters. A parameter array in JSFL is both zero indexed and associative. If the label for the first parameter is list, then doc.selection[0].parameters[0] will be the equivalent of doc.selection[0].param eters[“list”]. Changing the value of one will mean changing the value of the other. It is also important to note that whatever the type of data the parameter is expecting, a member of the parameter array will always be a parameter – doc.selection[0].par ameters[“(some parameter name)”] is a parameter object if it is expecting a Font, a String, or an Array. Setting a parameter's value is simple if it is a simple data type (String, Boolean, Number,

Color, Class, etc):

doc.selection[0].parame

(or true, 7, etc.). But it does get a little more complicated with Lists and Arrays. To set a parameter to reference a particular instance in a list, instead of setting the value (the value, in this case, is an array of list items) the listIndex needs to be set (doc.selection[0].parameters[“lis t”].listIndex = 3). Setting the listIndex to 3 means that the parameter is now set to the same object that is found in parameters[“lis t”].value[3]; Arrays are even more complicated. To add an item to an array parameter, the function insertItem must be called, eg: do ters[“string”].value = “bar”

c.selection[0].parameters[“foo”].inse

“myName”, “myValue”, String). Removing an item is generally just as simple removeItem. Normally, removeItem simply takes the index of an object in its array as a parameter, but there is one exception. For some reason, removeItem(0) does not function consistently, if it functions at all, but there is a workaround. If the first item in an Array parameter needs to be removed an option needs to be inserted before the first item and then removeItem(1) can be used. See (Listing 8.) That should take care of the majority of the more complicated and obscure aspects of Flash's JavaScript API. Obviously, this article is far from exhaustive, but using the above can save hours of work and potential dead ends. For one final time saver, (Listing 9) is an example of an extension made in Flex which will duplicate a library component, add text to it, add it to the document, and then set the parameter based on an Array. rtItem(1,

Summary The aim of this article is to provide a good starting point for future Flash Panel projects. It begins with advise about how to create a good testing environment. It then goes through several hacks to get around weaknesses in JSFL – including instructions on the automated production of components. It includes a Flex demonstration of all of these techniques.

On the 'Net • • • • •

50

XML and JavaScript with AS3L http://www.actionscript.org/resources/articles/745/4/JavaScriptand-VBScript-Injection-in-ActionScript-3/Page4.html An introduction to JSFL http://www.devx.com/webdev/Article/20821 A quick reference for JSFL http://dynamicflash.com/jsfl/#Document The next pages have other, incredibly useful JSFL hacks: http://www.mediasparkles.com/ 2004_02_01_archives.html#107724281417051885 http://moock.org/blog/archives/000058.html

CHRISTOPHER W. ALLENPOOLE Christopher W. Allen-Poole is a developer who works at a Marketing firm out of Parsippany, New Jersey. His work predominantly focuses on converting proprietary AS2-based technology into AS3 as well as maintenance and expansion of both sets of code. christopherw@allen-poole.com

02/2009 (4)



ActionScript Developement

SWX: The Native Data Format for Adobe Flash by R. Jon MacDonald In this article you will learn how to move data between your server-side code and Flash using SWX (SWF bytecode), the most native data format for Adobe Flash. What you will learn...

What you should know...

• What SWX is • How SWX works • Why you should use SWX

• Familiarity with ActionScript 3 • Basic knowledge of PHP

Level of difficulty

S

WX is the native data format for Adobe Flash. Data is stored as SWF bytecode, the most native possible format on the Flash Platform, which is interpreted by the Flash Player. The SWX format is a subset of the SWF format, just like JSON is a subset of JavaScript. For Flash or Flex developers using ActionScript 3, SWX provides you with custom events that are dispatched when your data is received, and the data is available for use immediately. For Flash or Flash Lite developers using ActionScript 2, this means you can use Flash’s loadMovie() method to load SWX data files and that data is ready to use the moment it has loaded. For both versions of SWX there is no need to deserialize or massage the data in any way before using it, as it is stored in native Flash objects such as a String, Number, or generic Object.

The SWX Philosophy: Systemwide Simplicity A system is only as simple as its most complicated part. It's not enough to just simplify individual components and processes; you must also simplify the relationships and interactions between components and subprocesses. Systemwide Simplicity takes a 52

wider approach to simplicity that involves understanding and supporting the entire user experience. It is thus SWX’s aim to make it as easy as humanly possible for Flash developers to start creating data-driven Flash applications from the moment they arrive on the SWX homepage to the moment they first get data into Flash using SWX RPC (Remote Procedure Call). In short, SWX is designed to provide Flash developers with a simple and enjoyable experience when building data-driven applications in Flash.

A Common Vocabulary Let’s define a common vocabulary for use throughout the rest of this article. Term – Definition • SWX – Native data format for Flash. It is a subset of the SWF format. SWX SWFs are regular SWF files that are used to store only data. • SWX RPC – Remote Procedure Call (RPC) protocol encoded in SWX format. The SWX RPC allows you to call methods on server-side classes and get the results returned in SWX format. • SWX PHP – SWX RPC implementation in PHP. SWX PHP is the most common implementation of SWX RPC but there are other implementations in various stages of development by the SWX community (Python, Ruby, J2EE, .Net,

etc.). For the purposes of this article, all examples will be shown and discussed using SWX PHP. SWX Tools – The SWX Service Explorer and SWX Data Analyzer. These tools come bundled with SWX PHP and allow developers to test their server-side classes and debug their remoting calls. SWX AS – A high-level ActionScript library for both ActionScript 2 and ActionScript 3 that handles the clientside queuing and execution of SWX RPC calls. The library provides developers with useful functionality such as cross-domain access, queuing of data calls, and more. SWX APIs – APIs for Flickr, Twitter, etc. The SWX APIs are as important as the SWX data format and the SWX RPC, as they provide Flash developers with a very easy way to create mashups. Using the Public SWX RPC gateway at swxformat.org, developers can use these APIs with ActionScript alone (no serverside programming is necessary). Public SWX RPC Gateway – Open SWX RPC endpoint. The Public SWX RPC Gateway is available for use at http: //swxformat.org/php/swx.php, and all of the available services can be viewed at the SWX Service Explorer (http:// swxformat.org/php/explorer/). You can use the public SWX APIs from this gateway in your own applications without having to write any server-side code whatsoever.

Supported Platforms and Technologies Developers can make the server-side call to create, and the ActionScript call to retrieve data from, SWX SWF files with any version of Flash, as they are simply SWF files. SWX PHP, the most popular current SWX RPC implementation, creates SWX files that 02/2009 (4)


SWX

are compatible with Flash Player 6+, and Flash Lite 2.0/2.1/3.0 – depending on the SWX ActionScript library chosen (AS2 or AS3). SWX AS2, the SWX ActionScript 2 library, compiles on Flash 6+ and using MTASC. SWX AS3, the SWX ActionScript 3 library requires Flash CS3+ or Flex 2+ to compile. Currently, you can use SWX to create applications that run on mobile phones (Flash Lite 2.0/2.1/3.0), the Nintendo Wii, Sony PS3, and devices such as the Nokia Internet tablets and the Chumby. You can also create SWX-based applications for the desktop using AWX AS3 and Adobe AIR.

What's new with SWX v2 The major feature update in version 2 of SWX is AS3 support. In addition, version 2 introduces a new and simpler way to work with data in Flash so that you can write less code. Version 2 provides full backwards compatibility, so your older AS2 projects will continue to work normally with your SWX RPC or the public gateway. AS2 and AS3 support are provided seamlessly. In fact, the same ActionScript code can be used on both AS2 and AS3 projects with only minor modifications.

How to get SWX up and running Step 1 Download the latest SWX release from the project’s Google Code page at: http://code.google.com/p/swx-format/ downloads/list Step 2 Install the SWX gateway – Deploy the Server/ SWXPHP/2.00 folder to your server. As of the beta 1 release PHP 5 is required, but PHP 4 is planned for future beta releases and the final release of version 2. Access the gateway you just installed using your browser and SWX will test itself. You may also use the free public gateway at http:// www.swxformat.org/php/. Step 3 Start coding. The new SWX ActionScript API can be found under Library/v2. For AS3 support, copy the org folder from Library/v2/ AS3 next to your Flash document. For AS2 support, copy the org folder from Library/v2/ AS2 next to your Flash document.

How to use the ActionScript API The SWX ActionScript library allows your Flash application to communicate with the SWX gateway. The AS3 API was written to be as close to the AS2 API as possible. There are two ways to exchange data with the server: using a Simple Call or a Custom Call. While the Simple Call is easy for beginners and 02/2009 (4)

for simple usage, the Custom Call allows more flexibility.

Making a Simple Call Simple Call is a method of interacting with the SWX RPC that uses all of the SWX default settings. Of course you can change any of these default settings if you would like, but only the gateway is required. When using Simple Call, the only event that can be defined is the resultHandler. This is the function to be called when your data

is returned. You can also choose to activate debug mode which allows you to use the Data Analyzer to debug your service classes. Let’s take a look at how to make a Simple Call. Step 1 Copy the SWX AS classes, located in the org folder next to your FLA, and then import the SWX API so you can use the classes: import org.swxformat.*;

Listing 1. Making a Simple Call var swx:SWX = new SWX(); swx.gateway = "http://www.swxformat.org/php/swx.php"; swx.encoding = "POST"; swx.debug = true; swx.timeout = 10;

var callParameters:Object = {

serviceClass: "Simple", method: "addNumbers", debug:true,

}

args: [1,4]

Listing 2. Making a Custom Call import org.swxformat.*; var swx:SWX = new SWX();

swx.gateway = "http://www.swxformat.org/php/swx.php"; // Default SWX options and handlers (optional) swx.encoding = "POST"; swx.timeout = 30;

swx.debug = false; swx.resultHandler = resultHandler;

swx.progressHandler = progressHandler; swx.timeoutHandler = timeoutHandler; swx.faultHandler = faultHandler;

Listing 3. Event Handlers function resultHandler(e:Object) : void { }

trace("The result is: " + e.result);

function progressHandler(e:Object) : void { }

trace("Loading: " + e.bytesLoaded + " of " + e.bytesTotal);

function timeoutHandler(e:Object) : void { }

trace("ERROR: operation timed out");

function faultHandler(e:Object) : void { }

trace("ERROR: " + e.fault.message);

53


ActionScript Developement

import mx.utils.Delegate;

On the 'Net • •

swx.Simple.addNumbers([1,4], Delegate.create

http://www.swxformat.org http://code.google.com/p/swx-format/

(this, resultHandler));

You can also define a default result handler property, and then omit it from the Simple Call:

swx.call(callDetails);

Step 2 Create a SWX instance and configure it to point to your server gateway, or the public gateway (as shown here):

swx.resultHandler = Delegate.create(this,

If everything is setup correctly the call to addNumbers(1,4) should show the following in your trace log:

swx.Simple.addNumbers([1,4]);

The result is: 5

Making a Custom Call

var swx:SWX = new SWX();

For more control over SWX you may wish to use a Custom Call. With a Custom Call you define all available SWX options with each call to your SWX RPC. For instance, you can define the number of seconds until the call timeout, as well as fault, progress, timeout and result handlers for your call. This allows you to create several SWX calls, each with their own settings.

Debugging with the Data Analyzer

swx.gateway = "http://www.swxformat.org/ php/swx.php";

Step 3 Create the result handler function, which will be called when your data is returned from the server: function resultHandler(e:Object) : void {

trace("The result is: " + e.result);

}

Step 4 Make the call (the addNumbers service is shown here): // Usage:

// swx.serviceClass.method(args:Array, // [resultHandler:Function], // [debug:Boolean]);

swx.Simple.addNumbers([1,4],

resultHandler);,

Important Notes When using the AS2 version of the SWX ActionScript API, if you want a this reference on your handlers you must use Delegate.

resultHandler));

Step 1 Copy the SWX AS classes, located in the org folder next to your FLA, and then import the SWX API so you can use the classes: import org.swxformat.*;

Step 2 Create a SWX instance and configure it to point to your server gateway, or the public gateway (as shown here), and define all of the properties you’d like to customize (see Listing 2). Step 3 Create your result, progress, timeout and fault handler functions (see Listing 3). Step 4 Prepare your request parameters object (the addNumbers service is shown in Listing 4).

Listing 4. Prepare SWX call {

// Required Parameters serviceClass: "Simple", method: "addNumbers", args: [10, 15],

// Optional parameters can be defined if you would like to override the default // settings defined on the SWX object created earlier gateway: "http://www.swxformat.org/php/swx.php", encoding: "POST", timeout: 5,

resultHandler: resultHandler,

progressHandler: progressHandler, timeoutHandler: timeoutHandler, faultHandler: faultHandler, debug: true }

swx.call(callDetails);

54

Step 5 Make the call:

To debug your SWX calls you can use the SWX Analyzer (located in /php/analyzer in your SWX server deployment directory or at http:// www.swxformat.org/php/analyzer for the public gateway). To enable debugging in your requests you must set the debug property to true. This can be done either on the SWX object or in the SWX call parameters.

Summary Now that you possess all of the knowledge you need to build your own SWX applications for web and mobile, be sure to check out the SWX Showcase. Because of the ability SWX provides to deploy to such a wide range of devices, the applications developers are creating with SWX vary greatly as well, so there is always something interesting and new. Visit http:// swxformat.org/showcase/ to view a collection of projects completed with SWX. More information about SWX can be found on the project’s Google Code repository http: //code.google.com/p/swx-format or the project’s blog http://www.swxformat.org. A great source of information is the SWX Mailing List on Google Groups. Developers can subscribe to this mailing list by visiting either the Google Code page or the project blog. The list is fairly active, and the members usually return answers to posted questions within a matter of hours. You can also browse the SWX Mailing List Archives for answers to previously asked questions.

R. JON MACDONALD A certified Adobe Flash and Web developer, Jon offers a wealth of expertise in development, design, usability and visual communication. Over the course of ten years Jon has honed his skills through a multitude of experiences. Jon works with household brands, advertising agencies and talented designers and developers across the country through JonnyMac Interactive, the interactive collective he started. Jon is an avid contributor to open source Flash Platform projects including SWX and SWFAddress, and was a contributing author to the recently released book „The Essential Guide to Open Source Flash Development”. http://www.jonnymac.com.

02/2009 (4)



ActionScript Developement

An introduction to Flickr In Flash by Jassa Amir-Lang Flickr is arguably the most used photo-sharing platform on the web today. In this tutorial we will use Flash and the Flickr API to access a Flickr account, and view it’s public photos. What you will learn...

What you should know...

• The basic steps needed to get started with the AS3 Flickr Library; • Using a custom class;

• General knowledge of Flash; • A general knowledge of AS3; • An understanding of how the Document Class works;

Setting up the FLA Level of difficulty

B

ecause Flickr already handles things like multiple image resizing, the ability to send photos straight from your cell phone to your account, and unlimited storage on their servers (pro account), it makes sense to leverage these technologies to create anything from a personal portfolio/album to a full-blown RIA.

Getting Started The first thing you will need to get started is a Flickr account. If you don’t already have one head over to flickr.com and sign up for a free account. Once you’ve done that, upload a few photos to your account. For this example we will only be pulling in public photos so make sure you set the photos you have uploaded to be publicly viewable. Next you’ll need to obtain an API key. Go to the Explore tab in Flickr, and then click Apply for a new API Key. For this example, just go with the noncommercial option, fill out the details and submit your application. Once your key is issued, jot it down. Now we need to grab the as3flickrlib class files. To do this, download the latest flickr library ZIP file from http://code.google.com/p/ as3flickrlib/ and extract it. 56

With that out the way we can jump over to Flash and get started on accessing your Flickr photos. Create a new Flash Document (actionscript 3), set the document size to 800x600, set the frame rate to 30fps and save it somewhere. Next we need to create the Document Class file. Create a new Actionscript file, name it FlickrInFlash.as and save it in the same location that you saved your FLA. Back in your FLA, link the actionscript file to the Flash Document

by setting the document class definition field in the properties panel to FlickrInFlash. You can make sure that it is linking up ok by clicking the little pencil to the right of the field. Finally, load up the Publish Settings of your FLA, go to the Flash tab, and next to the Actionscript Version dropbox, click the Settings button. Add the path to the folder where you unzipped the AS3 Flickr Library files. Now we’re ready to start coding.

Initial Setup To get started, jump over to your Actionscipt file and create your FlickrInFlash class that extends the Sprite class. see (Listing 1).

Classes Now we'll start importing some additional classes. First we'll import some flash classes.

Listing 1. Your Initial Function package { import flash.display.Sprite;

public class FlickrInFlash extends Sprite{ public function FlickrInFlash():void{

}

}

}

Listing 2. Importing the Flash classes import flash.display.Sprite; import flash.display.Loader; import flash.net.URLRequest;

import flash.system.Security;

02/2009 (4)


Listing 3. Importing the Flickr classes import com.adobe.webapis.flickr.*;

import com.adobe.webapis.flickr.events.*;

Listing 4. Setting up the constants and variables private const FLICKR_URL:String = "http://www.flickr.com";

private const CROSSDOMAIN_URL:String = "http://api.flickr.com/crossdomain.xml"; private const API:String = "PASTE YOUR FLICKR API KEY HERE"; private var _fs:FlickrService;

private var _pArray:Array = new Array(); private var _user:String;

private var _imgHolder:Sprite = new Sprite();

Listing 5. Connecting to flickr public function FlickrInFlash():void{ Security.allowDomain(FLICKR_URL);

Security.loadPolicyFile(CROSSDOMAIN_URL); _fs = new FlickrService(API);

_fs.people.findByUsername("YOUR FLICKR USERNAME");

_fs.addEventListener(FlickrResultEvent.PEOPLE_FIND_BY_USERNAME, getUser); _imgHolder.x = 250;

addChild(_imgHolder); }

Listing 6. Setting the NSID private function getUser(e:FlickrResultEvent):void{ _user = e.data.user.nsid; }

getPhotos();

Listing 7. Accessing the photos private function getPhotos():void{ _fs.people.getPublicPhotos(_user);

_fs.addEventListener(FlickrResultEvent.PEOPLE_GET_PUBLIC_PHOTOS, showPhotos); }

Listing 8. Creating the Thumbnail class package{

import flash.display.Sprite; import flash.display.Loader;

import flash.events.MouseEvent; import flash.net.URLRequest;

public class Thumbnail extends Sprite{ public var src:String;

public var title:String; private var _loader:Loader = new Loader(); public function Thumbnail(imgSource:String, imgTitle:Title):void{

}

}

02/2009 (4)


ActionScript Developement For this example you'll need the classes found in (Listing 2). You can insert these just after the Sprite class import. Next we'll import the Flickr AS3 Library classes that we’ll be using see (Listing 3).

this.addEventListener(MouseEvent.ROLL_OVER, handleOver);

function and start interacting with Flickr. The first thing you need to do is allow your server and Flickr to communicate with one another. To do this we simply allow the Flickr URL domain, and load the policy file that exists on Flickr’s servers. Next we create the FlickrService instance by passing it our API key. Once that has been created we need to find out what our NSID is. We’ll use this later to access our photos. To do this we use the FindByUsername method, pass it our API Key and add an event listener to deal with it, see (Listing 5). Next we need to create a function to handle the event listener created in (Listing 5). This will set the _user variable to your NSID. We need this to access the user’s public photos. see (Listing 6). Once we have it we can call the getPhotos function, which we will create next. Finally, we position the _imgHolder Sprite and add it to the display list.

this.buttonMode = true;

Accessing the Photos

Constants and Variables There are a few constants and variables that we need to set up for this example. You can see how I’ve set these up in (Listing 4). The FLICKR_URL and CROSSDOMAIN_URL constants are used to allow Flickr and your web server to communicate, and the API constant is where you paste the API you were issued from Flickr.

The _fs variable will be used to create the FlickrService instance, the _pArray will be used to store our photos once we have accessed them, and the _user variable will be used to store the NSID of the username who’s public photos you wish to access. The final variable is a Sprite that will be used to hold a larger version of the thumbnails we create when they are clicked on. These constants and variables should be declared between the public class and public function lines.

Connecting to Flickr Once we have set up our constants and variables, we can jump into our main

Listing 9. Finishing the Thumbnail class public function Thumbnail(imgSource:String, imgTitle:String):void{ this.addEventListener(MouseEvent.ROLL_OUT, handleOut); src = imgSource;

title = imgTitle;

_loader.load(new URLRequest(src + "_s.jpg")); }

addChild(_loader);

private function handleOver(e:MouseEvent):void{ }

e.target.alpha = 0.5;

private function handleOut(e:MouseEvent):void{ }

e.target.alpha = 1;

Listing 10. Finishing the Thumbnail class private function showPhotos(e:FlickrResultEvent):void{ _pArray = e.data.photos.photos as Array;

for(var i:uint = 0; i < _pArray.length; i ++){ var p:Photo = _pArray[i];

var src:String = "http://static.flickr.com/" + p.server + "/" + p.id + "_" + p.secret;

var t:Thumbnail = new Thumbnail(src, p.title); t.x = 1 + (i % 3) * 76;

t.y = 1 + (Math.floor(i / 3) ) * 76;

t.addEventListener(MouseEvent.CLICK, launchPhoto);

}

}

addChild(t);

Listing 11. Launching the larger image private function launchPhoto(e:MouseEvent):void{

while(_imgHolder.numChildren) _imgHolder.removeChildAt(0); var t:Thumbnail = e.currentTarget as Thumbnail; var l:Loader = new Loader();

l.load(new URLRequest(t.src + ".jpg")); }

58

_imgHolder.addChild(l);

Now we have all the information we need to access the user’s photos. To do this we simply use the GetPublicPhotos method and create an event listener to handle the result, see (Listing 7).

Creating the Thumbnail class To store the thumbnail for each photo in our flickr photostream we are going to create a custom class. This class will handle loading in the url for the image, plus add some simple mouse interactivity. It will also store information about the photo so that when we want to launch a larger version of the image, we’ll have the necessary information at hand. Go ahead and create a new Actionscript file. Call it Thumbnail.as and save it in the same directory as your Document Class. Start by importing the necessary classes and creating your initial function. We’ll also add two public variables – src and title. These will be used to store the base path to the image source and title of the image respectively. Add a third variable called _loader. This will need to be data-typed to a Loader and will be used to load the image into the Thumbnail. Finally, when you create an instance of the Thumbnail class you’ll need to pass it some arguments (the image source and the image title). Set these arguments up in the main function, see (Listing 8). Jump into the main function now and add some Mouse Events to handle rollOver and rollOut interactions. You’ll also need to create the necessary functions to handle the Mouse Events. I’ve also set the buttonMode of the thumbnail to true so that the hand cursor comes up when the user interacts with the Thumbnail. Next you can assign the public variables their values. Finally, load the image source into the Loader, and add it to the 02/2009 (4)


Flickr In Flash

Listing 12. The final Document Class code package { import flash.display.*; import flash.events.*; import flash.net.*;

import flash.system.Security;

import com.adobe.webapis.flickr.*;

import com.adobe.webapis.flickr.events.*; public class FlickrInFlash extends Sprite{ private const FLICKR_URL:String = "http://www.flickr.com";

private const CROSSDOMAIN_URL:String = "http://api.flickr.com/crossdomain.xml"; private const API:String = "YOUR API KEY"; private var _fs:FlickrService;

private var _pArray:Array = new Array(); private var _user:String;

private var _imgHolder:Sprite = new Sprite(); public function FlickrInFlash():void{ Security.allowDomain(FLICKR_URL);

Security.loadPolicyFile(CROSSDOMAIN_URL); _fs = new FlickrService(API);

_fs.people.findByUsername("YOUR FLICKR USERNAME");

_fs.addEventListener(FlickrResultEvent.PEOPLE_FIND_BY_USERNAME, getUser);

}

addChild(_imgHolder);

private function getUser(e:FlickrResultEvent):void{ _user = e.data.user.nsid;

}

getPhotos();

private function getPhotos():void{

_fs.people.getPublicPhotos(_user);

}

_fs.addEventListener(FlickrResultEvent.PEOPLE_GET_PUBLIC_PHOTOS, showPhotos);

private function showPhotos(e:FlickrResultEvent):void{ _pArray = e.data.photos.photos as Array;

for(var i:uint = 0; i < _pArray.length; i ++){ var p:Photo = _pArray[i];

var src:String = "http://static.flickr.com/" + p.server + "/" + p.id + "_" + p.secret; var t:Thumbnail = new Thumbnail(src, p.title); t.x = 1 + (i % 3) * 76;

t.y = 1 + (Math.floor(i / 3) ) * 76;

t.addEventListener(MouseEvent.CLICK, launchPhoto);

}

}

addChild(t);

private function launchPhoto(e:MouseEvent):void{

while(_imgHolder.numChildren) _imgHolder.removeChildAt(0); var t:Thumbnail = e.currentTarget as Thumbnail; var l:Loader = new Loader();

l.load(new URLRequest(t.src + ".jpg"));

}

}

}

02/2009 (4)

_imgHolder.addChild(l);

59


ActionScript Developement

Listing 13. The final Thumbnail Class code package{ import flash.display.Sprite; import flash.display.Loader;

import flash.events.MouseEvent; import flash.net.URLRequest;

public class Thumbnail extends Sprite{ public var src:String;

public var title:String; private var _loader:Loader = new Loader(); public function Thumbnail(imgSource:String, imgTitle:String):void{ this.addEventListener(MouseEvent.ROLL_OVER, handleOver); this.addEventListener(MouseEvent.ROLL_OUT, handleOut); this.buttonMode = true; title = imgTitle;

_loader.load(new URLRequest(src + "_s.jpg")); }

addChild(_loader);

private function handleOver(e:MouseEvent):void{ }

e.target.alpha = 0.5;

private function handleOut(e:MouseEvent):void{

}

}

}

e.target.alpha = 1;

Display List. Note that I’ve added the _s.jpg to the imgSource. The _s indicates that we want to load the Square Thumbnail size of the image (75x75px) and the .jpg is simple the filetype that we need to add on the end, see (Listing 9).

Displaying the Photos Now that we have created the Thumbnail class we can go ahead and display our public photos. Jump over to your Document Class (FlickrInFlash.as) and create a new function to handle the GetPublicPhotos method created earlier. First we’ll create an array from the result of the getPublicPhotos method. Then we’ll loop through the array and create a Photo instance for each of the photos in the array. Using the information from the photo we’ll build up the raw source path to the image. Then we’ll create a Thumbnail instance and pass it the image source and image title. Next, position the thumbnail so that they all appear in a grid. Feel free to play around with the grid values. Finally, add an 60

eventListener to handle a Mouse Click and add the Thumbnail to the Display List, see (Listing 10).

Launching the larger image We’re almost done – all we need to do is write the function to handle the Click event. Start by removing any existing images from the _imgHolder sprite. Next create a Thumbnail from the current Mouse Event target. You’ll need to create a Loader next to load the image source into. This can be grabbed from the Thumbnail object but you’ll need to add the .jpg to the end of it. Finally, and the Loader to the _imgHolder sprite, see (Listing 11). If you test your movie now, you should see a 3-across grid of the public photos you have uploaded to your Flickr account. If you click one of the thumbnails it will load the larger image on the page. There are many things you could do with these photos now that you know how to access them. You could grab the title that we have

stored in the Thumbnail and display it with the larger photo, or you could grab whole photo sets rather than just the individual photos – it’s up to you. I strongly recommend that you read through both the Flickr API documentation at http: //www.flickr.com/services/api/ as well as the as3flickrlib documentation (that should be in the library ZIP file you downloaded). This has just been a short introduction to show you the basics of connecting to Flickr and grabbing some photos, but there is a lot more that can be done with this API so check it out, and have

JASSA AMIRLANG Jassa Amir-Lang is a freelance Flash/Flex Developer based in sunny Adelaide, South Australia. He has been playing around with all things Flash for the last 10 years and is always looking for ways to implement ideas using the Flash platform. He is an active member of the Adobe User Group in South Australia. For more information you can check out his blog at www.bangersandflash.net.

02/2009 (4)



ActionScript Developement

Flash video and AS3 by Chaim Sajnovsky To basically understand how to extract the maximum profit from flash video we need to know first the three amigos.

What you will learn..

What you should know...

Streaming, you can send also. So what about the code?

• How coding for Flash video works • Differences between Progressive/Streaming flash Video • How to use AS3 to maximum profit for flash video

• Basic notions of Flash video • Basic AS3

var myStream:NetStream = new NetStream

Level of difficulty

T

he three basic elements in flash video are: NetConnection, NetStream and the video object. Those 3 are the base. Learn how they work and you already have half of the way done. NetConnection: Well, the NetConnection is the way Action Script has to connect with a remote server. Talking about video specifically (NetConnection is used for remoting also) you can connect with a web server(HTTP protocol) or a Streaming Server(RTMP protocol). This is very important. Think the NetConnection as a connection to a server. More basically, imagine you get connected to a TV cable service. NetConnection is the cable with the company. When you work with flash video, you have two choices: Progressive download or Streaming. Progressive is, as always referred, YouTube style. Click on play, wait for the video to load, and begin to watch it. The video is sent from a web server to our flash player, over HTTP. Advantages: you just put your video on any web server, and that's it. Downside: speed. If you web server is a good one, will take a little to load the video. If your we server is a lame one.. Go drink a coffee and then back to watch 62

(myConnection);

some seconds. Besides, perfomance is affected by how many users are watching the video, etc. Normal Http issues. But, cheap to build after all. Streaming is a different thing. You connect to a streaming server, ask for the video, and voila! The video begins to play immediately. Great thing. But expensive. Back to NetConnection: We got to the code now... So for progressive download what we do is:AS3 var myConnection:NetConnection = new

NetConnection;

myConnection.connect(null);

But for streaming, we need to refer the server path and tell flash we want to receive the video through RTMP, so the second line is different: myConnection.connect("rtmp:

//mystreamingServer/myApplication")

the path to the server can be a domain or a IP. and you always need to create an app at the server side. That is it for the NetConnection. Now, the second element: NetStream. If the NetConnection is the cable, NetStream is the video signal. NetStream is the vehicle to send and receive video, audio and data. If you work with progressive, you just receive a stream. But with

This is as saying create a new NetStream that travels through myConnection. Same is for progressive or for streaming. Now the third component, the video object. If you have a cable company, and a signal, what else you need in order to see the TV? a TV set! So the video object is that, a screen to display video. To create one, drag and drop a video object from the library or create one programatically. var myVid:Video = new Video;

and the base is done. But, just that, the base only. Now you should join the parts to make a nice video-player-application. How to join them? Well, the first two are already done. We said to Flash, create a NetConnection ,connect it and then create a NetStream, it will travel through the NetConnection we made, now we connect(or attach) the video object to the NetStream in order to receive the video data. myVid.attachNetStream(myStream);

and we are done. Please remember to add your video to the stage if you create if with code: addChild(myVid)

Once we have the basics connected and done, just make play. What is the way to make play? myStream.play()

But play what? Flash needs to know what you want to play. So there is a difference if you 02/2009 (4)


want to play progressive or streaming. The diference is what you write between the () for progressive (remember, we want a play a file from a web server) myStream.play("http://www.mysite.com/ videos")

That means, if the connection is ok, you can begin to work. Else, no server, no magic. NetStream has more events, since the stream uploading or downloading has more properties. To listen to it, just add a listener in this similar way:

for streaming you say it to play a file already existing at the server:

myNs.addEventListener(NetStatusEven

myStream.play("myvideo")

function che ckMyNetStream(evt:

Now join the lines and you have your code. Once you know the three amigos, you understand the business. Now, we are set for dirty tricks...

Learn to listen Two of the three components depicted before dispatch events: NetConnection and NetStatus. NetConnection events are useful to listen how the connection goes. And this is really important if you do streaming. Basically you can see 4 main events when attempting to connect to a Server: NetConnection.Connect.Success NetConnection.Connect.Closed NetConnection.Connect.Failed

NetConnection.Connect.Rejected

so if you want to be sure ynected or not, disconour app connected or not, was accepted or rejected at the server side, just put a listener to your NetConnection in this way: myNc.addEventListener(NetStatusEven t.NET_STATUS, checkMyConnection)

function checkMyConnection(evt: NetStatusEvent) {

trace(evt.info.code)

}

And you will receive the status of the ongoing connection. Now, and this is very important, if you want to do anything with AS3 and Flash Media Server, you HAVE to listen to the connection status first. So everything you want to code related to the fms and your application, should be after that listener: function checkMyConnection(evt: NetStatusEvent){

if (evt.info.code ==

"NetConnection.Connect.Success"){

////your code here...////// } }

02/2009 (4)

t.NET_STATUS, checkMyNetStream) NetStatusEvent){

}

trace(evt.info.code)

And while playing, recording o buffering you will receive a lot of events, since NetStream is very dynamic. You can find a full list of events at: http://livedocs.adobe.com/flash/9.0/ ActionScriptLangRefV3/flash/events/ NetStatusEvent.html#info Once you understand the NetStream Events, a lot of tricks can be done. i.e., what about playing a video in a loop? Easy to do, check it:once your NetConnection, NetStream and video object are set see (Listing 1). But you can use this technique to do more things: Chaining videos(remove the ns.seek(0) and play a different file then), redirecting to a new web page once the video is over, or adding some elements instead, making the video disappear, etc. A great event info is NetStream.Play.Strea mNotFound. It says you the file you attempt to play is not present at the origin. Use this event.info to work around times when the video just is not available. But NetStream has also properties: My 2 favourite are time and bufferTime. NetStream.time says reveals the current time being played in a stream. Think it as a playhead in a video editor, or the elapsed time in a VCR. You can use it as a powerful tool: Display the elapsed time in a video player, listen to it in order to know when to trigger a event or add a element to the stage, playing a new video, etc. NetStream.time it's a great help with working with several videos in parallel. Try to trace the NetStream.time every second and you will have a nice time display... NetStream.bufferTime is the property allowing us to pre-buffer or buffer our video. Buffering is the effect of storing video in the memory to avoid sudden stops during the playing due to lack of data loaded. Think of it as a reservoir. Because we generally get our video from an Internet server, and we know Internet connections can suffer bandwidth issues, we want to make sure the person watching the video won't suffer the wait 63


ActionScript Developement please,loading the video.. effect. Then we can set the seconds to buffer, depending of several factors. One is how good, big, fast is the web server connection that host your video file. The better and faster the web server, less the buffer time. But in the second hand, if your target viewer has a poor bandwidth, you should increase your buffer. So a previous analysis is needed before setting this property. Play around with it up to getting the desired buffer level. It's important to remember that NetStream.bufferTime will store as much video seconds as we ask him and will do it when we click on play. So if your bufferTime is very long, maybe the viewers begin to ask if something is wrong with the video player if

the video begins after, I.e, 20 seconds. Keep this is mind.

Before you start, know a little more about your file... A great built in function in As3 is onMetaData. It actually lets you check the metadata information embedded on the flv file. In order to receive this information, we need to add the function into our code as shown in (Listing 2). So we can, just for beginning, trace all the properties of or meta Object see (Listing 3). And we will get this tracing see (Listing 4). If we translated this to understable english, we have this:

Listing 1. Playing a video in a loop ns.play("http://somedomain/somevideo/flv")

ns.addEventListener(NetStatusEvent.NET_STATUS, playitagain) function playitagain(event:NetStatusEvent){

if(event.info.code == "NetStream.Play.Stop"){ ns.seek(0);

ns.play("http://somedomain/somevideo/flv")//plays the same video again and will be like this up to

remove the listener...///

Listing 2. How retrieve meta data from a FLV file var netClient:Object = new Object(); ns.client = netClient;

netClient.onMetaData = function(meta:Object) {

//////meta is the object that contains all the metadata...

}

Listing 3. Looping and tracing meta data var netClient:Object = new Object();

var duration:Number = meta.duration

It's very important to wait up to the video is buffered to listen the metadata and pass the values to the variables. This can be a little tricky, since you actually need to give the order to the NetStream to play a video to begin buffering. This can be avoided if we make this little trick with just 2 lines: myNs.play(“your video file”) myNs.pause()

and then our onMetadata will be received and we can use it. When you want to play the video, just command it to : myNs.togglePause()

audiosize = 823379

and it will play as usual. The funny issue is, if you don't add a onMetadata function when working with video and AS3, flash will output an error: Error #1069: Property onMetaData not found on flash.net.NetStream and there is no default value. So this requirement sometimes can turn it to a great help when working with video. Want to learn more about metadata in flash video? A great doc for this is http: //www.adobe.com/devnet/flv/pdf/video_file_ format_spec_v9.pdf So the base for making great video with flash is using the NetConnection and NetStream properties, – events and listening to metadata. I strongly recommend to take a look on the Flash help, or at Adobe live docs.

datasize = 9691457

CHAIM SAJNOVSKY

ns.client = netClient;

netClient.onMetaData = function(meta:Object) {

//////meta is the object that contains all the metadata...

}

Listing 4. Meta data results lasttimestamp = 107.966 videosize = 8868078

metadatacreator = FlixEngineLinux_8.0.11.0 (www.on2.com) height = 768 width = 1024

videocodecid = 4

videodatarate = 641.7007148083655 framerate = 30

duration = 107.966

audiodatarate = 59.58031637274698 canSeekToEnd = 1 audiocodecid = 2

64

The video height is 768 pixels, the width is 1024, the datarate (was compressed at... kbps) is 641.7007148083655, 30 frames per second, the video duration is seconds is 107.966, the audio was compressed at 59 kbps, the file has a size of 9691457 bytes divided on 8868078 for video and 823379 for audio, videocodecid = 4 means the video was encoded with On2 VP6, audiocodecid = 2 means the audio was encoded as MP3, and canSeekToEnd=1 means that we can seek up to the end of the video if we want to. This is great to advance further. We can isolate the duration property and we have the real duration of our clip, for example to show it in a video player. Or what about knowing the width and height of our video file and reconfiguring or video object before it starts to play? Inside our function, just create the vars, and take the values from the meta object, as i.e:

Chaim Sajnovsky is a flash/flex/fms developer, working as Consultant/developer. chaim.sajnovsky@gmail.com

02/2009 (4)



Server Side Interaction

WebORB tricks by Vitaliy Morarian WebORB for Java - it is server-side technology which enables connectivity between Flex, Flash, AJAX and Silverlight clients and Java applications.

What you will learn...

What you should know...

• You will learn some non-evident issues of WebORB. How to extend processions of exceptions from server side to Flex and custom serialization.

• Familiar with developing Flex application • Familiar with developing Java web based application

• http://flexblog.faratasystems.com/?p=289

Level of difficulty

W

ebORB instantly exposes deployed Java objects as remoting services to a variety of rich client technologies. In other words WebORB it is a gateway between client and server-side.

Serialization/deserialization Serialization – it is a process of saving object state in a byte stream, deserialization – is vice versa. Those processes are used when we want to exchange data between Flex and Java. WebORB supports serialization/ deserialization of many ActionScript types. (http://www.themidnightcoders.com/ fileadmin/docs/java/guide/flex/remoting/ datatypemappings.htm). These mapping types in most cases are enough to build up an application. But in some situation custom serialization may be useful. As you know, transferring Dates from/to Flex can be painful due a timezone differences. The root of the problem is that Dates transferred in UTC (Transfer to the UTC/local time happens automatically on protocol level). As result you will have unpredictable results if the timezone on server-side is not the same as on client side. Existing solutions: • http://weblogs.macromedia.com/lin/archives/ 2008/04/tips_for_workin.cfm 66

In my opinion, these approaches are not flexible. So, a main idea is to have a transparent and flexible solution for both sides – server and client. In our example we will use Joda-Time library (http://joda-time.sourceforge.net/) for server-side. It is not a requirement. You can use also java.util.Date. But, I have to say that this library makes it easy working with dates, durations, intervals and so on. , Note: This library may be included in next version of JDK as JSR-310 (http://www.infoq.com/news/ 2007/02/jsr-310). So, to solve our problem we will combine two techniques: • Custom writer • Externalizable Custom writer is a WebORB specific handler which will be invoked when an object graph that has to be serialized, is the object with the defined type. We have to write our implementation of WebORB's specific interface weborb.writer.ITypeWriter and register it in weborb-config.xml. public interface ItypeWriter { void write(Object obj,

IProtocolFormatter

iProtocolFormatter) throws IOException;

}

boolean isReferenceableType();

Here exists a hidden power – our Java method may return some specific objects, which can be serialized in a different way. Editor's note – what goes here where the question marks are? Missing text. We now know how to send specific objects to the Flex side but, for our case we also have to implement backward serialization – objects from Flex need to be transformed in Java objects. This can be done with other WebORB specific interface public interface IExternalizable {

Object readExternal(DataInputStream

dataInputStream, ParseContext

}

parseContext);

Implementation is simple enough. MessageWriter is a utility class which contains all writers and helper method for object serialization, see (Listing 1). Registration of our writer in weborbconfig.xml, see (Listing 2). Java exception is an object which describes a fault situation that appears in some part of the Java code. When such exception occurs on a server we can deliver this exception to Flex for further procession. WebORB for Java by default converts exception to string and dispatches the string with the fault event in the Flex remote object. This behavior has sense because in most cases on client side we do not need such detailed information that is included in the exception. On screen shot you can see the results of the invocation Generate Division By Zero from Flex Examples -> Remoting (AMF3) -> Server-side exception handling. Some one may say that it is a bug, but I can treat it as a feature. In most cases you just need to know about failure, but do not need to know what exactly happened. 02/2009 (4)


WebORB tricks

So, from this point of view, response of the remote invocation is not overloaded with garbage data. In some cases we may need to deliver data that can be processed by the client side. For instance a user form on a web page. The business logic on server-side needs to operate with data from database and it is impossible to make such check on client side. To clear an example let say that data entered on the form had an order and the server-side has to perform certain operations to determine if the item is in the inventory or if an exception needs to be issued. For sophisticated software we have to display a useful message to end user. From this point of view we can make custom exception which will hold all desirable data:

which exceptions the client may receive. You can remove this additional check, or make it more extendable by writing an exception translator. Listing 1. LocalTimeWriter class

public class LocalTimeWriter implements ITypeWriter { public LocalTimeWriter() { } public boolean isReferenceableType() { }

• • •

weborb.handler.JavaObjectHandler,

weborb.handler.EjbHandler.

weborb.handler.SpringBeanHandler,

weborb.handler.webservices.AxisWebS erviceHandler,

What we are going to do is to make own handler based on JavaObjectHandler, see (Listing 4). So, we delegate invocation to WebORB (Invocation.invoke), but change the behavior of result procession. In case the method throws an exception, it will be caught in Invocation.invoke and wrapped into ServiceException with public field clientSid eExceptionCause. I also added an additional check if the original exception is an instance of JeniveException. Logic is very simple here – I want to propagate to client only exceptions which are inherited from application specific. I find it useful because it gives me control 02/2009 (4)

return false;

public void write(Object obj, IProtocolFormatter formatter) throws IOException {

Log.log(ILoggingConstants.SERIALIZATION, "serializing LocalTimeWrapper " + obj);

• Useful message, • Target object, • Field name. Procession of exceptions which may be produced by the server-side relies on business logic and application design. So, how to handle a Java Exception in Flex with WebORB? A fault event occurs in the event of an exception during the invocation of a remote method. The fault event handler is provided with the FaultEvent object. This FaultEvent object has a property named message of type mx.messaging.messages.ErrorM essage. Let’s add some magic to WebORB because it has all the power to send an Exception. What we are going to do is write own invocation handler. This is a special glue between WebORB and your application which -isresponsible for mapping between services and methods which will be invoked. Invocation handler is an interface, see (Listing 3). And it has next implementations:

With this magic WebORB will work in the same way as BlazeDS – in rootCause of Message property will be set an Exception, see (Listing 5).

LocalTime time = (LocalTime) obj;

MessageWriter.writeObject(new LocalTimeWrapper(time.toString("HH:mm:ss")), formatter);

}

}

Listing 2. WebORB configuration <customWriters>

<customWriter>

<className>org.joda.time.LocalTime</className>

<writerClassName>com.uwiss.jenive.weborb.writer.LocalTimeWriter

</customWriter>

</writerClassName>

</customWriters>

Exception handling

Listing 3. Invocation handler interface public interface IInvocationHandler {

weborb.util.Value invoke(String serviceName, String methodName, Object[] args) throws Exception;

String getName()

Listing 4. JavaObjectHandler Object obj = Invocation.invoke(objectMethodPair.serviceObject, objectMethodPair.method, args);

if (obj instanceof ServiceException) { if (Log.isLogging(DEBUG))

Log.log(DEBUG, (new StringBuilder()).append("Exception was produced ").append (getName()).toString());

final Throwable throwable = ((ServiceException) obj).clientSideExceptionCause; if (throwable instanceof JeniveException) { }

throwable.setStackTrace(new StackTraceElement[0]); return new Value(throwable);

} else { }

return new Value(obj);

67


Server Side Interaction

Listing 5. Sending Exception with rootCause of Message property

Builder()).append("Exception during

processing method invocation in ").appen

public Value invokeWithExceptionHandling(String serviceName,

d(getName()).append(": ").append(error).

String methodName, Object[] args) {

toString());

if (Log.isLogging(INFO))

-

Log.log(INFO, (new StringBuilder()).append("Processing

method invocation in ").append(getName())

return new Value(new ServiceException(error, throwable));

-

}

.toString());

catch (UnAdaptableTypeException unadaptabletypeexception)

try {

{

ObjectMethodPair objectMethodPair = getObjectAndMethod

if (Log.isLogging(ILoggingConstants.EXCEPTION))

(serviceName, methodName, args);

Object obj = Invocation.invoke(objectMethodPair.servic

Log.log(ILoggingConstants.EXCEPTION, (new Strin

eObject, objectMethodPair.method, args);

gBuilder()).append("Exception during

if (obj instanceof ServiceException) {

processing method invocation in ").appen

if (Log.isLogging(DEBUG))

d(getName()).append(": ").append(error).

Log.log(DEBUG, (new StringBuilder()).append("Excep

toString());

return new Value(new ServiceException(error, unadapta

tion was produced ").append(getName()).to String());

}

if (throwable instanceof JeniveException) {

catch (Exception exception) {

obj).clientSideExceptionCause;

throwable.setStackTrace(new

}

String error = exception.toString();

StackTraceElement[0]);

if (error == null || error.length() == 0)

return new Value(throwable);

error = (new StringBuilder()).append("unable to

} else {

}

}

locate service object with class name

return new Value(obj);

").append(serviceName).toString();

if (Log.isLogging(ILoggingConstants.EXCEPTION))

Log.log(ILoggingConstants.EXCEPTION, (new Strin

catch (NoSuchMethodException nosuchmethodexception) {

gBuilder()).append("Exception during

String error = (new StringBuilder()).append("unable to

processing method invocation in ").appen

find method in class. method name ").append

d(getName()).append(": ").append(error).

(methodName).toString();

toString());

if (Log.isLogging(ILoggingConstants.EXCEPTION))

Log.log(ILoggingConstants.EXCEPTION, (new Stri

ngBuilder()).append("Exception during

processing method invocation in ").append

}

(getName()).append(": ").append(error).to String());

return new Value(new ServiceException(error, }

nosuchmethodexception));

catch (IllegalAccessException illegalaccessexception) { String error = "unable to invoke method due to

if (Log.isLogging(ILoggingConstants.EXCEPTION))

Log.log(ILoggingConstants.EXCEPTION, (new StringBuild er()).append("Exception during processing

method invocation in ").append(getName()). append(": ").append(error).toString());

return new Value(new ServiceException(error, illegalacce ssexception));

catch (InvocationTargetException invocationtargetexception)

}

return new Value(new ServiceException(exception));

Listing 6. IAuthenticationHandler and IAuthorizationHandler interfaces public interface IAuthenticationHandler

{

void checkCredentials(String userId, String password,

weborb.message.Message message) throws

insufficient access permissions";

}

bletypeexception));

final Throwable throwable = ((ServiceException)

weborb.security.WebORBAuthenticationEx }

ception;

public interface IAuthorizationHandler

{

boolean authorizeAccess(String serviceName, weborb.security

}

.ORBSecurity orbSecurity);

-

{

Listing 7. Client side authentication (ActionScript code)

tException();

var ro:RemoteObject = new RemoteObject( "TestService" );

Throwable throwable = invocationtargetexception.getTarge String error = "exception during method invocation"; if (Log.isLogging(ILoggingConstants.EXCEPTION))

ro.setCredentials( "login", "pwd" );

Log.log(ILoggingConstants.EXCEPTION, (new String

68

02/2009 (4)


Security WebORB provides a flexible mechanism for restricting access to server-side resources (remote classes and their methods). Access to specific classes can be restricted using WebORB configuration file (weborb-config.xml). An authentication request WebORB delegates a request to the pre-configured authentication handler to check the user credentials. If the credentials are valid the user's information is stored in the session. All secured service invocations will be checked by a pre-configured authorization handler. The handler checks if the logged on user is authorized to access the service. If the check passes, the invocation proceeds, otherwise exception occurs (WebORBAuthent icationException). All magic is around two handlers: • Authentication handler is responsible for authenticating user credentials. • Authorization handler is responsible for making a decision should be requested resources allowed or denied. Good news is that both handlers are defined as interfaces. It gives the developer the freedom to make their own implementation based on business logic, see (Listing 6,7). In the WebORB professional edition it is also possible to organize security restriction by host, IP range or role name. More information can be found here: http://www.themidnightc oders.com/fileadmin/docs/java/guide/security/ accessconstraints.htm

Conclusion The article explores some of the hidden, yet powerful features of WebORB - a technology enabling integration between Flex/Flash clients and Java applications. WebORB has many unique features which make it a superior product in comparison to Adobe’s BlazeDS or GraniteDS. Management console, code generators, graphical service browser, Spring and JMS integration as well as variety of examples and a user guide made it a clear choice for me and many other developers. Finally, the Midnight Coders, developers of WebORB are advancing their RIA Platform with many more tools and product for the RIA development. This includes RIA AppPuncher - a client/server debugging and testing system, PDF Generator for Flex/Flash clients and Java applications and soon to be released RIA Analytics platform.

VITALIY MORARIAN My name is Vitaliy Morarian. I'm a System Architect in Ukrainian office of Dutch company U-wiss. I have been involved in IT industry for 6 years and have taking part in different kinds of projects. For the time being I'm responsible for integration of RIA (WebORB + Flex) in projects of our company.

02/2009 (4)

69


Server Side Interaction

Multi-user Applications in haXe by Lee McColl Sylvester With the ever expanding broadband connections and the increase in popularity of massively multiplayer online games, e-learning applications and social websites, multi-user applications development is becoming more and more of a necessity for Flash programmers. What you will learn...

What you should know...

• How to use the haXe ThreadRemotingServer class to build a multi-user server application • How to connect to a multi-user server in Flash • How to pass object instances from Flash to the server and the server to Flash

• ActionScript at a competent level • An understanding of networked applications

Level of difficulty

perform. Much of the restrictions in our example will exist with the server machine hosting the Neko layer and will include factors such as how many processors the machine uses, its available memory and the amount of bandwidth available between the

server and its clients. This is true regardless of which platform you choose, though as a rule, you can expect a well executed application using the Neko virtual machine to perform better than equivalent applications running on Python or Ruby. Given a capable server, one could comfortably expect as many as five hundred to five thousand users connected simultaneously and could anticipate much more using chained servers or servers of a very high specification.

haXe Socket Server Principles There are three levels to which you can build a socket server in haXe. The first route

T

����������

����������

����������������

������ ���������

������ ���������

70

������

����������������

his article takes a look at how you can easily develop a powerful multi-user server and Flash client using the haXe language. Developing interactive applications is great fun, but developing applications that can be interacted with by multiple people at once is a whole lot better. With haXe, you are given the flexibility to be able to develop such applications using Neko, C++ or PHP as the server, and Flash, Neko or C++ as the client, with barely a difference in how they are coded. This allows for a much greater amount of flexibility and will ensure that your application fits your deployment environment. This article will focus on building a multiuser server using the Neko platform and connecting to that server using instances of a Flash 9 client. As the focus of many multi-user Flash applications is that of gaming, we will orient our server and client with the premise that it can be extended to facilitate such applications so that one can use it as a starting point for their own game. When developing any networked application it helps to be able to identify the bottlenecks which may affect how your application might

������

Figure 1. Client/Server Interface

02/2009 (4)


Multi-user Applications in haXe

entails working with raw sockets within your own custom framework, which will rely on an intimate knowledge of networked programming and data transfer. If you are competent enough to perform this feat, then you will likely be able to scan this article and head straight for the haXe API reference at www.haxe.org. The next level of server development requires using the ThreadServer class, which provides the handling of threaded sockets. Essentially, ThreadServer allows haXe developers to build multithreaded applications that can attach a customisable number of sockets to each thread. Out of the box, the ThreadServer is configured to apply up to sixty-four sockets to each thread, though you can raise or lower this value as desired. If one considers that an average Windows machine can handle around one thousand or so threads, this can lead to a staggeringly large number of simultaneously connected users. ThreadServer makes development of extensible socket servers an absolute doddle. The third and highest level of socket server development in haXe requires using the ThreadRemotingServer, which I will be demonstrating in this article. ThreadRemotingServer is a class that extends the ThreadServer functionality, but adds the haXe serialise and un-serialise functionality, so that developers can, in effect, send instances of objects from one layer to the other. It is this functionality that makes the development of multi-user servers in haXe so easy, and why many developers choose to use the haXe language for such applications. It is important to note at this time that, as the PHP and C++ output in haXe is still relatively new, users wishing to use these platforms will need to use raw sockets until the ThreadServer and ThreadRemotingServer classes for these platforms become available.

Listing 1. The server base class import neko.net.ThreadRemotingServer;

import haxe.remoting.SocketConnection; import haxe.remoting.Context;

class NekoServer extends ThreadRemotingServer {

public static var users = new List< UserServer >(); public static var count : Int = 0; public static function main() {

var server = new NekoServer();

neko.Lib.println( "Executing NekoServer..." );

}

server.run( "localhost", 4040 );

override function initClientApi( cnx : SocketConnection, server : Context ) { neko.Lib.println( "adding user" );

var user = new UserServer( cnx, ++count ); server.addObject( "UserServer", user ); users.add( user ); }

( cast cnx ).__user = user;

override function clientDisconnected( c : SocketConnection ) {

neko.Lib.println( "client disconnected : id = " + ( cast c ).__user.id ); var user : UserServer = ( cast c ).__user; users.remove( user ); for ( u in users )

if ( u.id != user.id ) }

u.removeUser( user.id );

Understanding Server to Client Communication Unlike most client/server applications, haXe's built applications use the same language. This is a boon for you as it means both the server and client can agree on an interface for communication. This is how ThreadRemotingServer works. Once your server is running and a socket connection is available for clients to connect to, it will already have been given one or more interfaces with signatures of functions that clients will have to expose for communication. Likewise, any client wishing to connect to the server will also have been given one or more interfaces detailing functions that the server can provide. Such interfaces will need to be written only once, yet both the client and server classes will utilize them. Figure 1, shows how this might look graphically. 02/2009 (4)

Figure 2. How the application should look

71


Server Side Interaction How this will work is that the server and client will both supply one or more Application Programming Interface (API) classes which will suffice as the methods that the other application will invoke. Each API will implement an interface describing the exposed methods. Then, the other application will be given an instance of the haXe AsyncProxy class, which is passed this interface as a type. This way, the calling application, whether it is the client or server, will know exactly how the methods are formed at compile time and will thus ensure that all remote methods are called correctly and know what return values to expect.

Getting Started – The Server Class In every socket application, you need a class that will either create an instance of the ThreadRemotingServer or extend it. Some applications do a lot more than simply run a sockets connection loop, such as maintaining an administration interface, thus using an instance of ThreadRemotingServer in composition makes a lot of sense. For an example, such as ours it pays to extend the class, since it makes for a much cleaner code base. We are going to call our server class NekoServer. This class could feasibly be reused

Listing 2. The server API interface interface IUserServer { }

function updateSelf( x : Int, y : Int ) : Void;

Listing 3. The client API interface interface IClient {

function setId( userId : Int ) : Void;

function addUser( userId : Int ) : Void;

function removeUser( userId : Int ) : Void;

}

function updateUser( userId : Int, x : Int, y : Int ) : Void;

Listing 4. The server API class class ClientApi extends haxe.remoting.AsyncProxy< IClient > {} public var client : ClientApi; public var id : Int;

public function new( cnx : haxe.remoting.SocketConnection, userId : Int ) { client = new ClientApi( cnx.client ); id = userId;

neko.Lib.println( id ); client.setId( id );

for ( u in NekoServer.users ) if ( u.id != id ) {

u.client.addUser( id ); client.addUser( u.id );

}

}

public function removeUser( userId : Int ) { }

client.removeUser( userId );

public function updateSelf( x : Int, y : Int ) { for ( u in NekoServer.users ) if ( u.id != id )

}

u.updateUser( id, x, y );

public function updateUser( userId : Int, x : Int, y : Int ) {

}

72

}

client.updateUser( userId, x, y );

in many of your socket server applications. It provides features that you will want to use again and again. The NekoServer class is displayed in Listing 1. As you can see, it is an incredibly simple class. Many developers often get scared about the concept of writing networked applications using sockets. Even I used to. Due to this, there are many encapsulated networked server applications, such as Colin Moock’s Unity Server, that you can buy off the shelf with the idea of extending it to your own ends. Hopefully, this article will now show that you will not need to do this. The NekoServer class provides the main entrypoint function required in all Neko applications. In our main function, we instantiate the NekoServer class, then call its run method, providing it with the domain name and port for communication with the outside world. As we are using the application locally on our desktop, we can use “localhost” as our domain name. If you choose to use a different port number, remember that you will need to propagate this into the client application code too. The NekoServer class also overrides two methods from the base ThreadRemotingServer class; initClientApi and clientDisconnected. initClientApi is called by the server when a client is newly connected. The method is passed a remoting context representing the server remoting capabilities. The remoting context is used to enable serializing and unserializing object instances for sending to and from the client. As our remote method contracts are stored within interfaces, we use the initClientApi method to register those server interfaces with the remoting context so that the remoting layer knows beforehand what API is available to it. As you can see, there is very little code required to do this. The method simply instantiates an instance of our server API class, called UserServer in this case and passes it to the remoting context along with a string representation of its name. You can actually supply any string value you wish though the client will use this name as a means to invoke the API methods. Each connected client has its own instance of the UserServer class available on the server. For that reason, we store a reference to the UserServer instance within the client connection object, as well as storing the connection object within a list, so that other clients can access it later. The second method clientDisconnected, is called whenever a client disconnects from the server. As a disconnected client is no longer contactable, there is little the server can do with that client. However, what it can do is to notify all the other connected clients of the disconnection, so that they can remove all local references to that client. In most cases, the 02/2009 (4)


Multi-user Applications in haXe

server API, or UserServer class in our example, handles all calls to the client. Thus, using our stored client references we can iterate through them and call their removeUser method one by one.

API Interfaces Any good developer plans their application development before doing any coding, which I am sure you all do. Ergo, creating your API interfaces for use in your multi-user server should be one of the first things you do. Looking at Listing 2 and Listing 3, you can see the interfaces we will be using for client and server. They are very simple and provide for very basic functionality. As we discussed earlier our application is going to be oriented toward games development, so I have written these interfaces to support sending x and y coordinates to and from the server. In our

case, these x and y coordinates represent the position of the mouse cursor within the client window, though in a gaming situation, they could quite feasibly represent the location of a game character or other such entity. What we will aim to accomplish is to have a graphical representation of each connected users mouse cursor appear in the window of each client. The client API’s interface is called, surprisingly, IClient. It exposes the method setId, which we require so that we can send the client its unique identifier. This is not absolutely necessary in socket server development, however in our circumstance, we need to be able to alert the clients about each other'ss current state and this requires some kind of unique reference. The next three methods of IClient are used to receive the client state notifications. This includes adding a new client, removing an

existing client, and notifying of the clients current mouse position. This is all very basic stuff and all the client needs to be aware of. When modifying this for use within a game, you will likely need to elaborate on these methods, but you will most certainly need this data as a minimum. The server API interface is called IUserServer, and exposes only one method. This is unusual for most networked applications, whereby the client responds to user interaction and based on certain user events will need to push or pull data from the server. This will require an array of server functionality. The server, on the other hand, will normally only harass a client pending encouragement from another client, which will not be nearly as frequent. In our example, the client is only interested in notifying the server of updates to the mouse

Listing 5. The client API class

import flash.events.Event;

x = y = 0;

import haxe.remoting.SocketProtocol;

graphics.drawRect( 0, 0, 300, 220 );

import flash.events.MouseEvent;

graphics.beginFill( 0xFF0000, 0 ); graphics.endFill();

class ServerApi extends haxe.remoting.AsyncProxy

}

class Client extends flash.display.MovieClip, implements

public function handleMouseMove( event : MouseEvent ) {

< IUserServer > {} IClient {

_server.updateSelf( Math.floor( event.localX ),

public static var client : Client;

Math.floor( event.localY ) );

public static var id : Int;

}

private var _server : ServerApi;

public function setId( userId : Int ) {

public static function main() {

}

private static var _socket : haxe.remoting.Socket; private var _users : List< User >; client = new Client();

public function addUser( userId : Int ) {

if ( _users == null ) _users = new List();

flash.Lib.current.addChild( client );

}

var u = new User( userId );

_users.add( u );

public static function onConnect( event : Event ) { }

trace( "connected" );

public function removeUser( userId : Int ) { for ( u in _users )

if ( u.id == userId ) {

_socket = new haxe.remoting.Socket();

removeChild( u );

_socket.addEventListener( Event.CONNECT, onConnect ); _socket.connect( "localhost", 4040 );

var context = new haxe.remoting.Context();

}

context.addObject( "client", this );

var cnx = haxe.remoting.SocketConnection.create(

_users.remove( u );

) {

for ( u in _users )

_server = new ServerApi( cnx.UserServer );

if ( u.id == userId ) {

drawBackground();

u.x = x;

this.addEventListener( MouseEvent.MOUSE_MOVE,

02/2009 (4)

}

public function updateUser( userId : Int, x : Int, y : Int

_socket, context );

handleMouseMove );

private function drawBackground() {

addChild( u );

}

public function new() {

}

id = userId;

}

}

}

u.y = y;

73


Server Side Interaction cursor location, so that it may notify other connected clients of this data. Therefore, we are able to keep the server API very simple.

API Implementations The implementation of the UserServer class, as seen in Listing 4, handles the functionality for the server API, as well as the code needed for the server to manage clients. Client management is usually of a certain bulk of your server code and so should be relative from application to application. In some cases, it might pay to put this information into a separate API class for reuse. When the UserServer class is first initialized, this signifies that an associated client has just connected to the server. If you recall from the NekoServer class, the new UserServer instance was passed a reference to the connected clients socket connection object, as well as its unique identifier. The UserServer instance then uses the connection object to create an asynchronous proxy, which it will further use to invoke methods on the client. At this point, it is worth noticing that the UserServer class is implementing the IUserServer interface, as one would expect. However, the AsyncProxy class, inherited by the ClientApi class instance, is passed the type for the IClient interface, thus sealing the remote method contract between client and server. The same occurs within the Client class, using the IUserServer, as you will see in a moment.

Once the remote proxy has been created, we then see that the client is given its unique identifier. Following this, each connected client, other than the current one, is informed of the new member and given its id. In turn, the newly connected client is made aware of each of the other client’s identifiers. This is akin to being introduced to people when arriving at a party and is all that is required to initialize our client. The removeUser and updateUser methods are merely proxies for the base server functions or clients to communicate with other clients. removeUser is pretty simple and merely removes the client with the given identifier from the client associated with this UserServer instance, while updateUser handles notifying this client of another clients mouse cursor location. updateSelf, on the other hand, is called by the UserServers client when its mouse cursor location has changed. As you can see, it is within this method that updateUser is called. The Client class, shown in Listing 5, looks a little more complicated than it needs to be, as it handles the graphical representations within the output Flash movie as well as the API functionality used by the server. When instantiated, the Client class needs to handle its own socket and context creation. The server has this done for it by the base ThreadRemotingServer class, though internally, it does this also. As you can see,

Listing 6. The user representation class class User extends flash.display.MovieClip { public var id : Int;

public function new( userId : Int ) { super();

id = userId; }

drawUser();

private function drawUser() { var g = this.graphics;

g.beginFill( Math.floor( Math.random() * 0xFFFFFF ), 1 ); g.drawCircle( 0, 0, 5 ); g.endFill();

}

}

Listing 7. The compile script -main NekoServer -neko server.n --next

-main Client

-swf-version 9

-swf-header 300:220:30:CCCCCC -swf ui.swf

74

we are using the same domain and port number we used in the NekoServer class. If you changed this, make sure you use the same value here or your client will not be able to connect. The client uses a drawn background so that it can capture the MOUSE_MOVE event. If you develop a Flash client aimed at the AVM1 virtual machine, you should not need to do this, as the stage will notify of mouse events too. When the mouse cursor moves over the drawn area, it indirectly calls the handleMouseMove method, which then proceeds to pass this notification to the server. The remaining methods of the Client class are used to maintain visual representations of the other clients. Each of these methods are invoked by the server. We use a separate class called User,as shown in Listing 6, to draw the client representation, which is given a random color, so as to remain distinct from the other clients.

Running The Application To compile the server and client applications, copy the content of Listing 7 into a new text file and rename it compile.hxml. Next, open a new command window and navigate to the directory containing your source files, then enter haxe compile.hxml and press enter. If you wish to create an executable of your server, enter nekotools boot server.n and press enter. To run the demo, execute the server first, then open several instances of the Flash movie ui.swf. The Flash movie should show a connected text at the top once it has successfully connected. Once this occurs on more than one client, you can proceed to move your mouse cursor over the client window. Doing so should result in you seeing a small colored circle moving around within the other clients, as shown in Figure 2 : How the application should look.

Conclusion In this article, we have developed a server application and client that can be used as a starting point to a multi-user Flash game or desktop application. As a starting point, the x and y values for the users mouse cursors could easily be replaced with the x and y values of a game character, giving rise to who knows what? Maybe even the next Flash MMO? Hopefully, this article has given insight into how simple multi-user applications are to develop with haXe, especially given that no new languages were required.

LEE MCCOLL SYLVESTER A haXe and Neko evangelist and author of the Professional haXe and Neko book. He is an expert ActionScript developer as well as a seasoned master in systems integration.

02/2009 (4)



Level of difficulty

Achieving a retro-style using only Flash by Tem Tupac Aguerre As much fun as programming can be. Let's take a look at another fundamental part of web development, design. One of the big misconceptions about Flash is that the the graphics tools within Flash are weak. They're not, you just need to know how to use them. With some advanced use of it's built in filters and blend modes you can actually make awesome visuals using nothing but Flash. 76

02/2009 (4)


retro-style

What you will learn...

What you should know...

• Advanced use of Flash's filters. • Working with gradient masks. • Using blend modes.

• Familiar with the flash interface. • Working with movieclips, layers and the timeline.

I

n case you haven't noticed, the 80's are back. And I'm not talking about mullets and huge shoulderpads, but moreso a lot of design styles and trends that were popular back then. It's all about retro now and one great example of this is the video for DVNO by Justice. Of course it is mainly made in After

Effects, it is also for that software I first learned how to do this. But a similar retro look can also be achieved directly in Flash. Without the help from any other software like Illustrator or Photoshop. Now you might wonder, what does this have to do with web development? Well, I can tell you we WILL be pushing the

Flash players graphics engine to it's limits. In this tutorial I'm using a free font called Bifurk, very similar to the font Pacmania, but with some well needed adjustments to some of the letters. They're both free and you can easily find them using your favourite search engine. And remember, this tutorial is to learn about the different results you can get using common filters and blend modes. You don't have to follow every setting religiously. Feel free to play around with the settings and see what other results you can get. So with that said, let's go right ahead with the tutorial!

01

1. Open a new AS3 flash file. For the sake of this tutorial we're keeping it pretty small. 600x350px will do just fine. Change the background to black and let's change the framerate to 30, so it runs smoother. Save the document.

02

2. Choose insert new symbol (ctrl+F8 on a pc) and name it retroText_mc.

02/2009 (4)

77


Sound and Animation

03

3. Take the text tool and write your text as static text, make sure that you use center align text, it will come in handy later, make it a light grey (#CCCCCC) and use the align panel to align the text dead center.

04 4. Convert the text into a movie clip [F8]. Name it baseText_mc and make sure the registration point is in the center. Now this is the movie clip we will be reusing everything that has to do with the text. The advantage of working like this is that if we ever want to change the font or the text, we can just change it inside that movie clip and it automatically update everywhere.

05 5. Now we're going to start building up the type element. Decide on what color you want to be the dominating color. If you want it to look retro you should pick any saturated (bright) orange, blue, yellow, pink or green. TIP If you have colors that you use a lot in a project, instead of memorizing the hex-code you can just add it to your swatches panel by picking the color, clicking the menu and choose add swatch. You can even save those custom swatches for later use. I'm going with pink (#FD41AA) on this one.

78

02/2009 (4)


Retro-style

6. Let's go ahead and make the type look 3d by doing a fake extrusion. I like to keep things neat and tidy so first rename the layer to 3d Extrusion.

06

TIP I will only be mentioning the settings I change. So if something isn't written down, I've left it at it's default. Apply a Gradient Glow to the movie clip: • • • • •

We also want the extrusion to be darker than our original color to enhance the 3d illusion so give both sliders the same darker color (#89014B). Lock the layer when you're done.

7. Now we're going to make the front of the text look like it's made out of metal by using more filters. Make a new layer. Name it Text Face and drag a new instance of baseText_mc onto the stage. Align it dead center with the align panel. First give it a Drop Shadow: • • • • • •

Blur X: 13 Blur Y: 6 Strength: 1000% Angle: 340 Distance: 7

Blur X: 0 Blur Y: 9 Strength: 65% Angle: 90 Distance: -3 Check: Inner shadow

08

Then a Gradient Glow: • • • • • • •

Blur X: 20 Blur Y: 25 Strength: 90% Quality: High Angle: 130 Distance: 15 Type: Inner

07

And finally a Glow: • • • •

Blur X: 6 Blur Y: 6 Strength: 225% Quality: High

Give it a lighter color than your base color (#FFB6FF). Don't forget to save your work now and then.

8. Now it's time for an outline. Lock that layer and make a new one, name it Text Outline and drag a new instance of our baseText_mc onto the stage. Again, align it dead center using the align panel. Hide the two bottom layers so we can see what we're working with and give the movieclip a Glow: • • • • •

Blur X: 1 Blur Y: 1 Strength: 500% Color: #FD41AA Check: Knockout

Unhide the two bottom layers. Not too exciting.. But look what happens if we apply the Add blend mode to it. Pretty nice huh?

02/2009 (4)

79


Sound and Animation

09 9. Lock that layer and make a new one, name it Reflection. Take the pen tool and start drawing a reflection over the text. Don't worry about going outside the text. Fill it with white and remove the outline. TIP If you double click a line, it will select all lines with the same color and width connected to it.

10

10. Transform it into a movieclip, name it reflection_mc, bring the alpha down to about 40% and give it an Overlay blend mode.

11

11. The edges are a bit too sharp so let's give it a Blur filter: • Blur X: 8 • Blur Y: 8

80

02/2009 (4)


Retro-style

12

12. Let's mask the reflection so it won't cause any problems later. Make a new layer, name it Reflection Mask. Drag another instance of our baseText_mc onto the stage and guess what? Align it dead center using the align panel! Make that layer into a mask by right clicking on that layer and choose Mask.

13.

13

14

Now let's make a huge glow that will sweep across our text layer. Make a new layer and name it Huge Glow, Drag another instance of our baseText_mc onto the stage and, bingo, align it dead center using the align panel. Hide the other layers and give the movie clip the following filters: • Glow: • Color: #FD41AA • Strength: 155% • Quality: High • Check: Knockout • Glow: • Color: #FD41AA • Blur X: 10 • Blur Y: 10 • Strength: 300% • Quality: High • Gradient Glow: • Blur X: 16 • Blur Y: 16 • Strength: 275% • Quality: High • Distance: 0 • Give both sliders the same color: #FD41AA • Type: Full Change the movie clips' blend mode to Add and give it an alpha of 70%. Give the movie clip an instance name, hugeGlow_mc. Lock the layer and unhide the other layers.

14. We're going to add a gradient mask to this but in order to make it work we're going to need just a few lines of code. Let's start by setting it all up first. Make a new layer and name it Glow Mask. Make a rectangle with a linear gradient starting and ending with alpha 0. No outlines. Then convert it into a movie clip and call it glowMask_mc and give it the instance name glowMask_mc.

02/2009 (4)

81


Sound and Animation

15

15. Now if we were to make the layer a regular mask layer and test our movie we would see that it still has sharp edges. So here's what we need to do. While this might not be the best way of coding, for the simplicity of this tutorial we're going to keep the code inside this movieclip. Make a new layer, name it actions and on that layer, add the following script: hugeGlow_mc.mask = glowMask_mc;

hugeGlow_mc.cacheAsBitmap = true; glowMask_mc.cacheAsBitmap = true;

If you test your movie now you'll see that it looks a lot better. Ok, before we continue, let's just play with this for a bit!

16. Tilt the mask about 30 degrees and in the actions layer add the following code:

16

glowMask_mc.addEventListener(Event.ENTER_FRAME, moveMask);

function moveMask(e:Event):void { }

glowMask_mc.x = mouseX;

Now what this does is it's positioning the mask on every frame to the x-position of the mouse. So test the movie and play with the glow for a bit. Now we're basically done with the text, so let's go ahead and make a grid.

17

17. Go out into the main timeline, rename the layer to Retro Text. Make a new layer in the bottom and name it Grid. Take the line tool and make a whole bunch of white vertical lines, thickness 1. Use the align panel to space them evenly horizontally across the stage and along the top edge.

82

02/2009 (4)


Retro-style

18

18. Select all the lines, copy ([Ctr]+[C] on a pc), paste them in place ([Ctrl]+[Shift]+[V] on a pc) and then rotate them 90 degrees ([Ctrl]+[Shift]+[9] on a pc) and resize them horizontally untill they cover the stage.

19

19. With the horizontal lines still selected, group them ([Ctrl]+[G] on a pc), align them along the top edge using the align panel and then ungroup them ([Ctrl]+[Shift]+[G] on a pc).

20

20. Select and delete anything outside the stage.

02/2009 (4)

83


Sound and Animation

21

21. Let's put the grid in a perspective. First, scale the grid vertically until it's a bit under the text.

22 22. Now we're going to use a tool that's notoriously horrible to use in flash. The distort tool, luckily we're not going to do anything advanced with it. with the grid selected, choose the distort tool and while holding shift, drag the corner inwards. This will bring the opposite corner in too. Drag it until you feel you have a nice perspective.

23

23. Scale it up horizontally until the back reaches the edges, select and delete anything outside the stage and convert what's left to a movieclip. Name it grid_mc.

84

02/2009 (4)


Retro-style

24

24. Apply a white Glow filter to it. Set the strength and the blur to a value you like. Quality should be on high though.

25

25. Copy the grid, make a new layer, and paste it in place. On its Glow filter, decrease the blur a bit, increase the strength and give that movieclip an Add blend mode.

26

26. Now let's make some stars. Lock the other layers, make a new one in the bottom. Name it Stars. Grab the brush tool, second smallest size, make the fill white, alpha 50% and just click away. Click click click click, until you feel you have enough stars. Now for the final touch, some clouds.

02/2009 (4)

85


Sound and Animation

27

27. Make a new layer over the Stars layer, Call it Clouds. With the brush tool again, biggest size. Give it an orange radial gradient that fades out to alpha 0%. Give it a rough cloudy shape. Now make a blue one next to it.

28

28. Select them, convert them to a movie clip and call it clouds_mc. Apply a blur filter, give it lots of blur.

29

29. Choose, copy, make a new layer, paste, make another layer and paste again.

86

02/2009 (4)


Retro-style

30 30. Now comes the really fun part. Resize and rotate the individual clouds any way you like, maybe change the alpha a bit. And play around with the blend modes on all three clouds. Try the Add, Difference, Invert and Hard Light blend modes. Depending on their stacking order, just changing one can produce a totally different result. For instance, give the top and the middle clouds an Add blend mode and set the bottom one to Hard Light.

31

31. Test your movie, and you're done!

Conclusion So in this tutorial we saw how we can use the built in features of Flash in some unusual ways to achieve cool results. But as powerful as Flash's drawing tools might be, the Flash player is weak when it comes to drawing filter and blend mode heavy animations. For example, if you were to make a big animation out of this. You would most certanily bring the Flash player to it's knees. Your CPU would cry and hate you while it's trying to help the Flash player do what it's told. Hopefully, with the increasing popularity of the use of the various 3d engines for flash, Adobe will adress the need for a more powerful Flash player in its future releases.

TEM TUPAC AGUERRE Tem Tupac Aguerre has recently set his base in San Diego, California where he works with Web Design and Motion Graphics. Before moving to the US he was an Internet Creative/Web Designer at one of Swedens major advertising agencies. Some of the clients he’s worked with include MTV, Samsung, HP and Chevrolet.

02/2009 (4)

87


Sound and Animation

Secrets of a professional Flash game programmer by Tom Rassweiler For the last five years as the leader of the Flash development team at Arkadium, a NY based game development company, I have worked on more than a hundred Flash games for clients, ranging from toy companies like Mattel to publishing giants like Hearst and NewsCorp. What you will learn..

What you should know...

• Practical tips for designing your Flash games to be flexible, versatile and more cost effective.

• A general understanding of XML formatting, loading external content, object oriented coding and working knowledge of Actionscript.

Level of difficulty

B

y developing stable, adaptable game engines, we have been able to reutilize many game engines, requiring minimal time and expense on adjustments to the code. At Arkadium, we utilize Adobe’s Flash player because it provides an amazing and efficient development platform for online

game creators. The plug-in is already installed on the vast majority of web-surfers’ computers and is also available on many phones, set-top devices and the Wii. I often get asked by smaller independent developers how they too can make their Flash games more flexible, versatile and ultimately more cost effective. Here I let you in on a few of our tips and tricks.

What is a reusable engine? The advantage of a reusable engine is that you can develop a game engine once and then easily give it a new coat of paint and re-deploy

it on a different website. One can change licensed games in a variety of ways to make them compatible and fresh for new clients and demographics, by using new art, music, levels or additional functionality, or all of the above, see (Figure 1).

Doesn’t standard Flash architecture present a problem? One major challenge when efficiently developing reusable Flash games is that Flash uses a single black box source package, an FLA file that often requires the programmer to integrate even the tiniest change. This is extremely inefficient. The artist lays out the art and times the animations. Then the programmer has to lay it out again and invariably gets it all wrong and needs to do it over. What’s a pixel difference here or there to a programmer? The same is true for sound and other content. You should develop the game the first time so that each specialist

Figure 1. An example of two launch-the-object matching games where the art is slightly tweaked, but the mechanics are exactly the same

88

02/2009 (4)


Secrets of a professional Flash game programmer

can make the necessary alterations without requiring a programmer’s help. The first step is to externalize everything that can possibly be pulled out of the black-box FLA. Anything that needs to be in there has to be organized so that any artist can work directly in the code without breaking it.

Externalizing sounds like a good idea but where do I start? The easiest things to externalize are text files. You can externalize all kinds of data in a text format. Include the simple stuff like chunks of visible text that will need to be edited in the future, such as story, dialog and help text. Include links out to web-service elements which can easily be adjusted by a webmaster. Most importantly, pre-plan to externalize all the possible level design variables. These will be unique to each game but can include numbers of levels, timers, level layouts, point values for every possible event, and toggles for special abilities that you might want to turn on and off in different versions. You might even add some scripting to allow designers to change the point algorithms or to allow them to create mad libs-style dynamic text. The key is to put all of the design controls in the hands of the game designers, with no reliance on the programmer. In this way, you can efficiently take a game that gets pretty hard, and then make an easier version, see (Figure 2).

externalize these functions as well. In terms of score communications, there is very little universality. Some sites need these messages encrypted with MD5, others with TEA. Some use communication through Javascript and others through direct calls to web services. Thus, it is best to make this functionality external to the game code so that when making changes to it, you limit the scope of potential errors. At Arkadium we use an external SWF game end. Every game is coded to load an external file like this at the end of the game, and all the complex and specific communications are housed there. Once we create a game end that communicates well with a client’s back-end, all of our games will have this potential with no change to their code, see (Figure 3).

What about animations that cannot easily be extracted from the source package? Art and animations are sometimes hard to extract, but with planning you can make this package more efficient. The goal is to let the artist work directly in the code. In this way, even the smallest artistic detail can be directly controlled by the artist so that time isn’t wasted trying to explain these problems to the usually aesthetically challenged programmers. This of course has pitfalls; it is easy for a non-programmer to break things while blundering around in the code. The key is to artist-proof your code so as to give them maximum accessibility with a minimum of breakable code left out in the open.

Is there a “best” format for external text files? You should use XML extensively to define external text elements. The nice thing about XML is that it is easy for anyone to open, edit and share. Better yet, there are strong interfaces in every coding language that you can use to parse and create XML documents, so the format provides great flexibility. You can begin with a simple trivia game all in Flash with a static XML document that the game reads to define the questions. Then, if you need to deploy it with a more substantial database of questions, you can develop a web-service solution that can output the XML in the exact same format, without significantly changing your game code. The long-term potential for this is enormous, because you can very easily take a simple Flash game engine designed to read questions and turn it into an entire website driven by user-generated content, see (Listing 1).

What if different sites have different ways to encrypt and communicate scores? Score reporting is just one example of a unique function that will need to be malleable from version to version. You should plan to 02/2009 (4)

Figure 2. In these two re-skinned games, the level, hints and point structures have been adapted for each version. The bottom version was made to be much easier with less color combinations

89


Sound and Animation How do I “artist proof” my code? To start artist proofing, make sure to isolate your code in external files. To most programmers this will sound obvious, but older versions of Flash did not allow some of the standard object-oriented practices of other languages. Even Actionscript 3 allows you to hide code on the timeline in little a frames, and artists might move or delete these without realizing it. Avoid putting code on the timeline as much as possible. Consider taking a few tips from the Model View Controller (MVC) design pattern, which

intensively isolates the game logic from the game display. It allows an artist to drastically change the display with little change to the engine logic, see (Figure 4).

How can I make it easier for artists working in the code? Animations in games can become very complex. Every screen and event needs intro and outro animations with countless event animations in between, all carefully timed. Our goal is to create an engine that, without our help, lets the artists have their freedom to tweak the timing

Listing 1. XML code <levels>

<sScoreEquation type="Equation">$nBaseScore + ($nFlysCaught * $nScorePerFly) </ sScoreEquation > <!-- equation to define the scores -->

<level name="Level 1">

<sStory type="String">Welcome to level 1 try and catch all the flies.</sStory > <!-- Text that displays before the level -->

<nBaseScore type="Number">1000</nBaseScore > <!-- The score earned by completing this level -->

<nScorePerFly type="Number">10</nScorePerFly> <!-- The score earned for each fly caught -->

<aFlyTypes type="Array">5,5,1,1,0</aFlyTypes> <!-- Probability of to show different fly types -->

</level>

<level name="Level 2">

<sStory type="String">Welcome to level 2.

Now it's getting harder</sStory > <!-

- The score earned by completing this level -->

<nBaseScore type="Number">2000</nBaseScore > <!-- The score earned by completing this level -->

<nScorePerFly type="Number">15</nScorePerFly> <!-- The score earned for each fly caught -->

<aFlyTypes type="Array">2,2,3,5,5</aFlyTypes> <!-- Probability of to show different fly types -->

</level>

</levels>

and the presentation of all of these animations to come up with the coolest possible feel for the game, and have it all still work. It sounds like a pipe dream but it’s 80% achievable just by being smart when developing the code. Place all functional objects on the stage. As clean as it is to a coder to see a blank stage and have all the objects neatly filed away, it will help an artist more to see them on the stage in place. If you tuck them away, artists will have a hard time finding all of the right objects in the library, even with good naming techniques, and you will have to spend time explaining to each new artist who needs to redo it. So it really saves time to actually leave all of the pieces in place on the stage. In this way the artist can easily find and change things and align them correctly with other pieces. This does mean that there could be lots of clutter on the stage to start, but AS3 helps us out with this. By using the removeChild() function you can clear them off the stage at initialization and then add them back when they are needed at the exact correct spot. When triggering events based on animation timings, you should use frame labels. For example: a curtain rises, and you need to have the code respond when the curtain is up. You can have code that watches for specific frame labels and executes. The advantage of this is that these labels are very visible to artists; if they want to extend the curtain rising animation or want to change it to a star wipe they can easily see and move the frame label to the appropriate location, see (Figure 5).

Flash games and higher profit margins Casual online Flash games provide simple addictive game mechanics that can be enjoyed by everyone. The only challenge is to provide appropriate art and atmosphere tailored for each specific audience. By using these tricks

Figure 3. Generic game end with points and login/registration prompt, and custom game end with points, login/registration prompt, advertisements, challenge a friend and more game links

90

02/2009 (4)


Secrets of a professional Flash game programmer

��������������

����������������

��������������������������� �������������������������������

����������������������������� ����������������������������

����������������������������������� ���������������������������������������������������� �������������������������������������������������������� �����������������������������������������������

������������������� �����������������������

����������������������������������������������� �������������������������������� ����������������������������������������������������������������������������������� ��������������������������������������������������

Figure 4. Sample MVC design pattern for a racing game

to develop stable flexible game engines, it will be easy to generate multiple versions for every kind of situation: maybe one for a kids’ TV show, one as an advertisement for soft drinks and one for middle-aged women who need to unwind. Each of these versions should require only a little work from artists and level designers and leave the programmer to focus on the next new game mechanic.

TOM RASSWEILER

Figure 5. Same frame labels in Layer 1

02/2009 (4)

Tom Rassweiler is the Manager of Game Development at Arkadium, a leading game solutions developer in New York City. For the last five years Tom has worked on over a hundred web and downloadable games, focusing on how to keep game development affordable and quick with growing competition and production costs.

91


Interview

by Kevin Hoyt

Interview with Lee Brimelow

Lee Brimelow is a Platform Evangelist with Adobe and an award-winning interactive designer. He has worked in the past for companies such as America Online, Netscape, eBay, Stanford University, and frog design and has a passion for developing new and innovative ways of using the Flash Platform to create rich user experiences. He runs the popular technology blog at theFlashBlog.com, produces the free Flash tutorial resource at gotoAndLearn.com, and has a regular column on Flash in Layers Magazine. Lee is also the author of several titles for Lynda.com including Flash Professional 8 Video Integration and After Effects 7 + Flash 8 Integration. Can you introduce yourself and tell us a little bit about your background ? I have a very colorful background to say the least. After high school I became a snowboard bum and began shooting video and photographs for magazines. Then I spent about 7 years working as a security guard at various places in Silicon Valley. It was during this time that I started to learn web development as a hobby. I was able to get my first job with a completely fictitious portfolio that included websites for companies that didn’t exist.

92

After about 5 years of HTML and JavaScript I fell in love with Flash and the rest is as they say, history. I’m living proof that you don’t need a college degree to be successful in this industry. I worked my ass of and that is why I am where I am today.

on it exclusively. I just loved that I could be both a designer and a developer in a single tool. I’ve always wanted to do it all aspects of interactive design and Flash has allowed me to do just that.

How did you get started with Flash?

That’s tough because there isn’t really a typical day for an evangelist since we travel so much.

What does a typical day look like for you?

I used to play around with Flash MX when I was working at AOL. But it wasn’t until I started working at Stanford that I really began to focus

02/2009 (4)


02/2009 (4)


Interview

to get ideas for motion graphics and animation by watching TV and movies. I also look a lot to magazines for interesting design and layout ideas. But the number one thing that inspires me is the Flash community itself. I have never met a nicer and more talented group of people in my life. That’s why every community wants to be like us.

What do you consider to be your biggest success?

But if I’m home I’ll wake up around 10am and go down to the local Starbucks to get some caffeine in me. Then I start going through email, reading blogs, and follow what people are talking about on Twitter. I basically can do whatever I think will help the Flash community that day. It may be writing a blog post, recording a tutorial, or working on a video project. If I’m travelling it is usually to speak at conferences so I can often be found holed up in my hotel room working on my slides and demos.

What are your plans for the future? My plans for the future are pretty simple. I want to keep being able to do what I’m doing right now. I can’t imagine having a better job than this. Of course maybe I’ll become a senior evangelist and

Who or what is your inspiration? Erik Natzke and Jared Tarbell were the two guys who inspired me the most in the early days. Now I get inspiration from everything around me. I like

My biggest success is definitely getting my current job. It took a lot of hard work and late nights but it paid off in the end. I would like to thank Mike Downey and Mike Chambers for recruiting me and seeing that I had the potential to do good stuff for Adobe. Gotoandlearn is also something that I am very proud of since it has really helped a great number of people learn Flash. The response that I get from people is truly amazing and I’m so happy that I have been able to help people get jobs and start their careers.

What changes we will see in flash player 11 (or the next major release)? or in another way what adobe will do to make flash player more powerful ? While I can’t talk about specifics just yet, we will continue to enhance the performance of the player. As more and more people push the envelope with Flash it will be important for us to make sure that they aren’t limited by the speed of the player.

What are the latest news about SWF files and crawling and indexing by Google? We provided Google and Yahoo with what is essentially a headless Flash Player that allows them to simulate an actual user and index SWF content in a much more useful way. Google is still working on their end to make things work as best as possible. The trouble is that they don’t reveal anything to anyone about their search algorithms so we don’t really know exactly what they are doing with the technology that we provided them. We are starting to seem to tests coming back to indicate that the new technology is improving the rankings of certain Flash content. It will be a while though before best practices emerge the same way they did for regular HTML content.

94

02/2009 (4)


Recommended Companies mod7

Adobe

ftware coma diversified so is c. In s m te d mobile soAdobe Sys of business an e lin a rs fe of aging, delipany, which creating, man r fo es ic rv se content and ftware and ith compelling w ng gi ga en technology vering and d Flash to its de ad be do A . in 2005. experiences of Macromedia on iti is qu m ac r te portfolio af www.adobe.co

Digicrafts

ing company nents is the lead po om C h as Fl d related proDigicrafts ex extension an Fl h/ as Fl ng pi design induon develo riences on the pe ex of s ar ye . We can creducts. With ultimedia design m on se rti pe gner to maxistry and ex oducts for desi pr e bl ita su t os ate the m tivity. mum their crea

and intecommunications al su vi a interacmod7 is specializing in cy en ag gn n graphics. raction desi gn and motio si de eb w , nic Arts to tive media – from Electro s nt ie cl of e for making A broad rang by our passion ed ck ro en be do the same CBC – have nces. We can rie pe ex e iv ct killer intera for you. m www.mod7.co

Kindisoft

to ensuvision; a vision a as t ou d te ity, and inKindisoft star s’ code, creativ er gn si de of y ternet is bere the securit e days, the In es Th . ty er op medium tellectual pr and interactive ic m na dy e or freedom to coming a m designers the ng vi gi n, io at ic of commun they want. lves in any way express their se

s.com.hk

ft.com

www.kindiso

www.digicraft

Advitor

tion and eative, innova cr ly gh hi a graphics, The Advitor is sign, motion de e iv ct ra te , animaexpertise of in dio, rich media au & ic us m of highfilm production, ing in all fields liz ia ec sp gy lo tion and techno and animation. music & audio , m fil , gn si de end com

www.advitor.

Powerflasher

undation in me since its fo co be s ha er ency speciaPowerflash g multimedia ag in ad le s e’ op , graphic ar1997 Eur ssionate coders pa rty Fo h. as an 1.000 intelizing in Fl velop more th de s or at im an and offline hutists and er-friendly onus t ye ng ni un us clients all ractive st es for prestigio nc rie pe ex ce man interfa over the globe. asher.com www.powerfl


Books Review

Programming Flex 3 The Comprehensive Guide to Creating Rich Internet Applications with Adobe Flex

Authors: Chafic Kazoun, Joey Lott Publisher: O'Reilly Media, Inc. Language: English Paperback: 657 pages (19 chapters) ISBN 10: 0-596-51621-5 ISBN 13: 9780596516215 Website: http://oreilly.com/catalog/ 9780596516215/

A

dobe Flex 3 is the hot new technology for creating rich experiences both for the web and for the desktop (with Adobe AIR). With Flex 3, web developers at any skill level can create high-quality, effective, and interactive Rich Internet Applications (RIAs) quickly and easily. Getting started with Flex is pretty easy. Flex may be easier to learn than the Flash IDE, but you still need a reliable guide to the framework. If you have work already on framework like .NET or Java; Flex will be quite easy to learn. In this learning process Programming Flex 3 The Comprehensive Guide to Creating Rich Internet Applications with Adobe Flex by Chafic Kazoun and Joey Lott is a good book to start with. You are absolute beginner then this book not for you. This book is written assuming that user are comfortable, have knowledge of working with programming languages as well as a server-side languages like Java, .Net, PHP, ColdFusion, or a similar technology. Flax is a robust, open platform, open source SDK useful for developing rich Internet applications. First of all, this book introduces us with Flex, Flex Application Technology and its new feature. With Flex 3, it’s easier and faster than ever to create beautiful and powerful applications. This book is the complete update for Flex 3 of the best-selling Programming Flex 2, the definitive introduction to Flex for developers. Flex removes the complexity barrier from RIA development by offering sophisticated tools and a straightforward programming language. This book traces more on building blocks of Flex 3 like MXML, ActionScript

96

3.0, Flex Framework basic, application life cycle of Flex application and expanding their coverage with real-world examples, including complete Flex code samples to work in real day-to-day tasks. One of the key features of Flex is its ability to simplify application layout. Here we see the power of Flex UI component in developing eyecatching user interfaces and customizing it with power of CSS, adding effects and transitions. Then we move further to deal with forms and data. Validating and formatting user inputs. Client data communication and remote data communication with technologies like XML and SOAP. Debugging is the technique which improves usability and quality of code. Keeping this in mind author introduce us with flex debugging technique. And at last we are ready to develop our Web based as well as windows application with the Flex.

Conclusion This book is an amazing book in the O'Reilly's Adobe Developer Library series. The book is very well organized with useful, understandable and easy to use examples. This book is nothing than a comprehensive reference to Flex 3 and a good abstract of the Flex documentation. This book will definitely help anyone to get more from amazing flex technology. by Chetankumar Akarte

01/2008 (1)



Books Review

Flash CS4: The Missing Manual

Authors: Chris Grover with E. A. Vander Veer Publisher: O'Reilly Media, Inc./ Pogue Press Language: English Paperback: 751 pages (19 chapters) ISBN 10: 0-596-52294-0 ISBN 13: 9780596522940 Website: http://oreilly.com/catalog/ 9780596522940/

O

ver the last 10 years Flash is the favorite among the web developer and animator. Designing, animation, multimedia development, Games, Banner and advertising where flash get mostly used. With Flash CS4’s easy to use Panels and Toolbar, we are able to create sophisticated and interaction animation which work smoothly on web, desktop, mobiles and kiosks. Browser and platform (operating system) compatibility are the main features which made Flash popular and people get crazy about it. Flash is little bit complex but easy to use and easy to learn. Flash CS4: The Missing Manual by Chris Grover with E. A. Vander Veer shows you how to get started with Flash CS4. Using this book Beginners will learn to use the software in no time, and experienced Flash designers will improve their skills. To explore flash feature effectively this book is divided into 5 parts viz: • • • • •

Creating a Flash Animation Advanced Drawing and Animation Adding Interactivity Delivering your Animation to Its Audience Appendixes

Part 1 – Creating a Flash Animation introduces us with Flash CS4 IDE. In this part we get acquainted with the different parts of the Flash IDE Window: the stage and main work area, menus, toolbars, panel, timeline and more. We learn to use various tools provided by Flash CS4 and using them to draw some objects. Flash is all about animation. We are ready with our object and now we have to add life to it means we have to animate our drawing now. Here we deal with frames, keyframes, layers, Tweening, Morphing, and Motion Editor. What they are? How and Where to use them? This part covers well enough for beginners who never interact with Flash before to start designing and animating with Flash CS4. Part 2 – Advanced Drawing and Animation deals with Flash animation editing. Here we’ll learn to reorganize our animation with

98

cutting pasting frames, editing timeline, dealing with the layers, using tools for advancing drawing, playing with colors, technique to reuse animation elements and movie clips. In this part we get familiar with advance tools and features provided by Flash CS4. We deal with Advance Motion editor and Motion preset, generating realistic animation with Inverse kinematics (IK) using Bone Tool, importing media from other Adobe family products, dealing with video and sound. Part 3 – Adding Interactivity introduces power of ActionScript 3 from the basic usability of this Flash’s built in programming language. Using actionscript for drawing, Dealing with events, handle them to make animation perfect and full-fledged. Use flash’s built in components for interactive development. Work with Typefaces and fonts, Animating text with actionscript and formatting them with CSS. Part 4 – Delivering your Animation to Its Audience deals with testing and debugging of the work, Testing strategies and techniques for better testing to make our work error free, Optimizing it, publishing and exporting it for web as well as desktops. Part 5 – Appendixes contain installation process and additional resources to explore the Flash’s world in depth. Appendix B Flash CS4, Menu by Menu provides a good description of every command in each menu of Flash CS4. While reading you will interaction with small notes like Up to Speed, Design Time which explore the topic in-depth and provides refreshment while reading. Really this is a good book to cover all aspect and uses of Flash CS4

Conclusion: This is one of the best Introductory Flash CS4 books I would like recommend to new users. This book guides you all about development and designing with flash in an easy way. This book is nothing but a good missing manual for Flash CS4. by Chetankumar Akarte

01/2008 (1)




Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.