You are on page 1of 52

Editors Note

Dear Readers,
December is a special month for everyone. Before you fall into Christmas-shopping spree , check whats new in Flesh and Flex Developers Magazine. Lets start from the third part of Huw Collingbourne series .He explains how to create family trees of objects by creating class hierarchies. 3D world of Alternativa3D engine has many similarities with flat flash world as well as many differences, so why Yuri Malsev learns us what we shoud know about the Alternativa 3D Platform. Very interesting is also article based on chapter 6 of HTML5 in Action By Robert Crowther, Joe Lennon, and Ash Blue .With Canvas 2D Context, you have all the benefits of Flash and your games will run on mobile devices and without a plugin. Is Adobe still committed to Flash Builder? Will Adobe continue to support customers using Flex? This questions are from Gabor Csomak who wrote for us News about Flash Mobile. Last month we began our journey to the Design Patterns land with the Singleton Pattern. This month we will see the Factory pattern and how can you apply it to simplify our work when dealing to databases connections with Marco Pires. Have you ever thought of watching DVD movies performed by favorite actors on Android devices, such as Android phone, Samsung Galaxy Tab, Fascinate, HTC Desire, etc.? If yes, you shoul read a review of WinX DVD Ripper in our magazine. Becouse this is the last issue before a New Year I wish you all the best in 2012. Thanks to all readers, authors and betatesters who are very helpful. Merry Christmas and a Happy New Year for everyone! Enjoy your reading Adela Kuniarska and FFD Team

Editor: Adela Kuniarska adela.kuzniarska@software.com.pl Proofreaders: Garry Schafer, Michael Jovel,Alberto Jose Argon Alvarez, Nick Middleweek, Ranjan Rajendran, Ed Werzyn DTP Team: Ireneusz Pogroszewski ireneusz.pogroszewski@software.com.pl Art Director: Ireneusz Pogroszewski ireneusz.pogroszewski@software.com.pl Senior Consultant/Publisher: Pawe Marciniak Flex/ActionScript 101 Section Editor: Marc Pires marcpiresrj@gmail.com iPhone Development Section Editor: Ryan DAgostino ActionScript in Action Section Editor: Huw Collingbourne Games Section Editor: Chris Hughes Contributing Editors: Pedro de La Rocque, Ali Raza, Csomk Gbor Publisher: Software Press Sp. z o.o. SK ul. Bokserska 1 02-682 Warszawa Poland Worldwide Publishing If you are interested in cooperating with us, please contact us by e-mail: cooperation@software.com.pl 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. Thanks to the most active and helping beta testers: Russell TangChoon, Lee Graham, Jassa Amir Lang, Ed Werzyn, Yann SmithKielland, Justus, Csomk Gbor, Kevin Martin, Charles Wong, Ali Raza, Almog Koren, Izcoatl Armando Estanol Fuentes, Lionel Low, Michael J. Iriarte, Paula R. Mould, Rosarin Adulseranee, Sidney de Koning To create graphs and diagrams we used company. program by

Mathematical formulas created by Design Science MathType

Distributing current or past issues of this magazine without permission of the publisher is harmful activity and will result in judicial liability.

ATTENTION!

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.

DISCLAIMER!

12/2011 (30)

CONTENTS
InBrief
8 End of Flash Mobile
GABOR CSOMAK

Gabor Csomak answers the questions like- does Adobe recommended we use Flex or HTML5 for our enterprise application development? Is Adobe still committed to Flax and Flash Builder? Will Adobe continue to support customers using Flex? And much more in his news column go and read!

and without a plugin. In addition, one HTML5 Canvas application can be distributed across multiple platforms through mobile frameworks like PhoneGap.com. This article based on chapter 6 of HTML5 in Action, shows you how to create your first Canvas game, taking advantage of physics, advanced animation, and keyboard/mouse controls.

Alternativa3D
40 What is Alternativa3D
YURI MALTSEV

ActionScript in Action
10 Starting ActionScript Programming Part Three
HUW COLLINGBOURNE

In the third part of this series, Huw Collingbourne explains how to create family trees of objects by creating class hierarchies. You will learn how to create get/set accessor properties and calling superclass constructors.

AlternativaPlatform is a company, headquartered in Perm, Russia. It develops and supports technology solutions for browser-based multiplayer projects. Article from Youri Maltsev from who you will know what is Alternativa3D and how to get started with it.

Patterns Factory
46 Applied Design Patterns Factory
MARC PIRES

Framework For Storage3D


14 Proscenium As A Rapid Prototyping Framework For Stage3D
ARMANDO ESTANOL

Stage3d is a marvellous technology that allows many more digital artist to incoporate 3D into Flash. From this article you will get to know about the preview 1 version of the Proscenium framework and libraries for rapid 3D application development and how to make a small animation. You will also cover how the 3D rendering workflow goes on this framework. You should be familiar with programming as3 and finding your way in Flash Builder.

Marc Pires is a Developer located in Brazil, during his career, he has worked in various roles such as Network Administrator, Instructor. Last month we began our journey to the Design Patterns land with the Singleton Pattern. This month we will see the Factory pattern and how can you apply it to simplify our work when dealing to databases connections.

Review
50 WinX Free DVD Ripper
MASON

HTML5 in Action
28 Creating a Canvas Game
ROBERT CROWTHER, JOE LENNON, AND ASH BLUE

With Canvas 2D Context, you have all the benefits of Flash and your games will run on mobile devices

Have you ever thought of watching DVD movies performed by favorite actors on Android devices, such as Android phone, Samsung Galaxy Tab, Fascinate, HTC Desire, etc.? Ideal Solution for Appreciating DVD Movies on Android shows by a freelance writter Mason.

12/2011 (30)

Voices That Matter: Android Developers Conference


February 9-10, 2012 | San Francisco, Ca http://android2012.voicesthatmatter.com/

November 25, 2011 CONTACT: Lisa Comeau 941-224-1536 lisa@alphastarpartners.comt

Android Developers Conference Taught by the Industrys Leaders


SAN FRANCISCO, CA. Pearson Education, the worlds largest learning company introduces the premiere of the Voices That Matter: Android Developers Conference, taking place in San Francisco, February 9-10, 2012 at the Julia Morgan Ballroom. Both Google insiders and outside experts will discuss, demonstrate, teach and listen in a series of how-to sessions, application case studies and interactive panels, where attendees will learn all about Android and its latest SDK, called Ice Cream Sandwich. The Voices That Matter: Android Developers Conference will be an intimate, focused and informative event in which attendees will have the opportunity to learn from leading authors and practitioners, while networking with fellow developers. The conference program was developed by co-chairs and authors, Shane Conder and Lauren Darcey. This two-day conference will be discussing the latest and hottest trends in Android application development, covering everything in relation to development. From Succeeding in the Android Market, Game Programming, Understanding the UI Toolkit, to the breakdown of Ice Cream Sandwich: the latest Android SDK, Augmented Reality and many more. For beginner developers, Voices That Matters offers a pre-conference developer boot camp where attendees can learn the ins-and-outs from expert Android developers. To register, visit http://voicesthatmatter.com/android2012/register.aspx. Use Priority Code: ANDR923 to save $150 off the current conference price. Combine it with Early Bird pricing in effect through January 5, 2012, for a total saving of $350! The Pearson Education Voices That Matter Conference series are led by the top leaders in the industry and give attendees access to these experts. These intimate conferences are specifically designed to enable participants to share their experiences and leverage the accumulated wisdom of the entire conference community. For more information, please contact conference manager Barbara Gavin at Barbara.Gavin@Pearson.com or call (617) 848-7026.

12/2011 (30)

IN BRIEF

End of Flash Mobile

Adobe is discontinuing work on the mobile Flash Player. What this means in short is that Flash Player 12 will not come to Android. Also there wont be Flash Player for iOS, and Bada, nor Windows Phone. Unfortunatelly, the global media announced it as the end of Flash, and this has sapped the confidence of a lot of people, customers and developers alike. It is not true, Flash Player is on the 99% of desktop computers, and on the premium category Android phones and tablets, and also on BBX platform. Adobe will focus on AIR for Mobile, instead of Flash Player, because AIR is on all major platforms, and Flash Player is not, and couldnt be because of iOS. Flash Player will remain to develop expressive content (particularly games and video) in the browser on the desktop. Read the clarifications here: http:// www.mikechambers.com/blog/2011/11/11/clarificationson-flash-player-for-mobile-browsers-the-flash-platformand-the-future-of-flash/?utm_source=feedburner&utm_ medium=feed&utm_campaign=Feed%3A+MikeChamb ers+%28Mike+Chambers%29. Some of the questions:

continue making significant contributions to open web technologies like WebKit & jQuery, advance the development of PhoneGap and create new tools that solve the challenges developers face when building applications with HTML5.

Is Adobe still committed to Flash Builder?

Yes. Flash Builder will continue to be developed and Adobe will work to ensure Flex developers can use Flash Builder as their development tool with future releases of Flex SDK.

Will Adobe continue to support customers using Flex?

Yes. Adobe will continue to honor existing Flex support contracts.

So, whats next?

Is Adobe still committed to Flex?

Yes. We know Flex provides a unique set of benefits for enterprise application developers. We also know that the technology landscape for application development is rapidly changing and our customers want more direct control over the underlying technologies they use. Given this, we are planning to contribute the Flex SDK to an open source foundation in the same way we contributed PhoneGap to the Apache Foundation when we acquired Nitobi. This project will be jointly led by some developers from the Flex SDK engineering team along with key developers from the Flex community, including members of the Spoon Project and contributors from enterprise companies currently using Flex. Flex SDK feature development will continue under a new governance model and Adobe will continue to contribute to the Flex SDK.

We are close to wrapping up development on Flex 4.6 SDK and it will be released on November 29th 2011. Following this, we will begin the process of moving to the open development model described above. On a personal note, we recognize we could have handled the communication better and promise to share regular updates over the coming weeks and months. We believe these changes to the Flex SDK development model will ensure that the broader community can continue to use and directly enhance Flex for many years to come. source: Adobe Blogs

Sony AIR App Challenge Ended.

Here is the list of the winners, www.airappchallenge.com/ winners.php who proved the awesomness of Adobe AIR for mobile.

Does Adobe recommend we use Flex or HTML5 for our enterprise application development?

In the long-term, we believe HTML5 will be the best technology for enterprise application development. We also know that, currently, Flex has clear benefits for large-scale client projects typically associated with desktop application profiles. Given our experiences innovating on Flex, we are extremely well positioned to positively contribute to the advancement of HTML5 development, starting with mobile applications. In fact, many of the engineers and product managers who worked on Flex SDK will be moving to work on our HTML efforts. We will

The winner is a game: Tweet Hunt, Runner ups are Conqu, Conveyor, Kidoodle, Sylvesters Band, Level, and Cassandra Stand. Show these apps to everybody, to spread the good word for AIR.

News by Gbor Csomk (@csomak)

source: Adobe Blogs

12/2011 (30)

12/2011 (30)

ACTIONSCRIPT IN ACTION

part three

Starting ActionScript Programming


In the third part of this series, Huw Collingbourne explains how to create family trees of objects by creating class hierarchies.

What you will learn


How to create class hierarchies How to create get/set accessor properties Calling superclass constructors

What you should know


Basics of classes (see last months column) How to write ActionScript code in external les How to create objects from classes

n my last column, I explained some of the essential features of ActionScript Object Orientation. You might recall that I said that just about everything you use in ActionScript is an object. An object can be thought of as a container that wraps up both data (variables) and behaviour (functions or methods). Each object is defined by a class. You can think of a class as a sort of blueprint. Just as many individual cars can be constructed from a single car blueprint, so many ActionScript objects can be constructed from a single class. You could create a Car class that defines set of data (such as the size, colour and cost) and behaviour (its speed and fuel consumption) common to all cars. You would then be able to then create any number of separate car objects based on that class.

Class Hierarchies

