Friday, October 29, 2004

Mastering the Array

Mastering the use of Arrays is important in any programming language. But it's especially important in ActionScript. The skills you learn by commanding arrays can easily be applied to just about every object in Flash.


Everything in Flash is an Object. And, an Object can also be treated as an associative array. For example, we can use dot-syntax to access an object's property or method as in: myObject.property. Or, we can use array brackets as in: myObject[“property”].


When I'm trying to learn about a new object, an easy way to see what properties and methods it exposes is to loop through the object and trace out the properties and methods it contains. I use this simple script to explore an object:


exploreObject = function (o) {

for (var i in o) {

trace (i + ": " + o[i]);

}

}

exploreObject(button_mc);


In this example, you could take a button component and place it on the stage. Give it an instance name of button_mc, and run the script. This will trace out all of the properties and methods of a button component. You can then look through it to find the property or method you are looking for. Sometimes you'll find additional objects as properties of the first object you are exploring. You can easily loop through them by passing them into the same function as in: exploreObject(button_mc.textStyle);


Strings are another object in Flash that can be thought of as an array. Although they are also an Object they can also be thought of as an array of characters. Strings and Arrays both have length properties, allowing you to loop through them and evaluate their contents. You can easily convert a string to an array and vice-versa. This trick is useful if you are loading external data into flash. You could load a delimited list of data into Flash as a string, and then split it into a data array by the delimiter, as in: var myArray = myString.split(“,”);


Being able to easily split strings into arrays and then back into strings also makes for a simple and elegant way of creating a String replace function. If we write this using the String.prototype, all Strings every in our Flash movie will be able to use this replace function.


String.prototype.replace = function(replaceString, withString) {

var myArray = this.split(replaceString);

return(myArray.join(withString));

};


When we call this function, we'll pass two parameters into it. The first is the substring we want to replace and the second is the string we want to put in its place. When this function is called, it uses the String.split() method to break the string into an Array, called myArray. The split method uses a string that is passed into it, in this case our replaceString, and everywhere this string is found, it breaks the original string into a new element in the array, removing the delimiter.


The Array.join() method does the same thing, but in reverse. It takes each item in the array, converts it to a string and inserts a specified delimiter, in this case withString, in between each array element, creating a single String. Here is an example of how it is used:


var s = "The red dog ate the red frog";

trace(s.replace("red", "green"));


These are two very simple examples, but they illustrate the power of understanding how to manipulate objects as if they were arrays. In my next tutorial, we'll build further on Arrays, exploring multi-dimensional arrays and ways that we can use them to store complex data.


Sunday, October 10, 2004

Flash & FSCommand

Hi,
If you have worked with Flash & FSCommand, you must have been frustrated with its dodgy behavior. That’s because FSCommands have a MAJOR drawback.

The Flash player runs FSCommands asynchronously, after all Action Script in the frame is completed. And this limitation forces you into a complex web of work arounds. For example, let's say your application needs to check for a net connection and download a file. Using FSCommands, you might write the following code. You'll find it does NOT work. Can you figure out why?

FSCommand ("checkconnection", "connectionIsAvailable");
if (connectionIsAvailable == "true") {
// download file
} else if (connectionIsAvailable == "false") {
// do something else
}


The code fails because connectionIsAvailable does not exist. The Flash player executes the FSCommand after the native ActionScript completes (after the IF statement) and returns a value to connectionIsAvailable only after the movie advances a couple of frames.
To make this simple example work using an FSCommand-based solution, you are forced to split the code into two frames -- running the FSCommand in frame 1 and the IF statement in frame 3.

Thursday, October 07, 2004

What does Object-Oriented Design Mean to You?

What does Object-Oriented Design Mean to You?

In today's world, you're just as likely to see a resume that says object-oriented design as you are to see a bachelor's degree. After more than a dozen years of sitting on a shelf, it seems like suddenly people are interested in object-oriented programming. Perhaps that's because Microsoft .NET and Java languages are all purportedly object-oriented languages. It seems like everyone believes that, if they are using an object-oriented language, they're doing object-oriented design. Nothing could be farther than the truth, and here's why.