Figure 1. A Simple Game Class Hierarchy Here the Thing class denes name and description. Both the Room and the Treasure class inherit name and description. The Treasure class adds on value. The Room class adds on directions: n, s, e, w

There is more to object orientation than creating objects from unrelated class definitions, however. The real power of object orientation resides in its ability to create related classes. So you might, for instance, create a generic Car class with wheels, colour and speed. Then you could create a new class, lets say a RollsRoyce class, as a descendent of the Car class. The RollsRoyce class automatically inherits all the features of the Car class so you dont have to program them all over again. But it also adds on a few new features such as, for example, a cocktail cabinet and leather upholstery (Im guessing here. Sad to say, I am not, in fact, a Rolls Royce owner). Lets look at another example. Lets assume you are programming a game of some sort. The game is full of all kinds of things including Treasures and Rooms. In other words, a Treasure is one type of Thing and a Room is another type of Thing. In order to write this in code I need to create a Thing class and make the Room and Treasure classes descend from it. Now I can code the behaviour of Things in general in the Thing class. The Treasure class will automatically inherit all the features of the Thing class, so I wont need to code those features all over again. The Treasure class will then add one or more additional features which are specific to Treasure objects for example, a value. The Room class will add features that are specific to Rooms for example, the exits at the north, west, east

10

12/2011 (30)

Starting ActionScript Programming

and south directions. You can see a plan of this class hierarchy in Figure 1. As a general rule, when creating a class hierarchy, the classes with the most generalised behaviour are higher up the hierarchy than classes with more specialist behaviour. So a Thing class which is relatively simple, having only a name and a description, is the ancestor of a Treasure class which is a bit more complex since it has a name, a description and, additionally, a value. The Thing class here is also the ancestor of the Room class which has a name, a description and exits in the four compass directions.

them. In ActionScript functions that use the word get after function can be used to return a value. Those that use set can be used to assign a value. The advantage of get/set accessors over regular functions is that they permit any code that wants to refer to the function name to do so using a syntax that is similar to that used when referring to variables. When you define private variables with public accessor methods, these may be called properties. So, to assign and retrieve a value to and from the name property you can write this:
var aName:String = thing1.name; TextArea1.text = aName;

Coding Classes in ActionScript