Object Oriented Languages Do Not Make Object Oriented Developers


Object oriented languages do not automatically make programmers into object-oriented developers. Saying that I'm an object-oriented developer because I've used an object-oriented language is like saying that, because I have a bottle of wine, I'm a wine connoisseur. (For the record, my knowledge of wine is red, white, and blush.)


An object-oriented language merely makes it easier for you to implement the good programming practices that you already know. You know to minimize the impact of changes through encapsulating your data and code together. You know that you should keep the code similar and minimize the dependencies between different sets of code. An object-oriented language facilitates these and other programming goals.


Becoming an object oriented developer means studying concepts and learning to apply them rather than simply learning a new language.


Objects Don't Make an Object Oriented Design


The funniest thing I have ever heard an interviewee say was, "I've created dozens of objects-yes, and I'm an object-oriented developer." It was funny because it made object-oriented programming sound like an accident. It wasn't something he thought about, but it was something that happened to him without his knowledge. That's about as far from being an object-oriented developer/designer as you can get.


In C#, it is mandatory to create objects. However, that doesn't mean that you're doing object-oriented development or design. It just means you're working within the requirements of the tool.


Object oriented design and development is a conscious thing. It's focusing on organizing information and code into meaningful objects that perform meaningful processes on data.


An Object is


One of the fundamental tenets of object-oriented programming is that an object is modeled after a real world concept. For instance, an object representing a dog might have a tail. The dog might perform the action of walking or eating. The object is modeled after its real world counterpart.


This works well with a concrete object; however, it gets more complex when dealing with abstract objects. For instance, catalog objects have products in them, they have methods that search for products, and they may also have other properties and methods that a physical catalog might not have. When you start to layer the properties and methods, the traditional physical objects begin to lose their focus and have trouble assigning those properties and methods.


One of the keys is to think of how the physical item would behave if it wasn't limited to the physical form. Focusing on the attributes it would take on in an electronic form can help you keep focus on where you put properties and methods.


Coupling and Cohesion


Two classic programming problems are coupling and cohesion. Coupling is a factor that, in general, should be minimized. Coupling refers to the interrelated aspects of different parts of code. Whenever you make one object dependent on another for its operation - or one system dependent on another for its operation, they are coupled. One problem with coupled systems or objects is that, when one changes, it exposes the other to potential problems.


When one object looks inside of another for its operation, rather than using defined interfaces, changes in the internal operation of that object can make the other object operate incorrectly. These subtle interactions between multiple objects can be difficult or impossible to locate.


The second problem is that coupled objects need to be changed together. Even if you avoid the debugging nightmare of not knowing which objects are related to one another, they must still change their function when the coupled objects change.


One obvious exception to the coupling rule is collections. Collections are necessarily coupled with the objects that they contain so that they can return specific type information. They are coupled in other ways as well, as they may need to rapidly create large numbers of instances of the objects they contain.


Like collections, there are other special situations when, used appropriately, coupling isn't a bad thing, and in ways that are clear to even the casual observer, coupling can be a necessary part of software development.


The most closely related concept to coupling is the concept of cohesion. Cohesion answers the question, should an object be one object or more than one object? A cohesive object is one that cannot easily be broken up into multiple objects. It is an object that has one clear purpose and one clear entity that it represents.


It is also applied to those situations when an underlying object is needed. For instance, if you have a dog object and a cat object, you have two objects that have many similarities. Without an underlying object that encapsulates that similar functionality, you risk rewriting the same code. Both cats and dogs are animals and mammals. As a result, a dog object may not be a cohesive object - unless it is derived from objects such as "mammal," which in turn is derived from "animal."


Conclusion


Object oriented design is more than a language. It's not some path that you can follow blindly. It's a winding road that requires concentration. However, there are rewards. Quicker development times, fewer defects in your code, and a more maintainable masterpiece can be yours if you can keep from falling off the path.


Thursday, September 30, 2004

Optimizations of flash code

I found a few good coding tips. The following are few important basics that would help a learner to learn the fundamentals of actionscripting. What we can learn from all these benchmarks is that by accurately choosing the right way to code certain time critical functions, we can greatly improve the flash player performance. The best approach is to isolate those very cpu-intense routines and try to apply as many of these advices as possible and also running your own tests for your specific problems.

Cheer and enjoy

Basic Optimizations:



When talking about code optimizations we usually refer to speed improvements and not very much to memory savings as today, even not so recent computers, have good amount of memory for our flash programs(128mb is more than enough for most programs and today the standard for a new machine is 512mb)

>> Variables

One of the most important optimization tip is to always declare local variables using the keyword var. Local variables are faster to access for the player and are destroyed when the function returns.

An example of not-so-good code would be this:



function doSomething()    

{
mx = 100
my = 100
ar = new Array()

for (y=0; y < my; y++)
{
for (x=0; x < mx; x++)
{
i = (y * mx) + x
arr[i] = i
}
}

return arr
}




This code is not very good because it does not declare those variables as local, making them slower to access and leaving them alive after the function has finished.

A better version would be this:



function doSomething()    

{
var mx = 100
var my = 100
var ar = new Array()

for (var y=0; y < my; y++)
{
for (var x=0; x < mx; x++)
{
var i = (y * mx) + x
arr[i] = i
}
}

return arr
}




In this case all variables are defined locally and are faster to access. This is very important as the function runs a 10.000 iterations loop! When the function returns, all local vars will be destroyed saving resources.

>> onEnterFrame events:



the onEnterFrame event is very useful for developers as we can run code continuously at the frame rate set in the SWF.

Back to the days of Flash 5 it was a pretty common technique to use many different of these handlers.

Actually it is not reccomendable to attach many of these event handlers all over the movie clip because this can lead to spaghetti code and also it can significantly degrade performance.

Most of the times using one single onEnterFrame can be a good solution: just one main loop that takes care of the various operations to carry on.

Another simple tip is to set the fps parameter to a reasonable value: remember that the higher is the fps the more CPU power you will need to execute your code in every frame.