Now lets look at the actual code we need to write in order to create this class hierarchy. First, the Thing class (Listing 1). This defines two private variables, _name and _description and provides public get/set accessors for
Listing 1. The Thing Class
package { public class Thing { private var _name: String;

As explained last month, a function which has the same name as the class and the code file which contains the class, is called a constructor. It runs when a new object is created from the class and you may optionally add arguments to the constructor definition so that variables are assigned values whenever an object is created. thats what Ive done in the Thing constructor:
public function Thing( aName:String, aDescription:String ) { _name = aName; _description = aDescription;

private var _description: String; public function Thing( aName:String, aDescription:

_name = aName; }

String ) {

Listing 2. The Treasure Class descends from Thing


package { public class Treasure extends Thing { private var _value:Number; public function Treasure( aName:String,

_description = aDescription;

public function get name( ): String {

return _name;

public function set name( value: String ): void {

_name = value;

aDescription:String, aValue: Number ) {

super( aName, aDescription );

public function get description( ): String {

return _description;

_value = aValue;

public function get value ():Number {

public function set description( value: String ):

_description = value;

void {

return _value;

public function set value (value:Number):void {

} } }

_value = value;

} }

12/2011 (30)

11

ACTIONSCRIPT IN ACTION

When I want to create a descendent class, such as Thing I add the word extends to the class definition followed by the name of the classs ancestor or superclass. Here Treasure descends from Thing so Thing is the superclass of Treasure (Listing 2). This is how I indicate that fact in the definition of the Treasure class:
Listing 3. The Room Class also descends from Thing
package { public class Room extends Thing { private var _n:int; private var _s:int; private var _e:int; private var _w:int; public function Room( aName:String, aDescription:

public class Treasure extends Thing

So now the Treasure class inherits the name and description properties of its superclass, Thing. Notice that the Treasure constructor receives arguments called aName and aDescription but it doesnt assign these itself. Instead it passes these to the constructor of superclass by calling super() in this way:
super( aName, aDescription );

The Treasure constructor takes a third argument, aValue, which it cant pass to its superclass since the Thing class does not have a value property. Treasure assigns this to its own _ value variable:
_value = aValue;

String, nDir:int, sDir:int, eDir:int, wDir:int ) {

super( aName, aDescription );

_n = nDir; _s = sDir; _e = eDir; _w = wDir;

} } }

Listing 4. Creating Thing, Treasure and Room objects


private function init ():void { var thing1:Thing; var room1:Room; var room2:Room;

The Room class also descends from Thing. It too inherits name and description but it adds integer variables for the four directions (in a real game, these might refer to Room objects at given indexes in an array of Rooms). As I dont want the exits to change during the game play, I make the variables private and I dont provide any public accessors (Listing 3). So now I have the class hierarchy shown in the diagram (Figure 1). All that remains to be done is to create some objects from them. Refer to Listing 4 to see an example of this. One deficiency of my class hierarchy at this point is that I have created all the classes in the top-level disk directory of my application. In ActionScript the top level directory of the class is indicated by the fact that the class definition is enclosed between the keyword package and a pair of curly braces:
package { }

var treasure1:Treasure; var treasure2:Treasure;

thing1 = new Thing("a wotsit", "a vague thingummy" room1 = new Room( "the Troll Room", "a dank );

In a complex program, the top level directory would soon become pretty cluttered if all the source files were kept there. In next months column, Ill explain how you can organise your code into subdirectories and named packages.

room2 = new Room( "the Dragon's Lair", "a crystaltreasure1 = new Treasure( "emerald ring", "a encrusted cave", 2, -1, 4, 3 ); magical Elvish ring", 400 ); amulet of power", 1200 );

dungeon", -1, -1, 3, -1 );

HUW COLLINGBOURNE
Huw Collingbourne is Director of Technology at SapphireSteel Software. Over more than 20 years, he has programmed in languages ranging from Ruby to C# and has been a technical columnist for computer magazines such as PC Pro and PC Plus. He is the software lead of the Amethyst Designer, the Flex user interface design environment of the Amethyst IDE for Visual Studio. SapphireSteel Software: http:// www.sapphiresteel.com/

treasure2 = new Treasure( "golden amulet", "an }

12

12/2011 (30)

Bringing fresh AIR to UML

With this code you can buy Crocus Modeller license for as low as $34.3 Use the code at crocusmodeller.com/buy.html (you'll be asked for it just before checking out)
The code is valid until 2011-11-15 00:00:00 MST

CrocusModeller.com | Fresh AIR in UML

FRAMEWORK FOR STORAGE3D

Proscenium
As A Rapid Prototyping Framework For Stage3D
Stage3D is a marvellous technology that allows many more digital artists to incorporate 3D into Flash. Having GPU accelerated support; we are now able to create very complex scenes and animations without using the CPU or seeing a degradation of performance with very few elements on screen.
What you will learn
You will get to know about the preview 1 version of the Proscenium framework and libraries for rapid 3D application development and how to make a small animation. We will also cover how the 3D rendering workow goes on this framework. You will learn some things about 3D along the way. This will become the foundation to understand more complex projects under the Proscenium framework..

What you should know


You should be familiar with programming as3 and nding your way in Flash Builder.

ome 3D frameworks have been created over the years with the idea of giving 3D animation capabilities to Flash. While these were pretty well done, the CPU limitations were reached very early before our creative spirit had just started to explore. Stage 3D has come along with some new technologies to compensate for this, and the good news is that the time invested on many of those frameworks is not lost. Many classic 3D frameworks have been moved into Stage3D and are now available with more power than ever. I started looking at Stage 3D and some inner working basics. We now know how a basic Stage3D application is created to incorporate the GPU streamlined pipeline.

The pipeline requires a couple of data sets: one for vertexes describing our objects, and one for describing relationships between these vertexes, in order to conform the triangles that describe our 3D objects. A couple of AGAL programs (Vertex and Fragment Shader) are needed to modify the final look of our output. While knowing all of that is important to a deep understanding of what is really going into Stage3D, but there are times when we really need to pitch out a fast prototype, or when we just need to test a concept. Making a complete Stage3D implementation from square one is a time consuming task, while on the other hand, the same could go for a full framework

Figure 1. Proscenium setup sequence

14

12/2011 (30)

Proscenium As A Rapid Prototyping Framework For Stage3D

Figure 4. Adding the PLAYERGLOBAL variable to our project

Figure 2. Proscenium download folder structure

implementation. In this scenario, we need to have access to a fast and simple way to meet our goal. That solution is being worked by Adobe, and its name is Proscenium. That is, its code name, since it is still an Adobe Labs creation, so it is to be treated more as a proof of concept at this moment of time. Adobe even disclaims that it could not make it into a real product, so you can use it on your own, but I believe that for fast setups, it makes a great job. Proscenium is available at http://labs.adobe.com/ technologies/proscenium/ where you can download it. You must also take into consideration that if you are also intending to play with Pixel Bender 3D (which we will not cover by now), you must make a couple of additional downloads and installations, for the Pixel Bender 3D beta and the Pixel Bender SDK, which is needed by the first. Proscenium is a set of libraries that build on top of Stage3D and which are intended to make a fast start as a means to rapid development. The download package

contains the ActionScript 3 library files, a complete documentation (up to its current state), and a group of sample and tutorial codes to help you. If you want to dig a little more into build instructions, and more details of the current preview release of Proscenium, you can do it at http://labs.adobe.com/ wiki/index.php/Proscenium. To start with the development, there are three specific elements that should be installed in your system before Flex Builder is able to incorporate the Proscenium libraries in our projects. These are: Latest Flash Player Content Debugger (http:// www.adobe.com/support/flashplayer/downloads.html) Latest Video Drivers (available in ATI or NVidia site) In Windows, you should also check if you have the latest DirectX runtime (at Windows downloads site)

After installing these elements, we can now proceed to configure the last details inside Flash Builder. Under Windows > Preferences we will add variables to link the Proscenium and Pellet libraries, and the Flash Player Content Debugger version. Under General > Workspace > Linked Resources add a new PLAYERGLOBAL variable and search the copy of playerglobal.swc. Add a PROSCENIUM _ LIBS variable pointing to the libs folder that you downloaded.

As a last step, under Flash Builder > Debug select the copy of the Flash Player Content Debugger that you downloaded. There are some additional steps that should be done, for those of us who want to play with Pixel Bender 3D. We will not do those by now. The folder structure that is included in the Proscenium package download contains 4 folders:
Figure 3. Creating an ActionScript project

Code this includes 3 subdirectories for Proscenium tutorial files, ActionScript3 examples, and a Flex

12/2011 (30 )

15

FRAMEWORK FOR STORAGE3D

Figure 5. Adding the PROSCENIUM_LIBS variable to our project

example (which shows how it is easily integrated in an MXML application). Docs this contains the library documentation. Libs this contains the Proscenium library and the Pellet library for rapid prototyping and physics simulation on your application. Tools this has an empty Pixel Bender directory, used for Pixel Bender 3D support to extend the shaders available on Proscenium.

Figure 7. ActionScript Compiler settings

To start our way into the Proscenium framework, we must start a new Flash ActionScript project. You can also make a Flex project, but in our example we will exclude MXML programming to keep things simple. Select Next. In this next screen, we will add the environment variables that were configured early in the Flash Builder application. Add a new SWC and use the PLAYERGLOBAL variable to point to the playerglobal.swc file. If you are not allowed to continue (Ok is greyed out) check your variable name and take notice that it is between curly braces and not parenthesis.

Add a new SWC Folder (remember that it is a folder, because we have in it the Proscenium and Pellet libraries) and use the PROSCENIUM_LIBS variable. The project window should look like this now that we have included the SWC and SWC Folder: Figure 6. When Flash Builder has finished creating our new project, there is just a last step to configure, so we are able to use the Stage3D platform, which is the base for the Proscenium framework. Under the ActionScript Compiler settings, you must specify the swf-version=13 argument to the compiler. Remember to access the Properties of your project, by right clicking your mouse in your project on the Package Explorer window. Now everything is ready to build our first Proscenium application. I have planned a really small program that will help us understand the basic building blocks of the Proscenium library. The scene will show a plane, which will make as a ground reference. In that manner we will perceive better the 3D effect. The scene also consists of a camera, a couple of objects (a cube and a sphere) and a light. These are the very basic elements that a Proscenium application should contain. Making an analogy to the real word, we are putting a spectator, a point of interest and a light that will allow the spectator to observe the objects (just as in the real life, you would not be able to look to an object without a light).

Figure 6. Project congured for Proscenium framework usage

Figure 8. Basic scene elements

16

12/2011 (30)

Proscenium As A Rapid Prototyping Framework For Stage3D

Listing 1. General view of code


package{

// import calls
public class ProsceniumTest extends Sprite{

// define constansts and variables

public function ProsceniumTest():void{

// Setup Stage3D, Context3D and event handlers for content creation events

private function contextCreated( event:Event ):void{

// Setup Proscenium Instance3D object and animation event handlers // Call camera, lights and object creation functions

private function setCamera():void{

// Setting up the camera

private function setObjects():void{

// Setting up the scene with some objects

private function setLight():void{

// Setting up the light

private function resizeMe(event:Event=undefined):void{

// Event handler for resizing of flash movie

protected function animationLoop(event:Event):void{

// Here we change the objects position and send new image to screen

private function contextCreationError(error:ErrorEvent):void{

// Output error information

private function resize(width:int,height:int):void{

// Configure the video buffer memory to display our viewport

Figure 9. Program ow

12/2011 (30 )

17

FRAMEWORK FOR STORAGE3D

These elements will have certain attributes associated to them. This will help us to describe their position, colour, material, intensity, etc. Our example will be based on a simple flow and the Tutorial #5 that comes with the Proscenium library
Listing 2. Metadata for our Flash movie
[SWF(width="640",height="480",backgroundColor="0x333 333",frameRate="125")]

Listing 3. Constants for the 3D world and animation


private const ORIGIN:Vector3D=new private const CAM_ORIGIN:Vector3D=new private const AMPLITUDE:Number=3.5;

Vector3D();

Vector3D(0,0,20);

Listing 4. The basic 3D objects in this Proscenium example


private var myS3D:Stage3D;

private var myProsceniumInstance3D:

Instance3D;

Listing 5. Main objects declaration


private var myCamera:SceneCamera;

private var myMainLight:SceneLight; private var myCubeObject:SceneMesh; private var mySphereObject:SceneMesh; private var myPlaneObject:SceneMesh; private var myMaterial:MaterialStandard;

package. We will setup our Stage3D object as usual, and then we will incorporate our basic elements (camera, objects and light) to the scene. There are a couple of event handlers to support resizing the screen, to avoid object distortion. The other handler is for the frame event, and it will be used to create the main animation loop cycle. The animations that the objects execute are sine and cosine based movements along a couple of axis for both objects. It demonstrates how you can manipulate elements inside the scene. The general schematic of the code flow looks is shown on the following diagram. The code structure is represented in the following Listing 1. There is an important library that is included in our demo program. The scenegraph library, which gives support to the Proscenium framework, contains all that we need to play with it. We include a small metadata before our class just to test our application out of the browser with an initial VGA sized screen and define its background colour. We must also change the Project properties under the ActionScript Compiler section. Just remove the tick from the Generate HTML Wrapper file setting. This will just publish the swf file and play it on the standalone Flash Player. We start by defining inside of our class some constants and variables needed to define things in our program. The first group consists of the constants that declare the relative origin of our 3D world. This position defined as (0,0,0) will become the absolute position to

Listing 6. Constructor function


public function ProsceniumTest():void{

ode.NO_SCALE; _LEFT;

this.stage.scaleMode=StageScaleM this.stage.align=StageAlign.TOP

Figure 10. A point light is a distant light far in the distance


myS3D=stage.stage3Ds[0]; myS3D.x=10; myS3D.y=10;

TEXT3D_CREATE,contextCreated); t.ERROR,contextCreationError); RenderMode.AUTO);

myS3D.addEventListener(Event.CON

myS3D.addEventListener(ErrorEven

myS3D.requestContext3D(Context3D

Figure 11. Showing append versus prepend

18

12/2011 (30)

Proscenium As A Rapid Prototyping Framework For Stage3D

which our 3D objects will be relative to. We then declare the camera origin point 20 units above the ground level (again, relative to the absolute virtual world origin). And finally, the amplitude will define how far our objects will travel in distance. Try playing with this variable to see our objects move farther or closer from their initial position. Since we will be working with Proscenium as a framework over Stage3D technologies, then we must initialize an Stage3D object and an Instance3D which will receive the Stage3D Context3D requested later, to work with it. We need 3 basic elements to visualize anything on our virtual world: a camera, an object to be seen and light to be able to see it. This is what makes a great
Listing 7. Context3D request is successful

difference between using Proscenium and Stage3D directly. In Stage3D, we must worry about the inner workings of the 3D render pipeline. But under Proscenium framework, we are proposed a more natural 3D environment. These objects will have several attributes associated with them. Some more specialized, like the material of our objects on scene, which is only an attribute of this kind of objects and is not shared with the camera, or the intensity that only applies to lights. But some are common to the three of them, and these are the 3 main transform attributes: translation, rotation and scaling. These are the only 3 operations that you can make to a 3D object and become the first thing you know when using a 3D program. It is important to have

private function contextCreated( event:Event ):void{

myProsceniumInstance3D=new Instance3D(myS3D.context3D); resize(stage.stageWidth,stage.stageHeight); stage.addEventListener(Event.ENTER_FRAME,animationLoop); stage.addEventListener(Event.RESIZE,resizeMe); setCamera(); setLight(); setObjects();

Listing 8. Setting up the camera


private function setCamera():void{

myCamera=myProsceniumInstance3D.scene.activeCamera; myCamera.identity(); myCamera.position=CAM_ORIGIN;

myCamera.appendRotation(-15,Vector3D.X_AXIS); }

myCamera.appendRotation(-25,Vector3D.Y_AXIS,ORIGIN);

Listing 9. Creating objects for our scene


private function setObjects():void{

myPlaneObject=MeshUtils.createPlane(50,50,20,20,null,"plane"); myPlaneObject.transform.appendTranslation(0,-2,0); myProsceniumInstance3D.scene.addChild(myPlaneObject); myCubeObject.appendTranslation(0,3,0);

myCubeObject=MeshUtils.createBox(8,2,12,null,"cube"); myProsceniumInstance3D.scene.addChild(myCubeObject); myMaterial=new MaterialStandard;

mySphereObject=MeshUtils.createSphere(4,32,32,myMaterial,"sphere"); mySphereObject.appendTranslation(4,10,0); } myProsceniumInstance3D.scene.addChild(mySphereObject);

myMaterial.diffuseColor.set(.8,.2,.3);

12/2011 (30 )

19

FRAMEWORK FOR STORAGE3D

this in mind, since we will be using it later when we make our animation. In our example, we will have 1 camera (our main camera), 1 light (our main illumination source) and 3 objects. These 3 objects will be a simple plane, a slanted cube or box and a sphere. The plane will simulate the ground level and will serve as a reference
Listing 10. Creating light and adding shadows
private function setLight():void{

object for the viewer to help his brain into creating a more efficient 3D effect. The box and the sphere will be moving along some sinusoidal paths to create a simple animation. The camera will represent our virtual position in the 3D world. It will contain some other properties that are the counterparts of its physical optical equivalent, like

myMainLight.appendTranslation(-20,20,20); myMainLight.kind="distant"; myMainLight.transform.prependRotation(-45,Vector3D.Y_AXIS); myMainLight.shadowMapEnabled=true;

myMainLight.color.set(.5,.5,.5);

myMainLight=new SceneLight();

myMainLight.transform.prependRotation(-70,Vector3D.X_AXIS);

myMainLight.setShadowMapSize(256,256);

myMainLight.addToShadowMap(mySphereObject);

myMainLight.addToShadowMap(myCubeObject);

myProsceniumInstance3D.scene.addChild(myMainLight);

Listing 11. Event handler for resizing stage action


private function resizeMe(event:Event=undefined):void{

resize(stage.stageWidth,stage.stageHeight);

Listing 12. Main animation loop


protected function animationLoop(event:Event):void{

myCubeObject.setPosition( 2,

AMPLITUDE*Math.cos(2*getTimer()/10000), AMPLITUDE*Math.sin(15*getTimer()/10000));

mySphereObject.setPosition(

AMPLITUDE*Math.cos(3*getTimer()/10000), 0);

AMPLITUDE*Math.sin(8*getTimer()/10000),

/*

myProsceniumInstance3D.render(0,false);

myMainLight.shadowMap.showMeTheTexture( myProsceniumInstance3D, myProsceniumInstance3D.width, myProsceniumInstance3D.height, 0, 0, 200); */ } myProsceniumInstance3D.present();

20

12/2011 (30)

Proscenium As A Rapid Prototyping Framework For Stage3D

the aspect ratio. The light is necessary to allow us to look at the objects. Unlike its physical counterpart, the virtual lights work in an inverse direction. Light normally comes out from its source, travels in a media and hits the object. The resultant bouncing light hits our eyes and makes the impression of figures, colours and textures on them. The virtual light system generates a ray coming from the camera position and into every relative pixel position direction on the screen. That is, it asks what my eyes are seeing in each pixel position. When those rays hit an object, they bounce and continue their trajectory until they hit further objects and bounce again (seen as reflections) or they hit a light. Of course, this could be an unending task, so our virtual rays are limited by number of bounces or distance. The resulting shade of colour on screen is the output of how material properties on the objects affect the direction our rays bounce and the properties of our light. The light object that we will use on this example is called distant. A distant light source has all its rays perceived as parallel to each other. For example, the Sun emits its rays from a point source and they go out in every direction from out of its surface. But those rays that hit the Earth have travelled so far that it appears to us as if those rays are parallel. In our 3D world the distant light source type has real parallelism on its rays. We will also declare an additional object of MaterialStandard type. This will be used to give the sphere a different look to differentiate it from the other objects in the scene which will use the default material. Under the constructor function we setup the general scene attributes, to make our Flash scene not to scale when it is resized. This setting will be used in conjunction with the resize event handler to control how our 3D scene looks and to avoid distortions. We have to obtain the first Stage3D object from the Stage as usual, and we position its viewport 10 pixels down and to the right. The idea behind this is to take
Listing 13. Error output

the illusion that our 3D scene needs to have just one viewport occupying the entire screen. We need 2 event listener functions before we request our Context3D object. One will listen to the success in 3D context creation; the other one is in place to catch any error during the procedure. This could happen if the GPU is in use by another application and has no resources available. When the requested Context3D object is created we need to use it to create an Instance3D object. This will be our entry point to the Proscenium framework. We will have to use a custom made resize function that will be explained later. Its function will be to setup our 3D scene with the correct aspect ratio, according to the current Stage size. The function ends by calling the 3 main functions that are in charge of setting up the main elements of our 3D scene. The setCamera function is in charge of getting the active camera from the Proscenium Instance3D object. It then positions it with a clear matrix, through the identity function. Setting objects on our scene will require the use of the MeshUtils library. We will use the createPlane, createBox and createSphere functions. We will be assigning a name to each object just to identify them, but these names will not be used by our program. We will append a translation to each object, to position them before adding them to the scene through the Instance3D object. Before creating the sphere object, we will create a MaterialStandard object, which will allow us to create a new material with a reddish colour. This material is then assigned to the sphere when we create it. The other two objects are assigned a null material, which means that they will use the default material. We need a light source in order to view anything that is on our 3D scene. We create it by using a SceneLight object with a grey colour. By appending a translation vector, we position our light in the scene.

private function contextCreationError(error:ErrorEvent):void{

trace(error.errorID+": "+error.text);

Listing 14. Taking care of aspect ratio and video buffer size
private function resize(width:int,height:int):void{

myProsceniumInstance3D.scene.activeCamera.aspect=width/height; } myProsceniumInstance3D.render();

myProsceniumInstance3D.configureBackBuffer(width,height,2,true);

12/2011 (30 )

21

FRAMEWORK FOR STORAGE3D

Listing 15a. Complete source code with comments


package

private var myCubeObject:SceneMesh;

// We import Proscenium namespace to access its libraries


import com.adobe.scenegraph.*; import flash.display.*; import flash.events.*; import flash.geom.*; import flash.utils.*;

private var mySphereObject:SceneMesh;

// Proscenium allows us to create a standard material with ease


private var myMaterial:MaterialStandard; public function ProsceniumTest():void

private var myPlaneObject:SceneMesh;

import flash.display3D.*;

// Standard Stage management in Flash e.NO_SCALE; LEFT;


this.stage.scaleMode=StageScaleMod this.stage.align=StageAlign.TOP_

// This metadata tag is used to control // // // swf movie size, VGA in this case html page background color (medium gray for our example) frame rate (try this as a performance indicator) [SWF(width="640",height="480",backgroundColor=" 0x333333",frameRate="125")]

// We work with the lowest Stage3D object on the display stack and position it // This will leave our viewport slightly moved down and to the right // It just demonstrates the viewport versatility myS3D=stage.stage3Ds[0]; myS3D.x=10; myS3D.y=10; // Create 2 event handlers for success and error on content creation // We then request a Context3D surface for our Stage3D screen XT3D_CREATE,contextCreated); ERROR,contextCreationError); nderMode.AUTO); myS3D.addEventListener(Event.CONTE

// We extend the Sprite class to gain more control with sprites on Stage
public class ProsceniumTest extends Sprite

// We need a relative origin point in space for all our 3D elements


private const ORIGIN:Vector3D=new private const CAM_ORIGIN:Vector3D=new

Vector3D();

// This const controls how far objects move


private const AMPLITUDE:Number=3.5;

Vector3D(0,0,20);

// We declare our basic Stage3D element // We need an Instance3D element // Compare this with the Context3D that is used without Proscenium
private var myProsceniumInstance3D: private var myS3D:Stage3D;

myS3D.addEventListener(ErrorEvent.

myS3D.requestContext3D(Context3DRe

Instance3D;

// Beware, Adobe warns that context3DCreate event can happen at any time, // such as when the hardware resources are taken by another process // These function is executed if there is no problem with assigning a 3D context
private function contextCreated( event:

// To create a scene we need these minimum requirements // // camera - our eyes in the virtual world lights - if the room is dark you cannot see // objects - there must be something to view
private var myCamera:SceneCamera; private var myMainLight:SceneLight;

Event ):void

22

12/2011 (30)

Proscenium As A Rapid Prototyping Framework For Stage3D

Listing 15b. Complete source code with comments


// We ask for a 3D context and pass it into the Proscenium instance object e3D(myS3D.context3D); myProsceniumInstance3D=new Instanc // This function call initializes resize(stage.stageWidth,stage.sta // We add the event handlers objects // // // // to it // We position it relative to the origin e(50,50,20,20,null,"plane"); slation(0,-2,0); // myPlaneObject=MeshUtils.createPlan myPlaneObject.transform.appendTran We finally add it to our scene A plane used as a ground The plane will be 50x50 units subdivision in the U and V We do not assign a material reference to the viewer in size, and will contain a 20x20 coordinates

our viewport and camera settings geHeight);

necessary to create the animation and give // support to changes on the viewport size _FRAME,animationLoop); E,resizeMe); stage.addEventListener(Event.ENTER

stage.addEventListener(Event.RESIZ

ild(myPlaneObject); // // something to show

myProsceniumInstance3D.scene.addCh A simple cube just to have We position it relative to

// We need to setup camera, lights, objects setCamera(); setLight(); setObjects();

the origin ,2,12,null,"cube"); 3,0); // myCubeObject=MeshUtils.createBox(8

myCubeObject.appendTranslation(0, We finally add it to our scene

// Here we setup the camera attributes {


private function setCamera():void

// Setting up the camera // We need to select the active camera in our scene ene.activeCamera; // myCamera=myProsceniumInstance3D.sc We set the camera transform

ild(myCubeObject); // //

myProsceniumInstance3D.scene.addCh Our next object will have a We use a standard material

different material assigned with a redish color myMaterial=new MaterialStandard; ,.3); // // myMaterial.diffuseColor.set(.8,.2 A simple sphere just to have We position it relative to

matrix to an identity matrix myCamera.identity(); // // The relative position of the (x,y,z) relative to (0,0,0)

something to show the origin ere(4,32,32,myMaterial,"sphere"); 4,10,0); // mySphereObject=MeshUtils.createSph mySphereObject.appendTranslation( We finally add it to our scene

camera to the virtual world origin myCamera.position=CAM_ORIGIN; 15,Vector3D.X_AXIS); myCamera.appendRotation(-

25,Vector3D.Y_AXIS,ORIGIN);

myCamera.appendRotation(-

// Here we setup the objects that configure our 3D scene {


private function setObjects():void

ild(mySphereObject);

myProsceniumInstance3D.scene.addCh

// Here we setup the light attributes


private function setLight():void

// Setting up the scene with some

12/2011 (30 )

23

FRAMEWORK FOR STORAGE3D

Listing 15c. Complete source code with comments


// Setting up the light // // Since this is a demo light we point light, not named and use the default parameters with no id myMainLight=new SceneLight(); // We use a medium gray in (r,g,b) format // The intensity of the light is a 100% alpha default level // myMainLight.color.set(.5,.5,.5); The relative position of the } 256); // myMainLight.setShadowMapSize(256, We finally add it to our scene

ild(myMainLight);

myProsceniumInstance3D.scene.addCh

// Since our lights emit shadows, // render node

we add our objects to the shadow myMainLight.addToShadowMap(myCube myMainLight.addToShadowMap(mySphe

Object);

light to the virtual world origin 20,20,20); // // // // rays // // // // // myMainLight.kind="distant"; We must prepend the rotation This is to operate this in the stack of It is important to remember transformations affects the myMainLight.appendTranslation(To cover all the scene, we This is similar to the light that the distance of the light emits parallel light

reObject);

// This event handler calls the resize function


private function resizeMe(event:

change the light type to distant of the sun, since we assume light is far away, this kind of

Event=undefined):void

geHeight);

resize(stage.stageWidth,stage.sta

// Here goes the code needed on your main program loop


protected function animationLoop(event:

to the light. transformations before any other transformations that the order of the final result in 3D ion(-45,Vector3D.Y_AXIS); myMainLight.transform.prependRotat myMainLight.transform.prependRotat // // // // // // // We want this light to emit The shadow map size is the render budget and The shadow map size must be A number too low and your A number too high and you resources

Event):void

// Here we change the objects position to generate an animation // // by using the time since sine and cosine equations Flash started as an input to // We use AMPLITUDE constant to control how far the objects move myCubeObject.setPosition( er()/10000), 2, AMPLITUDE*Math.cos(2*getTim

ion(-70,Vector3D.X_AXIS); shadows

important, because it afects on consumes GPU memory resources set in powers of 2 shadows will look squary will consume huge amounts of myMainLight.shadowMapEnabled=true;

mer()/10000));

AMPLITUDE*Math.sin(15*getTi

mySphereObject.setPosition(

AMPLITUDE*Math.sin(8*getTimer()/10000), 0);

er()/10000),

AMPLITUDE*Math.cos(3*getTim

// We need to clear and generate the 3D image // This is the first call, but it will be called each time the screen

24

12/2011 (30)

Proscenium As A Rapid Prototyping Framework For Stage3D

Listing 15d. Complete source code with comments


// is resized // We do not call the "present" function (we pass the false parameter) // we // are allowing to show the light shadow map before showing on screen
alse); private function resize(width:int,height:

int):void

// We set aside the video buffer memory to display our viewport kBuffer(width,height,2,true); myProsceniumInstance3D.configureBac

so we can insert additional

data over the image. In this case,

// We adapt the aspect ratio of

our camera in the viewport to its current size eCamera.aspect=width/height; myProsceniumInstance3D.scene.activ

myProsceniumInstance3D.render(0,f

// The following function renders the shadow buffer texture on screen /* myMainLight.shadowMap.showMeTheTe xture( myProsceniumInstance3D, myProsceniumInstance3D.wi dth, myProsceniumInstance3D.he ight, 0, 0, 200); */ // Here we transfer the 3D scene to the screen after the shadow map is // } overlayed myProsceniumInstance3D.present(); } } }

// We need to clear and prepare the image generated // By default it calls the "present" function to show the scene on screen myProsceniumInstance3D.render();

// There are sometimes when we get a 3D context creation error // Maybe some other program is accesing the GPU
private function contextCreationError(error

:ErrorEvent):void

"+error.text);

trace(error.errorID+":

// This function is in charge of arranging the necessary procedures to // setup our scene in the GPU and gives support to a resizing scenario

12/2011 (30 )

25

FRAMEWORK FOR STORAGE3D

The type of light will be distant. This will allow us to have a homogeneous source of light that will affect all of our objects in the same manner, independent of the light position. The rotation is prepended in order to execute this transformation before any other. In this case, the rotation is executed before the translation. In this way, we rotate the light in its centre and then translate it. Otherwise, the light would be moved first, and the rotation would have been executed over its original centre, giving an additional translation effect. The effects of this can be seen on the following graphic, where the difference can be seen with a different position on the resulting square after applying a prepended rotation and an appended rotation. We enable the shadow map, which is a texture rectangle that represents and projects the shadow of the objects, as seen by the light. The size of it determines the resolution of the shadow casted by the light. Normally, you would want to give this texture as much resolution as you can. The problem is that it affects directly on the lighting budget. That is, it consumes resources that might affect how many other lights, textures and shaders could be used on your scene before some are excluded or the performance is adversely affected. The shadow map is preferably used with measures that are a power of 2 (256,512, 1024, etc). This is because some GPU operations execute faster and we avoid using extra operations, which again, might go against our real time execution budget. Remember that a shadow map is nothing else than a rectangular texture projected from the light source point of view. After declaring that our light will use a shadow map, we have to add the list of objects that will be taken into account when calculating such a map. The resizeMe event handler calls out custom resize function with the current stage height and width parameters. The main function for this example program is the animation loop, which is the frame entered event handler. In this function we take care of animating things a little. Here we change the position according to some sinusoidal curves, so that our objects come back to their original position cyclically. We make use of the AMPLITUDE constant that we can change on the source code to make this movement broader or narrower. When the position of the objects is changed, we then call the Proscenium render function, but we pass the false parameter so that present is not called yet. We do this to have the opportunity to alter in some manner the image present on the 3D buffer, before it gets into the video buffer. This could be to apply some kind of 2D post effect or filter like bloom, glow or blur. In our example, we did this to give space to overlay

the shadow map over our image. We then proceed to use the Proscenium present function to copy the final image into the video buffer, so the user can see the final image. If anything goes wrong with the Context3D object creation, we need to know for debugging purposes. This is our custom resize function. In here, we take care of reconfiguring our video back buffer, with the new size of our screen and correct aspect ratio. This will take care of any distortion introduced by the resizing of the screen. As a last step, we proceed to render and present this new generated image. Of course, this function would not be necessary if we did not want to implement a full screen viewport. As we have seen, the Proscenium framework has allowed us to simplify the creation of a simple scene with animation. In contrast to the manipulation of vertexes and triangles that was necessary with the pure Stage3D technology. There is also the Vertex Shader and Fragment Shader assembly lines of code, that, even with the miniassembler utility, were complex to achieve to the entry level programmer. The abstraction into a camera, object and light model allow us to reach farther with more or less the same code lines. There are more powerful capabilities to explore in the framework, such as the loading of standard 3D object formats, such as Collada, or OBJ. We can also use the Pellet libraries to achieve some simple object collision and other physics based effects. These are a few to name some, but the possibilities of Proscenium as a rapid development library are really exciting. Of course, there will be some occasions when Proscenium will not be fit for the task, but this is only a preview version and will require some time to mature. Although, we must also have in mind that as Adobe mentions, this library could end up just as some kind of curiosity if something better comes abroad. The entire code, with my comments, follows: Listing 15.

IZCATL ARMANDO ESTANOL FUENTES


Izcatl Armando Estanol Fuentes is labouring at Universidad La Salle, Mxico as the IT Service Delivery Chief. He is passionate about his family, 3D and Flash animation, lm making and technologies applied to education. You can nd him around having a good time with his family, researching or making VFX for BYP UK. Contact: iaef@ulsa.mx

26

12/2011 (30)

HTML5 IN ACTION

HTML5 in Action
Excerpted from

HTML5 in Action By Robert Crowther, Joe Lennon, and Ash Blue With Canvas 2D Context, you have all the benefits of Flash and your games will run on mobile devices and without a plugin. In addition, one HTML5 Canvas application can be distributed across multiple platforms through mobile frameworks like PhoneGap.com. This article based on chapter 6 of HTML5 in Action, shows you how to create your first Canvas game, taking advantage of physics, advanced animation, and keyboard/mouse controls. You may also be interested in

For Source Code, Sample Chapters, the Author Forum and other resources, go to www.manning.com/crowther2

Creating a Canvas Game

n the past, youd develop browser games like Breakout, shown in Figure 1, through Flash. While Flash runs across all browsers, support is terrible on mobile devices, plus it requires a plugin. Now, with Canvas 2D Context, you have all the benefits of Flash, and your games will run on mobile devices and without a plugin. In addition, one HTML5 Canvas application

Listing 1. Default JavaScript


var canvas = document.getElementById(canvas); var canvasAtt = canvas.attributes; var canvasW = canvasAtt.getNamedItem(width).value; var canvasRun;

var canvasH = canvasAtt.getNamedItem(height).value;

if (canvas.getContext){

var context = canvas.getContext(2d);

background();

function background() { var img = new Image();

img.src = background.jpg; context.drawImage(img,0,0);

Figure 1. Breakouts objective is to bounce a ball via paddle to break bricks. When the ball goes out of bounds the game shuts down. You can play the game now at html5inaction.com and download all the les needed to complete your own Breakout game from manning.com

28

12/2010 (30)

HTML5 in Action

can be distributed across multiple platforms through mobile frameworks like PhoneGap.com. Your first Canvas game will take advantage of physics, advanced animation, and keyboard/mouse controls. While physics and advanced animation may sound scary, no prior knowledge is necessary, and well walk you through each step of the way. Before you create Breakout, download the HTML5 in Actions complimentary files from manning.com. From html5inaction.com you can test-drive the game and see all the cool features. For the rest of this article youll inflate a ball, carve a paddle, lay down the bricks, and then bring it all together. But first, you need to lay down the foundation setting up your file and Canvas. Lets get started!
Listing 2. Ball creation
var ballX; var ballY; var ballR; if (canvas.getContext){

Listing 3. Paddle creation


var padX; var padY; var padW; var padH; var padR; if (canvas.getContext){

var context = canvas.getContext(2d);

background(); ballInit(); ballDraw(); padInit();

#A #A

padDraw();

function padInit() {

var context = canvas.getContext(2d);

padX = 100; padY = 210; padW = 90; padH = 20; padR = 9;

background(); ballInit();

ballDraw();

function ballInit() {

ballX = 120; ballY = 120; ballR = 10;

#B

function padDraw() {

context.beginPath();

context.moveTo(padX,padY);

context.arcTo(padX+padW, padY, padX+padW, context.arcTo(padX+padW, padY+padH,padX+padW#C padY+padR, padR);

#A

function ballDraw() {

context.beginPath();

context.arcTo(padX, padY+padH, padX, padY+padHcontext.arcTo(padX, padY, padX+padR, padY, padR); context.closePath(); context.fill(); context.fillStyle = padGrad(); } #B padR, padR);

padR,padY+padH, padR);

context.arc(ballX, ballY, ballR, 0, 2 * Math.PI, context.fillStyle = ballGrad(); } context.fill();


false);

function ballGrad() {

var ballG = context.createRadialGradient(ballX,b

function padGrad() {

ballG.addColorStop(0, #eee); ballG.addColorStop(1, #999); }


return ballG;

allY,2,ballX-4,ballY-3,10);

var padG = context.createLinearGradient(padX,pad

padG.addColorStop(0, #eee);
return padG;

Y,padX,padY+20);

padG.addColorStop(1, #999); }

#B Initial setup

#A Sets the paddles spawn origin

#C Animates the object

#B Closing paths can prevent buggy behavior

12/2010 (30)

29

HTML5 IN ACTION

Set up the games HTML in a file called breakout.html and make the <canvas> tag 408 by 250 pixels so theres lots of room to work with. After that add an inline style to center everything:
<body style=text-align: center>

The Foundation

Listing 4. Brick array creation


var bricks; var bGap; var bRow; var bCol; var bW; var bH; if (canvas.getContext){

<canvas id=canvas width=408 height=250> </canvas> Download FireFox to play this game now!

<script type=text/javascript src=game.js></ </body> script>

var context = canvas.getContext(2d);

background(); brickInit(); brickDraw(); ballInit(); ballDraw(); padInit();

Next, create and point to a new JavaScript file called game.js (show in Listing 1). With a solid HTML setup, you can use the DOM to collect default variables to speed up game development. Youll find these variables useful when retrieving the <canvas> width and height for calculating equations. In addition, lay down a simple background image that takes up the whole play area.

padDraw();

Inflating a Ball

Instead of leaving the balls background plain, use a gradient to add some interest. The catch is you have to dynamically generate the gradient at the balls position. Otherwise, the gradient wont follow the object when animated.

function brickInit() {

bGap = 2; bRow = 3; bCol = 5; bW = 80; bH = 15;

Carving a paddle

To create a paddle follow, listing 3 to combine four arcs into a pill shape. TUse arcTo(x1,y1,x2,y2,radius), which allows circular shapes to be created as part of a path for an object. In addition, add a gradient like the ball, except add a linear version with createLinearGradient (x1,y1,x2,y2).

bricks = new Array(bRow);


for (i=0; i<bRow; i++) {

bricks[i] = new Array(bCol);

#A

#A

#A

function brickDraw() {

for (i=0; i<bRow; i++) {

for (j=0; j<bCol; j++) {

#B

if (bricks[i][j] !== false) {

#B

context.fillStyle = blue; bW,bH); #1

#B

context.fillRect(brickX(j),brickY(i),

#A Array creation loop

#B Array execution loop

Figure 2. With a total of 4 gaps at 2px each. The totaling 8px needs to be subtracted from the <canvas> width leaving 400px. Distribute the remaining width to each brick, leaving 80px for each (400px / 5 bricks = 80px)

30

12/2010 (30)

HTML5 IN ACTION

Laying Down Bricks

To get the width for each brick, youll need to do some calculations. Since you have 5 bricks with a total of 4 gaps that need spacing, place a 2px gap between each brick to take up a total of 8px (4 gaps x 2px). Remove the 8px from the 408px Canvas width for a total length of 400px. Since 5 bricks need to fit inside the remaining width, youre looking at 80px per brick (400px / 5 bricks = 80px). Want to use 9 bricks instead? Youll have to remove the 8 2px gaps from the width, then adjust the <canvas> width to a number thats perfectly divisible by 9 bricks. If you dont adjust the width, youll end up with a decimal that offsets your Breakout game. Having trouble following our logic? Look at the diagram in figure 2 for a visual explanation. Bricks could be placed by rewriting a basic shape command over, and over, and over. Instead, create a two dimensional array as seen in listing 4 to hold each bricks row and column. To lay down the bricks, loop through the array data and place each according to its row and column. While outputting the bricks, you need to be specific about the x and y coordinates. Add two functions (#1) to handle the column and row setup with the following code snippet.
Listing 5. Coloring bricks
function brickColor(row) { var brickG = context.createLinearGradient(0,y,0,y+bH); switch(row) { case 0:

function brickX(row) { }

return (row * bW) + (row * bGap);

function brickY(col) { }

return (col * bH) + (col * bGap);

Since the brick placement is taken care of, why dont you make them a little more colorful? Change up the graphics by coloring each brick based upon its row via a switch statement. In order to make listing 5 function correctly, replace context.fillStyle = blue; with context.fillStyle = brickColor(i);, otherwise the color wont change.

Assembling a Static Game

Since you just wrote a lot of code make sure the draw() and init() functions look identical to Listing 6. Your JavaScript file should be structured so variable declarations reside at the top, all object initialization function placed inside init(), and all draw functions placed inside draw(). Doing so will properly prepare objects to be animated and interacted with in the next section. Before proceeding, make sure that your current progress is identical to Figure 3.

brickG.addColorStop(1,#9604c7); break;

brickG.addColorStop(0,#bd06f9);

#A

#A

brickG.addColorStop(1,#c7043b); break;

case 1: brickG.addColorStop(0,#F9064A);

#B

#B

brickG.addColorStop(1,#04c711); break;

case 2: brickG.addColorStop(0,#05fa15);

#C #D

#C

} }

brickG.addColorStop(1,#c77f04); break;

default: brickG.addColorStop(0,#faa105);

#D

return context.fillStyle = brickG;

#A Row 1 red

#B Row 2 purple #C Row 3 green #D Row 4+ orange

32

12/2010 (30)

HTML5 in Action

So far in this game development journey, youve created all the core pieces of Breakout. Because nothing moves, the game is as useless as a rod without a reel. Next, well teach you how to bring your games static design to life!

Listing 6. HTML5 game coding template


if (canvas.getContext){

var context = canvas.getContext(2d);

Breathing Life Into Breakout

Currently your game looks really cool, but it doesnt do anything. Pulling out several different tools from our JavaScript and Canvas toolbox well show you how to get your new objects running. In fact, well even show you how to integrate physics, and move the paddle with a controller. Now, that youve created all the needed objects and divided code into init and draw functions, its time to begin animating. Your moving objects will be visible, but you wont be able to control them via keyboard and mouse until you work through the collision and controller setup in the following sections. Before we get started, you need to animate Canvas objects by adding return canvasRun = setInterval(draw, 12); to the end of the init() function. Its imperative you add the following code snippet at the end so it fires after all the initialization functions have setup their default properties. Now, youre ready to begin. First, lets make the paddle move from left to right. Next, well make the ball move diagonally.

init();

function init() {

brickInit(); ballInit(); padInit(); draw();

Animating Game Elements

function draw() {

context.clearRect(0,0,canvasW,canvasH); background(); brickDraw(); ballDraw(); padDraw();

#A

#A Draw functions overlay from bottom up

Listing 7. Paddle animation


var padSpeed; function padInit() {

Rowing The Paddle

To make the paddle move adjust the x axis each time its drawn. Making x positive will draw the paddle forward while a negative value will pull it back. First, add an undeclared variable at the top for your paddles speed. Second, give the variable a value of 4 in padInit() to make things run a little faster than you normally would for players. Finally, add an incremental

padY = 210; padW = 90; padH = 20; padSpeed = 4; padR = 9;

function padDraw() {

padX += padSpeed; context.beginPath();

#1

context.arcTo(padX+padW, padY, padX+padW, padY+padR, padR); context.arcTo(padX+padW, padY+padH,padX+padWpadR,padY+padH, padR); padR, padR);

context.moveTo(padX,padY);

context.arcTo(padX, padY+padH, padX, padY+padHcontext.arcTo(padX, padY, padX+padR, padY, padR); context.closePath(); context.fill(); context.fillStyle = padGrad();

Figure 3. Using the previous code snippets, you created a ball, a paddle, and bricks with gradients. After refreshing your browser, the current result should look like this

12/2010 (30)

33

HTML5 IN ACTION

equation at the beginning of the paddles draw function. Listing 7 puts it all together for you. Now, refresh your page. Oh no! The paddle swims off into oblivion due to a lack of a movement limiter (#1). The only way to keep your paddle from vanishing is to integrate collision detection. First though, the ball needs to be pitched.

then you need to activate some logic to handle the situation. For instance, if the ball and paddle overlap that should cause the ball to bounce off.

Real Game Physics

Throwing The Ball

Making the ball move is almost exactly the same as moving the paddle. The only difference is that the x axis and y axis are incremented each time theyre drawn. Run the code in Listing 8. You can tweak the balls trajectory by adding a few extra points to the Y axis. While optional, such an adjustment will make the ball move at a sharper vertical angle. After refreshing, the ball and paddle should fly off the screen and disappear. While their disappearance may leave you depressed and lonely, do not fear! You will soon retrieve them through some basic physics integration.

Sad to say, but these physics arent real in a mathematical sense. If youre interested in learning how to make games more lifelike please see Glenn Fiedlers robust article on game physics at http:// gafferongames.com/game-physics/. Start building collisions detection into Breakout by keeping objects contained inside the play area. After taming objects, youll focus on using the paddle to bounce the ball at the bricks. After the ball is bouncing back, the games bricks need to be removed when touching a ball. Lastly, create rules to determine when the game is shut down. Lets get started. To prevent your mouse and paddle from flying off the screen, theyll need to be checked against the <canvas> width and height. Use the canvasW and canvasH variables to keep your objects in check. Go to the padDraw() function and replace padX += padSpeed; with the equation in the snippet that follows to check if the paddle has a positive X coordinate and is within the <canvas> width. If it is, then update the paddles
Listing 9. Ball edge detection
if (ballY < 1) {

Making Interactive Objects

Detecting Collisions

In simple 2D games, using physics could be stated as testing for object overlap. These checks need to be performed each time the interval refreshes and draws an updated set of objects. If an object is overlapping,
Listing 8. Ball animation
var ballSX; var ballSY; function ballInit() {

ballY = 1;

#A

ballX = 120; ballY = 120; ballR = 10; ballSX = 2;

else if (ballY > canvasH) { } if (ballX < 1) {

ballSY = -ballSY; #B #C

ballSY = -2;

ballX = 1;

function ballDraw() {

else if (ballX > canvasW) {

ballSX = - ballSX; #D

ballX += ballSX; ballY += ballSY;

ballX = canvasW - 1; ballSX = - ballSX;

context.arc(ballX, ballY, ballR, 0, 2 * Math.PI, context.fillStyle = ballGrad(); } context.fill();


false);

context.beginPath();

ballX += ballSX; ballY += ballSY; #A Top edge #B Bottom #C Left #D Right

34

12/2010 (30)

HTML5 IN ACTION

X coordinate as normal. If performed correctly, youll notice that the paddle stops at both the left and the right edge.
if ((padX > 0) && (padX < (canvasW padW))) { } padX += padSpeed;

When the balls x and y coordinates overlap the paddle, bounce the ball in the opposite direction by reversing the y axis with the ballSY variable.
if (ballX >= padX && ballX <= (padX + padW) && ballY >= ballSY = -ballSY; padY && ballY <= (padY + padW)) {

Since the paddle is taken care of, stop the ball from dropping out of gameplay by adding Listing 9 to the top of your ballDraw() function. Create a test for the balls Y coordinates and another for the X coordinates. If the ball is overlapping make the speed negative by replacing ballX += ballSX; and ballY += ballSY;. In addition to reversing the ball youll need to put it back inside the play area; otherwise, you run the risk of it getting stuck at higher movement speeds. Use the following code snippet to make the ball repel off the gameplay areas sides. With the ball ricocheting, youll need to use the paddle to deflect it back toward the bricks. Since the ball changes direction on impact and the paddle stays stationary, put your deflection logic inside ballDraw() by ballx += ballSX and ballY += ballSY;, as seen in the following snippet.
Listing 10. Removing bricks
function brickDraw() {

ballX += ballSX; ballY += ballSY;

Listing 11. Ending the game


function ballDraw() { if (ballY < 1) {

ballY = 1;

else if (ballY > canvasH) {

ballSY = -ballSY;

clearInterval(canvasRun);

canvasRun = setInterval(goDraw, 12); canvas.addEventListener(click, restartGame, false); #A

#A #A

for (i=0; i<bRow; i++) {

ballX = 1; }

for (j=0; j<bCol; j++) {

ballSX = - ballSX;

if (bricks[i][j] !== false) {

if (ballX >= brickX(j) && ballX <=

else if (ballX > canvasW) {

(brickX(j) + bW) && ballY >= + bH)) {

ballX = canvasW - 1; ballSX = - ballSX;

brickY(i) && ballY <= (brickY(i) bricks[i][j] = false; ballSY = -ballSY; #B #A

ballX += ballSX; ballY += ballSY;


if (ballX >= padX && ballX <= (padX + padW) &&

brickColor(i); context.fillRect(brickX(j),brickY(i) } ,bW,bH); }

ballY >= padY && ballY <= (padY + padW)) {

ballSX = 7 * ((ballX - (padX+padW/2))/padW); ballSY = -ballSY;

context.beginPath();

#A Collision test

context.arc(ballX, ballY, ballR, 0, 2 * Math.PI, context.fillStyle = ballGrad(); } context.fill();


false);

#B If true brick = false

#A Add these lines

36

12/2010 (30)

HTML5 in Action

If youve played Breakout, youll notice that the paddles deflection appears to be broken. When the ball hits it isnt dynamically bouncing back based upon where it hits the paddle. To make collisions dynamic, modify the equation to take into account the balls X axis based upon where it impacted the paddle, as follows:
if (ballX >= padX && ballX <= (padX + padW) && ballY >= ballSX = 7 * ((ballX (padX+padW/2))/padW); } ballSY = -ballSY; padY && ballY <= (padY + padW)) {

all animation. After that, youll notice two mystery functions that take care of the game over screen. Now that you can deflect the ball back towards bricks, players have the ability to defend themselves from the dreaded game over. Well, not exactly... We still havent explained how to let players control the paddle. Whipping up a little bit of jQuery magic well show you a few simple code recipes for setting up keyboard and mouse functionality.

Creating Keyboard and Mouse Controls

With the paddle dynamically generating the balls trajectory the bricks need to start disappearing. Use the brickDraw() function in Listing 10 to test if the ball is overlapping when a brick is drawn. If so, reverse the balls y-axis and set the bricks array data to false so it wont be drawn or interact with the ball any longer. To finish up Breakouts detection, there needs to be a point where a game over occurs. In order to stop the game add logic in the ballDraw() function for when the ball goes below the play area. The game over occurs in Listing 11 with a clearInterval() that stops
Listing 12. Keyboard listeners
var keyL; var keyR;

Removing Objects

To create an interactive game experience, keyboard or mouse input is required. The sad news is that browser support for detecting keyboard events is nothing short of terrible. DOM level 3 is supposed to help standardized keyboard monitoring, but support is currently dodgy. Although youve gotten away without using it so far, youll need the jQuery library to detect keyboard events. Download the library from jquery.com and insert it right above the Canvas games JavaScript file. We highly recommend that you download the minified production file to minimize the games size (the smaller the size, the faster it loads).
<script type=text/javascript src=jquery.js></script> <script type=text/javascript src=game.js></script>

#1 #1

$(document).keydown(function(evt) {
if (evt.keyCode === 39) {

keyL = true;

#A

else if (evt.keyCode === 37) {

});

keyR = true;

#B

With jQuery locked-in and loaded you can set up a flexible control scheme where the player has options. For the first option, youll create keyboard controls with the left and right arrow keys. For those who wield the power of a mouse, youll create a JavaScript mouse listener that monitors cursors movement and places the paddle there. Lastly, well give you a few tips on best practices for integrating controls based upon techniques that produce happy customers.

Mastering The Keyboard


#C

$(document).keyup(function(evt) { keyL = false;

if (evt.keyCode === 39) {

else if (evt.keyCode === 37) {

});

keyR = false;

To create a keyboard detector you need two new variables near the top of the JavaScript file. One for the left and another for the right keyboard arrows. Think of these monitoring devices as switches for activating left or right movement. To turn keyboard variables on and off youll need two jQuery listeners. One that detects when keys pressed down and another that monitors key release. For detecting the keys use keycodes for the most consistent and simple way to detect a users keyboard input.

#A Checks if left arrow key #C Resets keyL and keyR

#B Checks if right arrow key

More Keycodes!

If you would like to know more about the state of keyboard detection and get a complete list of key codes, please see Jan Wolters article JavaScript Madness: Keyboard Events at http://unixpapa.com/js/key.html.

12/2010 (30)

37

HTML5 IN ACTION

Based on the current state of the monitored keys, the paddle is shifted left or right. Dump the code from listing 12 at the very bottom of your JavaScript file. Refreshing the page, youll notice that the paddle refuses to acknowledge your commands. With the keyL and keyR variables storing keyboard input (#1), the padDraw() function needs to be updated to detect whether to move left or right. The movement function will need to be rewritten into two parts one that moves the paddle to the right and stops against the right wall and another that does the same for the left. Replace if ((padX > 0) && (padX < (canvasW padW))) {} with the following code snippet to make the paddle react to the variables.
if (keyL && (padX < (canvasW padW))) { } padX += padSpeed;

else if (keyR && padX > 0) { } padX += -padSpeed;

Manipulating The Mouse

jQuery does more than hijack keyboard keys; it also makes mouse movement easy to monitor. To get the current mouse location, create a listener at the bottom of your JavaScript file. Note that placing listing 13 at the bottom of your JavaScript file will override the keyboard listener you integrated earlier.

use keyboard shortcuts to increase user productivity. While allowing users to speed up interaction is useful, it can quickly create problems. You need to be careful when declaring keyboard keys in JavaScript. You could override default browser shortcuts, remove operating system functionality (copy, paste, and so on), and even crash the browser. The best way to avoid angering players is to stick to the arrow and letter keys. Specialty keys, such as the space bar, can be used, but overriding shift or caps lock could have unforeseen repercussions. If you must use a keyboard combination or specialty key, ask yourself, Will this cause problems for my applications users in some way? When playing videogames, people dont want to spend their first 10 minutes randomly smashing keys and clicking everywhere. Put your games controls in an easy-to-find location and use concise wording. For instance, placing the controls directly under a game is a great way to help users. To add a control description to Breakout, add a simple <p> tag directly below <canvas>. It should say LEFT and RIGHT arrow keys or MOUSE to move. If you really want, you could create a graphical illustration thats easier to see, but for now well just use text for simplicity.
<canvas id=canvas width=408 height=250> </canvas> Download FireFox to play this game now!

Control Input Considerations

In the past couple years, JavaScript keyboard support for applications and websites has grown in leaps and bounds. YouTube, GMail, and other popular applications
Listing 13. Mouse controls
var mouseX;

<p>LEFT and RIGHT arrow keys or MOUSE to move</p> <script type=text/javascript src=jquery.js></script> <script type=text/javascript src=game.js></script>

Congratulations! Youve just completed an HTML5 game from beginning to end.

$(#canvas).mousemove(function(e){ tion().left);

Summary
#A

var canvasPosLeft = Math.round($("#canvas").posi var canvasPos = e.pageX - canvasPosLeft; var padM = padW / 2;

#B

if (canvasPos > padM && canvasPos < canvasW -

mouseX = canvasPos; mouseX -= padW / 2; padX = mouseX;

padM) {

});

While 2D games can be fun to make, they arent exactly making record sales in the game market. In addition, most 2D-based game and animation studios have closed down or converted over to 3D. If browser interfaces want to compete with professional tools, such like 3D Studio Max, Maya, and After Effects, then 3D must be capable in the browser. On the other hand, 2D applications can be fairly cheap to produce and casual gaming on the internet has grown tremendously in the past ten years, which is resulting in high demand for 2D games (especially on mobile devices).

#B Centers paddle on mouse

#A Game position from left in pixels

38

12/2010 (30)

ALTERNATIVA 3D

Alternativa3D
AlternativaPlatform is a company, headquartered in Perm, Russia. It develops and supports technology solutions for browser-based multiplayer projects.
What you will learn
What is Alternativa3D. How to get started with Alternativa3D

What you should know


Prior experience programming with ActionScript 3 is required. A previous background working with 3D graphics is also recommended.

lash-3D-engine, physical engine, GUI library and high-performance server-side, developed by company, allows to create a unique browser-based games, social networking applications, promotional projects and demonstrations. One of the key projects is browser-based multiplayer realtimeaction Tanki Online (Figure 2). Now the second version of the game is in development (Figure 3). It is optimized for social networks. Also company works on a few other online games (alone and as a technology partner). In

addition, AlternativaChina company is established in Shanghai, and dedicated to localizing and releasing games for the Chinese market.

Alternativa3D

Alternativa3D engine is intended for displaying 3D graphics in the Flash Player environment. The possibilities with Alternativa3D are comprehensive and diverse. The technology is widely used in different spheres ranging from 3D websites creating

Figure 1. AlternativaPlatform Logo

40

12/2011 (30)

Alternativa3D

to developing multiplayer browser-based games and applications for social networks in full 3D. The purpose of the appearance of Alternativa3D was creating high-performance 3D-renderer for using in new projects of AlternativaPlarform company. Version 5 of the engine was released in may 2008. It was a public version, which is available for using in any non-profit projects. It used the BSP-tree for scene building and could very quickly and correctly render greater levels. Due to these facts Alternativa3D 5 got widespread among flash-developers. In 2010 the next generation of Alternativa3D with number 7 became available. This version used API of Flash Player 10, so improved the quality of display objects in perspective. Also the engine architecture was rewritten. At that time the focus was on efficient processing and sorting dynamically changing scenes polygons. Current version 8 of the engine uses videocard GPU to render 3D graphics. Also, you can use Alternativa3D 8 and Alternativa3D 7 for free in any projects, even in commercial ones.

it can be done by calling the addChild() method each object has its own coordinate space all child objects keep their position in parents coordinate space properties holding objects position are familiar (such as x}, {{y, z, scaleX, rotationY and so on) coordinates of an object in its own space are always equal 0, 0, 0 even all visible parts visual content can be created in code as well as loaded from external file or embedded assets

and differences: root object of the flat world is an application itself but you should create a root object for 3D world simplest DisplayObject cant have children but Object3D can as well as DisplayObjectContainer flat world is ready with an empty application but 3D needs some preparation (minimu set of created objects and calls)

What You Should Know About 3D World of Alternativa3D

3D world of Alternativa3D engine has many similarities with flat flash world as well as many differences. Lets start with calling familiar things: both worlds have hierarchical structure all objects of each world (include root object) have one base class (DisplayObject and Object3D) if object should be visible it needs to be added in hierarchy almost any node of hierarchy can be parent for objects

The general comparison can get some comprehension and for deeper comprehension make deeper comparison between heart of 2d and 3D visual objects. Usual flash graphics are built on points with lines which can be straight or curved. Object itself can consist of strokes, fills or both. Not all Object3D is visual and now we will talk about main visual Object3D class mesh. It also built on points called vertices, but a vertex can hold additional data (such as texture coordinates, normals and tangents and so on), not only its own coordinates. Another difference is that verticies can be linked with direct lines only to make a triangle.

Figure 2. Tanki Online

12/2011 (30)

41

ALTERNATIVA 3D

Sequence of these triangles form a surface.The surface is like a usual flash shape which has its own one fill but does not have to be flat. The Fill in 3D world associated with material. Material differs from a fill as follows: besides color information for each pixel material can hold a lot more information concerned with lightning. This information defines the behavior of an object exterior depending on the point of view and the disposition and the features of lights presented in the world. Different materials depending on their complexity can demand different sets of data to be successful. The simplest material is FillMaterial it acts as a solid fill in pure flash. It does not need any additional data and the surfaces with this material will ingore lights at all. The most complex and extensive material in alternativa world is StandardMaterial. So it require maximum additional data in textures as well as in vertex. For the Surface to work with StandardMaterial it should have the following vertex data: texture coordinates vertex normals complex data type consisting of tangent and binormal.

Besides the additional vertex data and usual diffuse map which defines with which image surface fills, StandardMaterial needs normal map texture defines deviations between geometry surface and surface which will act in light calculations in order to make the surface look more detailed than its geometry. So flat surface can look rough due to normal map. Also you can set to StandardMaterial additional textures which are not required but can make the surface more attractive and realistic. There are: glossiness map and specular map.

Types of Object3D

As we already note, not all Object3D are visual, and visual ones not limited with Mesh. So they are listed and described below.

Visual Classes
Mesh

static 3D object consists of surfaces. Primitives (Box, GeoSphere, Sphere and Plane) subclasses of mesh which include built on visual form generated in creation according to its name. Skin subclass of mesh which include joints (bones) in order to aid moving and animating parts of solid object.

Figure 3. Tanki Online 2.0

42

12/2011 (30)

Alternativa3D

Decal subclass of Mesh with a z-fighting suppression engine. Usual usage additional marks which overlays existing mesh such as bullet holes, bloodsplashes occurs in games during gameplay and so on. WireFrame stroke analogue in 3D world which shows lines (e.g edges of mesh or axis) SkyBox cubic primitive meant for showing the environment. So it has a few differences with Box such as normals turned inside and permanently staying at the bottom layer so it does not overlap any other object. Sprite3D and AnimSprite are flat pictures/animations which live in 3D world but always turned to the camera so it can not have any perspective distortion.

Camera3D Object3D which determines what we will see on screen: point of view, field of view, direction. Light3D Base class for all lights in Alternativa3D: OmniLight, DirectionalLight, AmbientLight. It lights surfaces with appropriate materials such as VertexLightMaterial and StandardMaterial. Joints also known as bones, Object3D meant for moving (animating) parts of solid mesh. Joint act like container for a set of vertices but 1) one vertex can be handled by up to 8 joints and 2) this vertex has value of power of affect of each joint.

Non-visual Classes

Since the new flashplayer has hardware acceleration for rendering 3D, we should follow some restriction to be compatible. First we should know,a hardware rendered image does not included in classic DisplayTree. There is a special stage stage3D. Any application can have 4 stage3D, all of them placed as layers on each other but below the DisplayTree so any flat flash object will overlap the 3D image. Second and most important thing in dealing with hardware API is that all data required to render image with GPU should be loaded into video memory. Such data associated with resources in Alternativa3D. There are 2 general types of resources: vertex data and textures. Alternativa3D gives several ways of dealing with resources but it is possible to start with the simplest gathering all resources of the object and all its children by using the method getResources(true). Sometimes as you use TexturesLoader to load textures from external files it cares about uploading texture resources to video memory. Another thing you should know about textures its width and height should be to power of 2. 512x256 good example, but there is no way to use texture 200x300. Usual flash application is inherited from DisplayObject like Sprite or MovieClip so it has all working requirements done.The Alternativa application needs in creation of 3D world and some parts connecting it with flat screen. First we need the root object of the 3D world. It can be just an Object3D instance, lets call it rootContainer.
rootContainer = new Object3D();

Hardware API and resources

Listing 1. Application structure


package {

Application Structure

import alternativa.engine3d.core.Camera3D; import alternativa.engine3d.core.Object3D; import alternativa.engine3d.core.View; import flash.display.Sprite;

[SWF(backgroundColor = "0x909090", width = "800", height = "600")]

public class HelloBox extends Sprite { private var camera:Camera3D; private var rootContainer:Object3D; public function Template() {

Then we need the Camera3D added somewhere in rootContainer hierarchy.


camera = new Camera3D(10, 1000);

camera = new Camera3D(0.01, 10000000000); camera.view = new View(stage.stageWidth, 0x404040, 0, 4); stage.stageHeight, false,

rootContainer.addChild(camera);

addChild(camera.view);

} }

rootContainer.addChild(camera);

rootContainer = new Object3D();

When creating a camera instance we should to pass 2 arguments: nearClipping and farClipping which determine the depth of the space camera can be observed. It is because of the z-buffer used in the hardware rendering engine. The rendering engine draws objects one by one and should know if some part of already drawn objects are placed nearer than those parts that are in processing in the same part of the screen, and also that part that needs not to be drawn as it should be hided. In order to know that the engine keeps distance to the camera simultaneously

12/2011 (30)

43

ALTERNATIVA 3D

with drawing each pixel or, if for the presented distance value closest to camera for this pixel, the engine just leaves this pixel as it is. GPU has a fixed size of memory to keep such distance to camera (this is z-buffer). Therefore with increasing depth of space between nearClipping and farClipping the precision of distance falls. So it will be better to keep nearClipping and farClipping closest to each other. While rendering objects placed that are close to each other visual artifacts can occur (Z-fighting). Since overlapping marks should be very close to other surfaces,to prevent visual artifacts Decal class was created. Last thing we need to create is viewport of the camera. It determines the size of a visible area, color of the background and so on.
Listing 2. Project example
package {

camera.view = new View(stage.stageWidth, false, 0x404040, 0, 4); stage.stageHeight,

And view should be in regular need to call


addChild(camera.view);

DisplayTree

so we also

And if you want to see something, you should add it to rootContainer hierarchy too. Take all it together in the order which they should be presented in application (Listing 1). Any created object at the begining has 0,0,0 coordinates by default which are associated with the

import alternativa.engine3d.controllers.SimpleObjectCo import alternativa.engine3d.core.Camera3D; import alternativa.engine3d.core.Object3D; import alternativa.engine3d.core.Resource; import alternativa.engine3d.core.View; import alternativa.engine3d.materials.FillMaterial; import alternativa.engine3d.primitives.Box; import flash.display.Sprite; import flash.events.Event;

addChild(camera.view); rootContainer = new Object3D();

ntroller;

rootContainer.addChild(camera); box = new Box();

box.setMaterialToAllSurfaces(new rootContainer.addChild(box);

FillMaterial(0xFF0000));

import flash.display.Stage3D;

stage3D = stage.stage3Ds[0]; CREATE, init);

stage3D.addEventListener(Event.CONTEXT3D_ stage3D.requestContext3D();

[SWF(backgroundColor = "0x909090", width = "800",


public class HelloBox extends Sprite { private var stage3D:Stage3D; private var camera:Camera3D;

height = "600")]

}
private function init(event:Event):void {

private var rootContainer:Object3D; private var box:Box;

for each (var resource:Resource in rootContaine

private var controller:SimpleObjectController;

resource.upload(stage3D.context3D);

r.getResources(true)) {

public function HelloBox() {

addEventListener(Event.ENTER_FRAME, } enterFrameHandler)

camera = new Camera3D(0.01, 10000000000); camera.x = -50; camera.y = -300; camera.z = 100; controller = new SimpleObjectController(stage, camera, 200); } }

private function enterFrameHandler(event:Event):

controller.update(); }

void {

camera.render(stage3D);

controller.lookAtXYZ(0,0,0);

camera.view = new View(stage.stageWidth, 0, 4);

stage.stageHeight, false, 0x000000,

44

12/2011 (30)

Alternativa3D

origin of its parent. Thus the camera in the code given above placed in the center of the rootContaner and looking upwards. So even if we place some geometry to rootContainer, the camera would not see anything since the new geometry occurs in the center too and will surround the camera. All geometry in Alternativa3D has only one side and can not be seen from inside (the visible side is determined by the normals of the surface but from the inside unlike from the outside it will invisible SkyBox acts like this). In the light of this fact we should move and turn the camera. We can do so just by setting up coordinates and rotation properties of the camera but it doesnt look so obvious to calculate these values. Usually we want to handle the camera by the keyboard and the mouse or just make it look at a given object. It is not always true. However it looks right for most simple application such as what we are talking about. There is SimpleObjectController class in Alternativa3D for these cases. It makes the camera fly by using the keyboard and mouse and has set of methods to handle the camera from the code (like lookaAt()).
camera.x = -50;

is needed to get context3D as a parameter meant as destination of this upload. You can be surprised that this stage3D does not have the ready to work context3D, yet. We should ask for it, and start to do something with context3D after it is done.
stage3D.addEventListener(Event.CONTEXT3D_CREATE, init); stage3D.requestContext3D();

As we get context3D, we can upload resources and start rendering.


private function init(event:Event):void { getResources(true)) {

for each (var resource:Resource in rootContainer. resource.upload(stage3D.context3D);

addEventListener(Event.ENTER_FRAME, } enterFrameHandler)

camera.y = -300; camera.z = 100; controller = new SimpleObjectController(stage, controller.lookAtXYZ(0,0,0); camera, 200);

As long we should render every frame, we place this call in enterFrameHandler with controller.update() together.
private function enterFrameHandler(event:Event):void { controller.update(); camera.render(stage3D);

To be successful with the controller you should make a few notes: You should let the controller know about the need of change of the position of the camera every time. It can be done just by calling controller.update(). Just add this call to enterFrame handler if you are going to use a keyboard and a mouse. If a controller performs a relative move such as step forward, it uses coordinates which it keeps in itself. So if you change the camera placement through its properties like x, y, z, it will dropped during the next controller.update() calling. To avoid this you should change the camera placement through controller.set Position().

Base application done. You can use it as a clear template for yours so it is the reason of Template class name. But there is not any visible object yet. A cube is a good option for the first time so lets add it and rename our class to HelloBox.
box = new Box();

box.setMaterialToAllSurfaces(new rootContainer.addChild(box);

FillMaterial(0x804080));

No object can be visible without material so we just assign one. You should get something like this: Listing 2.

Friendship with GPU

Having done preparing the 3D world so let to meet our application with GPU. What we will need first is Stage3D and its property conext3D which is associated with the video memory.
stage3D = stage.stage3Ds[0];

YURI MALTSEV
Yuri Maltsev is a consultant at the AlternativaPlatform training center. He graduated from the Perm State Pedagogical University, where he studied computer science and pedagogy. Yuri writes technical documentation for the Alternativa3D, communicates with the developers community on issues involving the Alternativa3D engine.

As we already said, all resources should be in such memory. It can be loaded by upload() method which

12/2011 (30)

45

PATTERNS FACTORY

Applied Design Patterns Factory


Last month we began our journey to the Design Patterns land with the Singleton Pattern. This month we will see the Factory pattern and how can you apply it to simplify our work when dealing to databases connections.
What you will learn
Learn about the Factory Pattern Begin to identify the various Design Patterns Use a xml le to hold cong options

What you should know


A good understanding of AS3 and OO Principles Be curious Love to learn new topics

he example app is intended to connect to vary myriad of databases, as Oracle, MySQL and son on. For the example app for this article lets suppose that this application will connect directly to a database server and perform some operation on it.

Listing 1. Cong.xml le
<?xml version="1.0" encoding="utf-8"?> <connection> <database>

Project Structure

Lets begin creating our application structure, create a new ActionScript project called Factory and in the src folder create the Classes folder. Also create a xml file called config. See Figure 1.

<adapter>MySQL</adapter> <host>localhost</host> <port></port> <user>root</user> <db>test</db>

<password>test</password> </database>

The Config File

To simplify connection configuration for this example, Ill be using a xml file that will store all the parameters needed for database connection. See Listing 1.

</connection>

Listing 2. Interface that all DB classes must implement


package Classes.Adapters

public interface iDBAdapter function save():void;

function find(params:Array = null):void; function initWithConnection(host:

String,user:String,pwd: String,db:String):void;

Figure 1. ProjectStructure

46

12/2011 (30)

Applied Design Patterns Factory

Using this xml file to config our connection type and so on, we ensure that we can change the adapter from MySQL to Oracle for example, without the need to modify any code. We will se this later in the article

Listing 4. Simple Factory class


package Classes

Database Adapters

As all databases share common attributes such as host name, connection port and etc, I began creating an interface (IDBAdapter) and an abstract class (DataBase). Despite I could create the DataBase class without implementing this interface, doing so ensure that any
Listing 3. DataBase abstract class
package Classes.Adapters

public class DBConnectionFactory import Classes.Adapters.DataBase; public function DBConnectionFactory()

{ }

public function create(adapter:String):DataBase

var dbClass:DataBase; switch(adapter)

public class DataBase implements iDBAdapter public function DataBase()

case 'MySQL':

{ }

import Classes.Adapters.MySQL;

public function save():void

break;

dbClass = new MySQL();

throw new Error('Children must implement

case 'Oracle':

save method');

import Classes.Adapters.Oracle;

public function find(params:Array=null):void

break;

dbClass = new Oracle();

case 'PostgreSQL':

throw new Error('Children must

import Classes.Adapters.PostgreSQL;

implement find method');

break;

dbClass = new MySQL();

public function close():void

case 'SqlServer':

import Classes.Adapters.SqlServer;

throw new Error('Children must

implement close method');

case 'PostgreSQL':

break;

dbClass = new MySQL();

import Classes.Adapters.PostgreSQL;

public function initWithConfig(host:String,user:

void

String,pwd:String,db:String):

break;

dbClass = new MySQL();

case 'SQLite':

import Classes.Adapters.SQLite;

throw new Error('Children must

implement the initWithConfig method');

break;

dbClass = new SQLite();

} }

}
return dbClass;

12/2011 (30 )

47

PATTERNS FACTORY

Listing 5. MySQL adapter implementation


package Classes.Adapters

public class MySQL extends DataBase public function MySQL()

{ }

override public function

initWithConnection(host:String, user:String, pwd:String,

Figure 2. AdaptersAndInterface

class that inherits from the DataBase class have to implement the methods defined in the interface. See Listing 2 and 3. Another procedure I made in the DataBase class is that in each method, throw an error that notifies the developer that these methods must be implemented by its children. Thats because in this king of situation any database might deal with each of these tasks differently, but as they implement the same methods defined in the interface, we have a solid API for interaction with of these database servers thus hiding the details of the implementation.

db:String):void trace('Connecting to the ' + host + 'with'

+ db +' database on mySQL server ' + 'User: ' + user

+ ' and Password: ' + pwd);

override public function save():void

trace('Inserting data into MySQL database');

The Little Factory

Now lets see how our little factory class works, which is pretty straight forward, so its simple factory. I begin importing the DataBase class as we will return an instance of the this class, then I defined the create method, where we check the king of database adapter must be return, instantiate it and finally return it. The kind of the adapter to be used is obtained from the config.xml file, if a create another adapter type, the only places I will have to change after creating the new adapter class is this simple factory and then specify that I want to use this adapter in the config file.

override public function find(params:Array = null):

void

trace('Query parameters: ' +

params.toString());

Figure 3. Output Information

48

12/2011 (30)

Applied Design Patterns Factory

Adapters Implementation

For the example of this article, the database adapters dont really connect to any database, they just print out its information on the Flex Builder console. See Figure 2 and Figure 3.

Putting it all together

Now that we have our database adapters and our factory, its time to put it all to work as shown in the excerpt of the Factory class our app main class. Listing 5 shows how to load the config information store inside the xml file using URLRequest and URLoader classes. Then its assigned an event listener to the onComplete where I get the loaded data from the xml file, assign the result to the config variable. After that a create an instance of the DBConnectionFactory class and pass the type of the database adapter must be created assigning the returned adapter to the db variable and issue the adapter methods. See Listing 6.
Listing 6. Loading the cong le
var config:XML = new XML(); var XML_URL:String = "config.xml";

Figure 4. Data Base Class In complete Implementation

Note

That I could have defined the create method as static, so the line where the factory instance is created would be no necessary. Thus its not common that an application developed with Flex to connect directly to a database, but does it via a backend via AMF for example, I tough it would be a nice example to illustrate the concept. I also left some sharp edges in the example, that I will be approaching next article. So thats all for now. Any question about this article drop me a line.

var XMLURL:URLRequest = new URLRequest(XML_URL); var loader:URLLoader = new URLLoader(XMLURL);

loader.addEventListener(Event.COMPLETE, onComplete);

Listing 7. Using the factory to get an adapter instance


function onComplete(event:Event):void

config = XML(loader.data);
var factory : DBConnectionFactory = new var db : DataBase;

DBConnectionFactory();

db = factory.create(config.database.adapter); db.initWithConfig(config.database.host, config.database.password, config.database.db)

MARC PIRES
Marc Pires is a Developer located in Brazil, during his career, he has worked in various roles such as Network Administrator, Instructor. He has a strong passion for working with and researching new technologies. Specialized on RIA, Iphone Development, Restful web services and other interesting things, hes one of the main developers of the Esus System and is beginning his startup specialized on mobile development. Contact information: @MarcPires (Twitter) | marcpiresrj@gmail.com | IChat: marcpiresrj@aim.com

config.database.user,

db.find([':all']); db.close();

12/2011 (30 )

49

REVIEW

WinX Free DVD Ripper


Ideal Solution for Appreciating DVD Movies on Android
Have you ever thought of watching DVD movies performed by favorite actors on Android devices, such as Android phone, Samsung Galaxy Tab, Fascinate, HTC Desire, etc.?

es, put DVD to Android devices and you can appreciate DVD movies anytime and anywhere. Plus, watching DVD movies on Android phone can be a visual enjoyment due to the Android touch screen design and high resolution which well fit for video viewing. If you have no idea how to put DVD to Android devices, WinX Free DVD Ripper can be an ideal solution to rip DVD to Android devices. Here we would like to show how to rip DVD to HTC via this totally free DVD ripper. Free download WinX Free DVD Ripper and install it http://www.winxdvd.com/dvd-ripper/.

Hit the Start button and go! This totally free DVD ripper published by Digiarty Software for you to backup DVD to MP4, WMV, MPEG, H.264, Android phone, iPhone/ 4S, iPod, Apple TV, Samsung, HTC, etc. In addition, you can try WinX DVD Ripper Platinum, the advanced version of WinX Free DVD Ripper to backup DVD to ISO image for later burning, or fully enjoy DVD movies on iPad regardless of all known copy protections, even the most complicated Disney X-project DRM.

Step 4

Know more about WinX Free DVD Ripper


WinX Free DVD Ripper delivers faster speed than similar free DVD rippers in current market due to its embedded Hyper-threading engine. Support both homemade and commercial DVDs and work stably to convert DVD regardless of CSS encryption, DVD region code, Sony ARccOS, UOPs, RCE, etc. With corresponding profile settings, it can be much easier even for beginners to rip DVD to various video formats and portable devices without quality loss. Freely capture image from DVD video to save as BMP, JPEG pictures. Flexible audio/video settings allow you to balance video quality and file size.

Step 1

Launch this software and insert your home DVD or commercial DVD, click DVD disc to load DVD.

Step 2

Click Browse to in output settings area to select a destination of output video.

Step 3

Click HTC and choose an optimal setting from profile settings.

In brief, this free DVD ripping software can be an ideal solution to rip protected DVD to Android phone, iPhone/4S, iPod, Apple TV, Samsung, HTC, etc.

MASON
Mason is a freelance writer. His goal is writing and sharing anything about apps or software closely related to DVD, CD, Blu-ray, Android and Tab or so, aiming at bringing real & useful message to readers. Contact email: masoncliton@yahoo.com

Figure 1. Rip DVD to HTC Android phone as a simple example

50

12/2011 (30)

You might also like