Values between 25 and 35 fps can be good to for executing pretty complex code in every frame even on slower machines and it is not desirable to exceed the value of 60fps (unless there's a specific reason)

>> Bitmaps vs Vectors:



Talking about graphics it is very important to choose the right approach before starting.

Flash seamlessly works with vector art as well as images but these two have very different impact on the flash player.

In using vector graphics try to simplify the shapes as much as possible eliminating redundant points. This will help in reduce the amount of calculations that the player has to compute for each vector shape. Another important aspect is the usage of outlines, which can definitely kill your performance. Whenever possible try to avoid them.

Using alpha values < 100 can also have bad impact on your general speed, so if you experience noticeable slow downs go hunting all those alpha values in your movieclips!

Moreover if you really need many sprites on screen and many animated art you may want to consider bitmap graphics.

Flash is not really a champion of speed in handling bitmaps, (for example compared to his elder brother Director) however images are faster than vectors.

Even if Flash supports GIF, JPG and PNG formats the latter seems to render faster than the others, therefore it is recommend using PNG whenever possible.

>> Movieclip visibility:



Very often you can have a large number of offscreen movicelips that are waiting their turn to come into the visible screen area.

When dealing with offscreen stuff it is important to understand that the flash player still consumes a certain amount of resouces for each of them. (doesn't matter if they are one frame only or animated)

One of the best solutions to this problem is to have an empty frame in your movieclips where you can gotoAndStop(), freeing up some work to the flash player.

Please remember that setting the visibility property ( _visible = false ) doesn't work as the movieclip still consumes some player time.

>> Arrays:



Another important tip to optimize looping in an array is to use the for in loop instead of the usual for or while syntax.

Code like this:



for (var i in arr)    

{
if (arr[i] > 50)
{
// do some processing here
}
}




has proved to be faster than this code:



for (var i=0; i<10000; i++)     
        {     

if (arr[i] > 50)
{
// do some processing here
}
}




by a 30% ratio! Not bad as a speed improvement!

>> Single vs Multiple var declaration

Whenever possible try to assign values to your variables using multiple assignment.

This can speed things up pretty nicely.

If you have in a loop something like this:



a = 0

b = 0
c = 0
d = 100
e = 100



Use this instead:



a = b = c = 0

d = e = 100




>> Attaching moviclips: for loop vs. while loop

A typical program loop where you attach movieclips to a target mc.

Using the while loop instead of for results in better performance, and if you're also

reading data from an array (this is shown in the next benchmark) then the for in loop should be the best choice.

So instead of using:



for (var i=0; i<1000; i++)
{
// code here
}



You should use:



var i=-1

while (++i < 1000)
{
// code here
}




>> Var name lookup



This test shows how important is saving name lookup time especially when inside a looping structure.

Instead of calling Math.random() at every cycle, define a reference to it and use it in the loop, this will save you time because the function name is resolved once, before entering the loop.



Example:



var num = null

t = getTimer()
for (var i=0; i < MAX; i++)
{
num = Math.floor(MAX) - Math.ceil(MAX)
}
t1.text = "Always lookup: " + (getTimer() - t)





is not as good as:



t = getTimer()

var floor = Math.floor
var ceil = Math.ceil
for (var i=0; i < MAX; i++)
{
num = floor(MAX) - ceil(MAX)
}




>> Declaring var in loops vs. declaring before loops

Before running this benchmark we thought that declaring a local var before a loop

structure could save some xtra time, but tests proved the exact contrary.



// Inside

t = getTimer()
for (var i=0; i < MAX; i++)
{
var test1 = i
}
t1.text = "Inside:" + (getTimer() - t)


// Outside
t = getTimer()
var test2
for (var i=0; i < MAX; i++)
{
test2 = i
}




>> Using nested if

Whenever using complex conditional expressions you can optimize the code by breaking them into single nested conditions.

This way you don't have to evaluate all the expressions all the times.

The following code is what we used for the benchmark: even if the conditional expressions are pretty simple the speed increse is significant.

Also you can notice that the expression that evaluates as false is in 3rd position, so you may even get better performance when it is placed in 2nd or 1st position.



MAX = 20000

a = 1
b = 2
c = -3
d = 4

var i=MAX
while(--i > -1)
{
if (a == 1 && b == 2 && c == 3 && d == 4)
{
var k = d * c * b * a
}
}


var i=MAX
while(--i > -1)
{
if (a == 1)
{
if (b == 2)
{
if (c == 3)
{
if (d == 4)
{
var k = d * c * b * a
}
}
}
}
}




>> Accessing local vars (This vs. With vs. Reference)

Local variables and objects can be referenced in more than one way.

We've tested two ways to do it and found out that the usage of the keyword this produces the worst results.

More speed can be achieved using with operator.



obj = {}

obj.a = 1
obj.b = 2
obj.c = 3
obj.d = 4
obj.e = 5
obj.f = 6
obj.g = 7
obj.h = 8
obj.test1 = useThis

obj.test2 = useWith


MAX = 10000


function useThis()
{
var i = MAX
while(--i > -1)
{
this.a = 1
this.b = 2
this.c = 3
this.d = 4
this.e = 5
this.f = 6
this.g = 7
this.h = 8
}
}


function useWith()
{
var i = MAX
while(--i > -1)
{
with(this)
{
a = 1
b = 2
c = 3
d = 4
e = 5
f = 6
g = 7
h = 8
}
}
}




>>Math.floor() vs int()

Instead of using the new Math library floor() function try the old-fashioned int()




Compiling for flash player 6 using Flash MX 2004:

One of the interesting things with FMX 2004 is that the actionscript compiler has been improved under many aspects.

The new compiler does a better job with both global (player 6 and 7) and local register (player 7 only) making some of the tweaking presented here less important.



You can see by yourself, from our benchmark table, that some very interesting results were achieved.



The most noticeable improvements we noticed were that _global variables seems to be a lot faster than timeline variables and nested loops now perform way better than before.

Also you will notice that almost every test run faster than the Flash-MX compiled version.







Tuesday, September 28, 2004

WHAT’S A THIN CLIENT?

You know an IT concept has real value when its meaning starts being obfuscated, when a lot of people want to take a ride on the hype train. This is where we’re at today with thin clients. There’s a lot of debate about how thin these devices must be to be truly worthy of the name, or how thick they can be while still delivering most of the advantages.
Thin clients are those that, one way or another, do without hardware or software that was previously considered essential. These skinny devices usually lack floppy and hard drives, and they employ as little memory and processing power as they can reasonably get away with.
When you are attempting to evaluate desktop devices for thinness, you should use the locations where processing and storage are actually carried out as criteria. The ultimate, original thin client was an ASCII terminal—a keyboard and screen unit that merely echoes characters sent from a remote location. That’s too thin for most of today’s needs, but many other options exist.
A true thin client should be stateless. In other words, applications and data are stored on a server (ideally, so should the client device’s OS, if one is even required). Clients acquire a state only when a user switches one on and logs on to a server. Management, therefore, is unnecessary, and users can roam from desk to desk seamlessly.
Sometimes termed a thin client (but actually rather toward the thick end of the scale) is the Network PC, or NetPC, offered by Compaq (the iPaq), Dell (the WebPC), Hewlett-Packard (the e-Vectra), and others. NetPCs use standard Intel processors and Windows OSs, but they have been “locked down” in that they have neither floppy drives nor expansion slots. Peripherals, if any, are connected via Universal Serial Bus (USB) ports.
Omitting local storage and booting NetPCs from a server, as with yesterday’s “diskless workstations,” is feasible, at least for those that contain the required boot ROMs. However, most implementations include local hard drives, sometimes trendily redubbed “cache” and sometimes not. Therefore, NetPCs are vulnerable to hard disk failure.
Because NetPCs are designed to execute applications locally, they need all the processing power and memory upgrades of an ordinary PC, with the early obsolescence that implies. If, in addition, administrators attempt to achieve statelessness by storing all applications on servers, then there is a significant effect on network bandwidth consumption.
Another thin-client wannabe is the NC developed by IBM, Oracle, and Sun Microsystems. Truly thin by virtue of its statelessness, this downloads its OS as it boots, then executes Java applications both locally and remotely. Problems? Apart from the lack of coveted Windows support, the demand for network bandwidth is relatively high—especially when multiple units are switched on simultaneously—and so is the processing power required at the desktop.
Almost as expensive and potentially obsolete as a PC, the NC was appealing only to Java zealots, and thus basically doomed at birth. Trying again, Sun recently replaced it with the SunRay, a fascinating device that relies on switched 100Mbit/sec Ethernet connectivity, but, in return, becomes the thinnest possible client.
The SunRay, which has audio capabilities and can drive a 1,280-by-1,024 display, contains only a moderate-performance SPARC CPU and 2Mbytes of main memory. No software is stored or executed on the device; instead, it is run and rendered on a server, then streamed to the SunRay via UDP. User input, such as keystrokes and mouse clicks, is returned to the server in a similar manner.
“This might not be the thin client for you if you primarily want to run Windows applications,” says Gene Banman, Sun vice president and general manager for information appliances. “Going into the future, though, software development should be aimed at Web APIs—and this will be the lowest-cost way to run them. The SunRay ought to be usable for 10 years or more.”
While such devices might inherit the earth, today’s market leader is the Windows-Based Terminal (WBT) architecture developed by Citrix Systems ( http://www.citrix.com/). Citrix has been working on thin clients for 10 years (it released a multiuser version of OS/2 in 1990), and it doubled its user base to more than 15 million in 1999.

Monday, September 27, 2004

AMFPHP

An Open-Source Alternative for Flash Remoting




Introduction


This is the project page for the AMFPHP project, aka Flash Remoting for PHP.


Ubiquity, stability, and platform neutrality make PHP the perfect server side scripting language for building server side applications, handling business logic, and connecting to web services. Ubiquity, stability, and platform neutrality make Macromedia Flash MX the perfect tool for deploying rich internet front ends. Flash remoting for PHP offers a seamless connection between the flash client and php server applications.


Flash remoting for PHP enables objects in PHP to become objects in actionscript, almost magically! AMFPHP takes care of all the data-type conversions, serialization, and other client-server details. This provides a great way of connecting rich media clients with data and logic living on the server. While at the same time allowing designers to design and programmers to program.


While this project is progressing please follow the following links:


Friday, September 24, 2004

Shared Object in Flash

"Lou Montulli, the protocols manager in Netscape's client product division, wrote the cookies specification for Navigator 1.0, the first browser to use the technology. Montulli says there's nothing particularly amusing about the origin of the name: 'A cookie is a well-known computer science term that is used when describing an opaque piece of data held by an intermediary. The term fits the usage precisely; it's just not a well-known term outside of computer science circles.'"

In the broadest sense, a cookie allows a site to store state information on your machine. This information lets a Web site remember what state your browser is in.

Haven’t we wished that you had some feature that enables you to store and retrieve cookies in Flash? In fact you can.
It is called SharedObject

mySharedObject = SharedObject.getLocal( objectName [, localPath ])objectName can be a text string(excluding ~ % & \ ; : " ' , < > ? # and SPACE). You can also use “/” in the objectName. Eg:
myso = SharedObject.getLocal( “fuel”); //creates a local storage file called fuel.sol
myso = SharedObject.getLocal( “fuel/rajesh”); //creates a folder called #fuel and local storage file called rajesh.sol within that.

You can use the same objectName in different movie swfs. Using the same name won’t clash the objects. This is because, Macromedia stores each object within a folder by the name of that movie. That is, a getLocal call from nav.swf is stored in a folder nav.swf (full file name, with extension, is used for folder name).


mySharedObject.flush([ minimumDiskSpace ])

Immediately writes a locally persistent shared object to a local file. If you don't use this method, Flash writes the shared object to a file when the shared object session ends—that is, when the SWF movie is closed. If you set the optional minimumDiskSpace (integer), that much byte will be allocated for the file. By default it is zero.
If flash was able to store the data, this method returns true or else false.
If the disk space usage exceeds allocated size for the website, flash pops up a window and asks the user to allocate/de-allocate disk space for the site. While the window is open, the flush() method returns a “pending” value.


The user is able to manage the disk space allocation for the storage file. By default, Macromedia Flash MX can save locally persistent remote shared objects up to 100 K in size. When you try to save a larger object, the Macromedia Flash Player 6 displays the Local Storage dialog box, which lets the user allow or deny local storage for the domain that is requesting access. Make sure your Stage size is at least 215 x 138 pixels; this is the minimum size Macromedia Flash MX requires to display the dialog box.

mySharedObject.getSize();
This method returns the current size of the shared object, in bytes.

mySharedObject.data
This property is used to store and retrieve data in the local storage.

Eg:
visitedArray = new Array();
visitedArray[0] = 1;
visitedArray[1] = 0;
visitedArray[2] = 1;
visitedArray[3] = 1;
mySharedObject.data.userName = “Rajesh”;
mySharedObject.data.languageID = “1033”;
mySharedObject.data.lastUnitVisited = “m2p3u2”; //stores text
mySharedObject.data.progress = 20; //stores numeric
mySharedObject.data.visitedUnitsArray = visitedArray; //can store arrays as well!!!
mySharedObject.flush();


mySharedObject.onStatus
mySharedObject.onStatus = function( infoObject ) {
//add code to trap the error
}
onStatus Event handler is invoked every time an error, warning, or informational note is posted for a shared object. If you want to respond to this event handler, you must create a function to process the information object generated by the shared object. infoObject parameter contains the status message information.

"status" , "warning" , or " error" are some of the common infoObject parameters. Apart from that, some class/methods return additional information.
Eg:
mySharedObject.flush.Failed // A SharedObject.flush command is returned when "pending" has failed (the user did not allot additional disk space for the shared object).
mySharedObject.Flush.Success //A SharedObject.flush command that returned "pending" has been successfully completed (the user allotted additional disk space for the shared object).


Important: This works with FlashPlayer 6 and above. Also the user needs to allow adequate local storage permission.