Inicio

November 26, 2005

How to write unmaintenable code

And old link, that I lost, and that I found again yesterday. I love the opening quote: " Never ascribe to malice, that which can be explained by incompetence"

A funny read: how to write unmaintenable code

November 23, 2005

[Cocoa] Memory management and exceptions

In languages like Java and actionscript, the "runtime" manages memory, using what is called a garbage collector, that reclaims the memory occupied by an object once it determines that object is no longer accessible. In Objective-C, the programmer must release the resources that he or she has previously allocated to be used by the program.

Memory management is not difficult by itself, because the developer must follow only a few rules, but it is the source of many memory leaks, specially when the program behaves in an unexpected way.

So, what happens when we need to throw exceptions?. How can we be sure that we are not producing memory leaks?. Chris Hanson writes about it in Cocoa memory management & exceptions

November 03, 2005

Tomorrow in the papers

design-nation is in the papers. In the October's issue of MacWorld Spain, there is an articles written by me, the First Contact with Macromedia Studio 8.

Even with that article, the magazine is full of interesting contents, like a report about the .Mac services, an in-depth article about iMovieHD or a comparison between all the Macs.

If you can read Spanish, you should buy it...

November 01, 2005

Design patterns poster

I am sure you have heard about the Head First series and about the Head First Design Patterns book, because it is probably the best introductory book to understand design patterns.

Last week I was browsing amazon when I found this item: Head First Design Patterns Poster.

designPatternsPoster.jpg

As its name says, it is a poster (a big one, in fact) that contains a graph (taken from the original book), not an UML diagram but a graph that explains the pattern and also the page number of the pattern in both the Gang of four and Head First Design Patterns.

It visually summarizes 18 patterns, and it is attached to the wall in front of my computer right now...

(By the way, all the links in this post will NOT earn me a comission).

October 18, 2005

And the pattern was...

Strategy. That was the name of the pattern in yesterday's post.

October 17, 2005

An example of the guess-its-name pattern

UPDATED: This is the Strategy Pattern. So, the title of the post could be "An example of the strategy pattern in actionscript"

Professor Coupling has been enjoying his well deserved hollidays after conquering the world (yes, since the last time we knew about him he seems to have succeeded with his evil plan).

But ruling the world is quite boring. Professor Coupling misses the old times, when nobody understood him, when he could hate all the world's leaders because they ignored him... Now he has to deal with a lot of paperwork everyday, and he misses when he could hang around with his troops, telling jokes, and drinking beer.

So, he has decided that, to combat this mortal boredom, he wants to see a millitary parade everyday. A different parade everyday, formed by a different selection from his troops. One day he will ask his Marshal to form a parade with the cows from the company B, another day he will want a parade formed by all the sheeps whose name contains an "a"... Evil geniuses...

Continuar leyendo "An example of the guess-its-name pattern" »

September 20, 2005

Flash 8 examples source code

We have updated our previous posts about flash 8, adding the source code:

[Flash 8] Blur filter

[Flash 8] Glow filter

[Flash 8] The sun and its shadow

PS: If you feel that the same functionallity can be achieved with flash 4, build an example, and post a comment with a link to the source code. Thanks

August 10, 2005

[Flash 8] The sun and its shadow

Drag the sun around the earth, and see how the shadow of the earth changes. Of course, you will need the flash player 8 public beta




For this example, I've used the following new features: movieclip filters ( glow, dropshadow and bevel ) that I change dinamically when the position of the sun changes. To calculate distances and angles, I have also used some of the new classes developed for geometrical calculations.

UPDATE 20/9/05: download the source code

August 08, 2005

[Flash 8] Glow filter




Click on the stage

UPDATE 20/9/05: download the source code

[Flash 8] Blur filter





Click on the stage

UPDATE 20/9/05: download the source code

August 04, 2005

An example of the memento pattern ( the actionscript version )

Conquering the world is not easy. You and me both know it. And Professor Coupling knows it too.

He has the knowdlege, he has a plan, he has the skills, and he has even the looks, but there are a lot of little details to care for before he can finally conquer the world!!.

In previous posts, be have seen how he has implemented the prototype pattern ( to create his army of clones –hey, I’ve just noticed the joke- ), the extension objects pattern ( to assign their roles ), the command pattern ( to assign them their orders ) and the observer pattern ( to implement a communications system ). It seems that Professor Coupling has had a lot of work, but was it enough?. NO!! ( muhahahahahahaha ).

Continuar leyendo "An example of the memento pattern ( the actionscript version )" »

June 17, 2005

DRY, and by the way, encapsulate what will change

Don't repeat yourself. When you write the same code more than once, you are starting to paint yourself into a corner.

See, for instance, this example.

I'm working on an application where I'm going to use the UI components. It's a MVC application, so the view is completely abstracted from the application's logic.

There's more than one view ( there are many different screens where I have to show the model data in different ways ), so I've thought that it will be better to build a different class for each view ( each screen ).

So, each view will attach a movieclip that contains the screen's graphics and interactive elements ( buttons, datagrids, whatever ). All those view inherit from a class that implements event dispatching, and some more common code. That's one reason to not inherit from movieclip. There are other ones, but I should not want to discuss them now. Anyway...

Also, I still don't have the definitve graphic assests. Even more, if the budget is big enough, I'll have to develop my own set of components, and use it.

So, imagine that you run the application. The first screen you'll find will be the login screen.

encapsulate.jpg

As you see in the screenshot, that screen contains a component. Here's the LoginView code:

import mx.utils.Delegate; class LoginView { private var timeline : MovieClip; private var loginScreen: MovieClip; function LoginView( tl: MovieClip ) { this.timeline = tl; } public function init( ) { this.loginScreen = this.timeline.attachMovie( "LoginScreen", "LoginScreen", this.timeline.getNextHighestDepth( ), { _x: 0, _y: 0 } ); this.loginScreen.loginBtn.label= "Go!"; this.loginScreen.loginBtn.addEventListener( "click", Delegate.create( this, click ) ); } private function click( ) { trace( "click" ); } }

So, when I want to show that screen, I'll do something like:

var loginView: LoginView = new LoginView( this ); loginView.init( );

And the button doesn't work. It doesn't even shows the right message. Some minutes of googling, and a bit of common sense and knowledge of the platform, told me that maybe, the button is not initialized when the movieclip is attached, so maybe I should wait a frame to assign its text.

import mx.utils.Delegate; class View { private var timeline : MovieClip; private var loginScreen: MovieClip; function View( tl: MovieClip ) { this.timeline = tl; } public function init( ) { this.loginScreen = this.timeline.attachMovie( "LoginScreen", "LoginScreen", this.timeline.getNextHighestDepth( ), { _x: 0, _y: 0 } ); var theView: View = this; this.loginScreen.onEnterFrame = function( ) { theView.initButton( ); delete this.onEnterFrame; } } private function initButton( ) { this.loginScreen.loginBtn.label= "Go!"; this.loginScreen.loginBtn.addEventListener( "click", Delegate.create( this, click ) ); } private function click( ) { trace( "click" ); } }

It's solved. But this solution smells ( not only because of the scope trick ). I'll have various screens that contain components ( maybe 10-12 ), so I'll have to write that code in 10 classes. Sure, I could write a base class and move that code to that base class, but that's not a solution, because not all my views will have the same amount of buttons, so there's not sense in subclassing just to override later. And my views are subclasses of another base class yet.

Even worse, probably, I'll have to develop my own components, so maybe, that code will have to be changed.

So, I'm repeating code, and that code will be probably changed in a near future. What should I do?. Encapsulate it into its own class.

To do so, I'll use my old Callback class:

class Callback { private var callbackObjVal: Object; private var callbackMethodVal: String; public function Callback( objParam: Object, methodParam: String ) { this.callbackObjVal = objParam; this.callbackMethodVal = methodParam; } public function fire( parameter: Object ): Object { return this.callbackObjVal[ this.callbackMethodVal ]( parameter ); } }

So, I'll write a ButtonHandler class:

class ButtonHandler { public static function initButton( mc: MovieClip, callback: Callback ) { var cb: Callback = callback; mc.onEnterFrame = function( ) { cb.fire( ); delete this.onEnterFrame; } } }

And I'll use it this way:

import mx.utils.Delegate; class View { private var timeline : MovieClip; private var loginScreen: MovieClip; function View( tl: MovieClip ) { this.timeline = tl; } public function init( ) { this.loginScreen = this.timeline.attachMovie( "LoginScreen", "LoginScreen", this.timeline.getNextHighestDepth( ), { _x: 0, _y: 0 } ); ButtonHandler.initButton( this.loginScreen, new Callback( this, "initButton" ) ); } private function initButton( ) { this.loginScreen.loginBtn.label= "Go!"; this.loginScreen.loginBtn.addEventListener( "click", Delegate.create( this, click ) ); } private function click( ) { trace( "click" ); } }

Overkill?. Well, the solution is a bit complex, but it's the one that most satisfies me, because it's the one that brings more flexibility. If I have to change the way I manage the buttons, I just have to change the implementation of one method in one class, and I don’t have to change any interface. I'm coding for the interface, not for the implementation.

June 02, 2005

An example of the Observer pattern

Be aware!. Professor Coupling and his army of clones are ready!.The final attack is going to be launched quite soon!. And their weapons are actionScript and design patterns!

In the previous posts, we’ve seen how Professor Coupling is able to clone any animal, and how he’s able to assign different roles to those clones. Oh, and he has also found the way to assign any animal its orders. Muhahahahahaha

Continuar leyendo "An example of the Observer pattern" »

April 26, 2005

An example of the Command Pattern

Everything is ready. The sheeps and the cows are cloned, and their roles have been assigned. It’s time for Professor Coupling to launch the final attack. It’s time to conquer the world!!!.

But how will Professor Coupling give his troops the order to launch the attack?.

Continuar leyendo "An example of the Command Pattern" »

April 06, 2005

An example of the Extension Objects pattern

Do you remember Professor Coupling?. Do you remember his evil plans to conquer the world?.

Today, we’ll see how the Extension Objects pattern ( or “how to change the interface that a class implements at runtime” ) has helped Professor Coupling. It won’t be an easy task, because this is a complex pattern, but who said that being an evil genius was easy?.

Continuar leyendo "An example of the Extension Objects pattern" »

March 29, 2005

An example of the Prototype Pattern

Professor Coupling is a Spanish scientific that is planning to conquer the world. Do you want to read about the problems he encountered, and how he solved them using the prototype pattern?

Continuar leyendo "An example of the Prototype Pattern" »

February 14, 2005

A situation where we shouldn't extend movieclip

You know that you can assign an as2 class to any movieclip symbol in the library. If that class extends movieclip, when you attach the symbol, you get an instance of that class. But you don’t even need to attach the symbol. You can just put the symbol on the stage at design time, and that’s enough to materialize that class when the timeline gets to the frame where the movieclip is located. That can be helpful when you are building an interface. You just put, for instance, a movieclip that represents a button on the stage, and *magic*, you have an instance of its associated class.

So, imagine you have to create an interface similar to this one:

the interface

Continuar leyendo "A situation where we shouldn't extend movieclip" »

December 14, 2004

Get your Flash Lite Content submitted for the contest!

I guess you've heard it yet, but Macromedia has opened a contest to see who develops the coolest Flash Lite application. And they are going to give out a lot of cool and expensive prizes!

Here are the details of the contest:

http://www.macromedia.com/mobile/special/contest/

Obviously, you'll need to test your applications in a mobile device. You can request the Flash Lite player for your handset, sending an email to flashlite_contest@macromedia.com, sending also your handset model and IMEI.

If you want to know if your device is supported, you can take a look at:

http://www.macromedia.com/mobile/supported_devices/#tmobile

Hurry up!. The contest closes February 1, 2005. Show the world what you can do!

December 13, 2004

[PPC] The model-view-controller architecture applied to a pocket pc application

This is a extremely simple application, but it can be an example of how to develop pocket pc applications using and adapting the movel-view-controller architecture. And I’ve also used the Delegate class!.

Continuar leyendo "[PPC] The model-view-controller architecture applied to a pocket pc application" »

December 02, 2004

Some practical benefits of OOP

If you're an experienced developer, I'm afraid you won't find this post interesting.

But, if you're starting to learn about object oriented programming, maybe you've heard about its benefits, about how an object oriented approach can help in developing and maintaining your applications. But, is it true?. Does oop really make our work easier?.

Continuar leyendo "Some practical benefits of OOP" »

November 08, 2004

Inner classes in AS2?

ActionScript does not support the creation of inner classes, at least, not in the way that Java does.

Manuel de la Higuera has made an interesting post about how to implement inner classes in ActionScript, and the effect they have on performance. I think it's worth to be checked.

Design patterns considered harmful?

An interesting discussion about the "over designed" systems. Does the use of design patterns encourage over-engineering?.

In this discussion at the c2 wiki, you could find the opinions of people supporting the use of design patterns, and people that thinks that they should not be used always. And also, a lot of links to very interesting resources. A must read.

So, here's the link:

Design patterns considered harmful

Favour composition over inheritance ( and III )

But there are more heavy weight reasons to favour composition over inheritance.

First, inheritance doesn’t allow to change the implementations of the subclasses at run time, and breaks encapsulation, because the implementation of the superclass is visible through the subclasses.

Continuar leyendo "Favour composition over inheritance ( and III )" »

Favour composition over inheritance ( II )

What happens if our class hierarchy is extremely deep?. Any change in any of the superclasses will mean that we’ll have to make a lot of changes in many different parts of our program.

Continuar leyendo "Favour composition over inheritance ( II )" »

Favour composition over inheritance( I )

Inheritance is a powerful tool. I can´t imagine my work without it. But it's not good to rely only on inheritance. Composition can be a better solution for many of our problems.

A few weeks ago, someone told me that the discusion about inheritance vs composition was like the discusion about PC vs Mac. But I don't think so. I believe that there are many points that suggest that we should favour composition.

Continuar leyendo "Favour composition over inheritance( I )" »

October 19, 2004

[software] Maxivista

MaxiVista can turn any Laptop or Tablet PC into an extended monitor of your primary PC. Program windows can be moved and extended across both screens as they would be one big monitor. Just connect up to four PCs via network and enjoy the extended desktop real estate.

Continuar leyendo "[software] Maxivista" »

September 29, 2004

An example of the abstract factory pattern

This is one of the creational patterns, whose intent is to provide an interface for creating families of related or dependent objects without specifying their concrete classes.

I’ll try to explain it using a "real life" example. Let’s suppose I want to decorate my house. And let’s suppose that there are only two different furniture shops in the town I live. One of them sells modern designs, and other one sells classic furniture. And let’s suppose again, that I’m only going to buy a door and a tv set ( I don’t have too much money ). And, finally, let’s suppose that I can buy the same items in both shops ( doors and tv sets ).

So, if I want to buy a tv set, I just have to any of the shops and ask for one tv set ( and pay it, of course ). And after having it properly installed at home, I know I can do some certain things with my tv set ( switch it on and off, pump the volume up,… ). And those actions could be done both with a modern tv and with and old one, although could be applied in a different way.

Well, I know I can go to the shop ( the modern one or the classic one, depending on what I exactly want ), but I could also pay someone to go and buy my tv and bring it home. I will only have to say "please, bring me a modern tv", and he / she should know that, to buy a modern tv, he / she should go to the “modern” shop and pay for a tv set. This guy / gal is the abstract factory. I don’t care how or what he / she does to bring a modern tv, I just want me tv now.

Before the as2 implementation, it’s time to point out something important. ActionScript doesn’t implement abstract classes. Sure, I can write a class that acts as an abstract class, but the fact is that the language doesn’t support them. So, although the GoF book says that the abstract factory and the factories should extend an abstract class, my implementation will be based on interfaces.

Well, back to code. If I go to the shop myself, or if I ask someone to bring me a tv, I just have to say “I want a tv”. So, both the shops and the guy that buys the tv will implement a common interface ( just to say it clearly, they should extend an abstract class, if possible, but as actionscript doesn’t implement them, they will just implement the same interface ).

Here is the interface:

import net.designnation.patterns.AbstractFactory.* interface net.designnation.patterns.AbstractFactory.IFactoryActions { public function getTV( ): ITVActions; public function getDoor( ): IDoorActions; }

There are two actions: getTV and getDoor ( "bring me a tv", and "I want a new door" ).

This is the code for the two shops:

import net.designnation.patterns.AbstractFactory.* class net.designnation.patterns.AbstractFactory.ModernShop implements IFactoryActions { function ModernShop( ) { trace( "I've picked a modern shop" ); } public function getTV( ): ITVActions { return new BrandNewTV( ); } public function getDoor( ): IDoorActions { return new ModernDoor( ); } }

import net.designnation.patterns.AbstractFactory.* class net.designnation.patterns.AbstractFactory.ClassicShop implements IFactoryActions { public function ClassicShop( ) { trace( "I've picked a classic shop" ); } public function getTV( ): ITVActions { return new OldTV( ); } public function getDoor( ): IDoorActions { return new ClassicDoor( ); } }

Both classes ( shops ) implement the same interface : IfactoryActions ( in other words, they implement two methods: getTV, and getDoor ).

Let’s take a closer look at the getTV method:

public function getTV( ): ITVActions { return new OldTV( ); }

Are we creating an instance of the OldTV class, but this method returns an interface?. Sure. That’s what lets us manage all the TV sets the same way. We won’t have to care about where we bought the tv (if it is modern or classic). We just will know that we can do some actions ( switch it on,… ). So, the two classes that represent the two kinds of tv sets will implement the same interface:

interface net.designnation.patterns.AbstractFactory.ITVActions { public function pumpUpTheVolume( ); public function shutUp( ); }

The modern TV will be:

import net.designnation.patterns.AbstractFactory.* class net.designnation.patterns.AbstractFactory.BrandNewTV implements ITVActions { function BrandNewTV( ) { trace( "I've received is my new 42 inches plasma TV" ); } public function pumpUpTheVolume( ) { trace( "sure, let me find the remote..." ); } public function shutUp( ) { trace( "By pressing down this key, the sound dies" ); } }

And the classic one:

import net.designnation.patterns.AbstractFactory.* class net.designnation.patterns.AbstractFactory.OldTV implements ITVActions { function OldTV( ) { trace( "I've bought an old TV" ); } public function pumpUpTheVolume( ) { trace( "My old tv has no remote, so I must wake up and pumpUpTheVolume myself" ); } public function shutUp( ) { trace( "My old tv has no remote, so........" ); } }

And will do the same with the doors. If the door is a modern one or a classic one, there will be the same actions: opening and closing it. So, now, the common interface that both classes will share is:

interface net.designnation.patterns.AbstractFactory.IDoorActions { public function open( ); public function close( ); }

The modern door:

import net.designnation.patterns.AbstractFactory.* class net.designnation.patterns.AbstractFactory.ModernDoor implements IDoorActions { function ModernDoor( ) { trace( "ModernDoor constructor" ); } public function open( ) { trace( "the modern door is opened" ); } public function close( ) { trace( "the modern door is closed" ); } }

The classic one:

import net.designnation.patterns.AbstractFactory.* class net.designnation.patterns.AbstractFactory.ClassicDoor implements IDoorActions { function ClassicDoor( ) { trace( "ClassicDoor constructor" ); } public function open( ) { trace( "the classic door is opened " ); } public function close( ) { trace( "the classic door is closed" ); } }

Well, it’s the moment to stop, and look back. We have two shops. Both shops sell doors, and tv sets. The classic shop sells classic doors and tv sets, and the modern one sells moderns TVs and doors.

The guy we send to the shop to bring us a tv will be the abstract factory:

import net.designnation.patterns.AbstractFactory.* class net.designnation.patterns.AbstractFactory.AbstractFactory { public static var MODERN : Number = 1; public static var CLASSIC : Number = 2; public static function getFactory( shopType: Number ): IFactoryActions { if ( ( shopType & MODERN ) == MODERN ) { return new ModernShop( ); } if ( ( shopType & CLASSIC ) == CLASSIC ) { return new ClassicShop( ); } } }

This class implements the same interface that both ModernShop and Classic shop implement. So, I will only have to say: “hey, abstract factory, bring me a modern tv”, and I could forget about the details of the process. And the end of the process I’ll have a tv set, but I will not know how it came home, where it was built, or sold…. But how?. Look:

import net.designnation.patterns.AbstractFactory.* var factory: IFactoryActions = AbstractFactory.getFactory( AbstractFactory.MODERN ); var myTV: ITVActions = factory.getTV( ); myTV.pumpUpTheVolume( ); var myDoor: IDoorActions = factory.getDoor( ); myDoor.close( );

You can download the code here

September 20, 2004

Flashblog: Flash / php / mySQL opensource weblog

Flashblog is an opensource blogging system, based on Flash, php and mySQL, that has been developed by some members of the spanish-speaking community.

Although it is not available yet, an initial release is expected in October. Right now, the project and the website are only in spanish, but here is the link, just in case you want some more info.

Flashblog.org

September 09, 2004

Flashtival 2004

The largest Flash and Webdesign conference of the Benelux will take place on Monday 27th September.

Flashtival 2004 will be an informative and educational event, completely related to Macromedia Flash, webdesign and Rich Internet Application development.

The Flashtival 2004 program is divided into 3 concurrent tracks, which are: "development", "animation and design", and "general Flash related topics". This way, every visitor will be able to attend a masterclass at his own level and choose the subject of his personal interest.

At the Flashtival website, http://www.flashtival.nl, you will find a complete list of all speakers.

Flashtival 2004 takes place at Congress Centre De Doelen in Rotterdam, Holland.

August 29, 2004

The State pattern and game development ( IV and final )

Well, finally it's time to develop a full game.

This is how our microgame ( "Drops everywhere" ) will work. Drops keep popping on the screen, but we ensure that the number of drops on the screen is lower than a given number. We can remove a drop by clicking on it. And we have to maintain a low number of drops during a given time. If we succeed, we can play again, or finish the game. If we play again, the maximum number of drops will be lower, so we’ll have to click more of them in the same time. The game goes on and on until we decide to finish it, or until the number of drops is higher than the allowed number.

You can see a statechart diagram here.

The code is distributed in three layers. There’s a model, a view, and a controller, although it is not structured as a MVC. The controller listens to the events fired by the model, and notifies the model when there is an action in the view ( a button click, for instance ).

The initialization process of the game is the following: when the swf is loaded, an instance of DropsController is created. This object creates an instance of DropsWorld, registers itself as an event listener, and starts the state machine associated to the world. The class DropsWorld extends another class called EventSource( in the package net.designnation.events ), that provides the ability to fire events , and to register listeners to those events. The controller ( DropsController ) also creates an empty MovieClip, that will be the main “clock”.

So, when the world is created, we have to start its state machine:

public function initWorld( param: Object ) { this.stageMC = param.baseline; this.initBehaviour( ); var theClass: DropsWorld = this; this.base_MC.onEnterFrame = function( ) { theClass.doProcess( ); } this.mySMachine.startMachine( ); } private function doProcess( ) { this.BEngineVal.doProcess( ); }

So a new cycle of the state machine will be executed with every execution of the base_MC.onEnterFrame event.

We define the state machine here:

private function initBehaviour( ) { var initGame : State= new State( "initGame", new CallbackDecl( this, "initGameAction" ) ); var startGame : State= new State( "startGame", new CallbackDecl( this, "startGameAction" ) ); var createDrop : State= new State( "createDrop", new CallbackDecl( this, "createDropAction" ) ); var overDrops : State = new State( "overDrops", new CallbackDecl( this, "overDropsAction" ) ); var endOfTime : State= new State( "endOfTime", new CallbackDecl( this, "endOfTimeAction" ) ); var defeat : State= new State( "defeat", new CallbackDecl( this, "defeatAction" ) ); var victory : State= new State( "victory", new CallbackDecl( this, "victoryAction" ) ); var endOfGame : State= new State( "endOfGame", new CallbackDecl( this, "endOfGameAction" ) ); new Transition( "initGameToStartGame", initGame, startGame, new CallbackDecl( this, "initGameToStartGameEval" ) ); //---------------------------------------------------------- new Transition( "startGameToCreateDrop", startGame, createDrop, new CallbackDecl( this, "startGameToCreateDropEval" ) ); //---------------------------------------------------------- new Transition( "createDropToEndOfTime", createDrop, endOfTime, new CallbackDecl( this, "createDropToEndOfTimeEval" ) ); new Transition( "createDropToOverDrops", createDrop, overDrops, new CallbackDecl( this, "createBubbleToOverDropsEval" ) ); new Transition( "createDropToSelf", createDrop, createDrop, new CallbackDecl( this, "createDropToSelfEval" ) ); //---------------------------------------------------------- new Transition( "overDropsToDefeat", overDrops, defeat, new CallbackDecl( this, "overDropsToDefeatEval" ) ); //----------------------------------------------------------- new Transition( "endOfTimeToVictory", endOfTime, victory, new CallbackDecl( this, "endOfTimeToVictoryEval" ) ); new Transition( "endOfTimeToStartGame", endOfTime, startGame, new CallbackDecl( this, "endOfTimeToStartGameEval" ) ); //------------------------------------------------------------- new Transition( "defeatToEndOfGame", defeat, endOfGame, new CallbackDecl( this, "defeatToEndOfGameEval" ) ); //------------------------------------------------------------- new Transition( "victoryToEndOfGame", victory, endOfGame, new CallbackDecl( this, "victoryToEndOfGameEval" ) ); this.mySMachine.resetToInit( initGame ); }

Once the states and the transitions are defined, we must implement the callbacks needed.

The class that we use to manage the drops is a very light controller. It also extends EventSource, so it will be able to fire an event when the drop is clicked. I know the way I’ve implemented this functionallity can start an endless discussion, but I’ve decided that a drop is a drop, not a MovieClip, so the MovieClip with the drop graphic is aggregated to the Drop class, and the Drop class does not extend MovieClip.

I’d also like to say that obiously this is not the final implementation. A lot of the DropsWorld code should be common for any game that we develop, so it will be wise to put that common functionallity on a base class, and make DropsWorld extend that class. The game itself is not completely finished ( there’s an obvious lack of feedback ), but, in general, I believe this example can be considered as a start point. And, for your information, the development time has been of about an hour and a half.

Well, the final result is here:

And the source code can be downloaded here ( don’t forget to set your classpath ).

Packages:
net.designnation.behaviours
net.designnation.data
net.designnation.events
net.designnation.physics
net.designnation.PoppingDrops ( game classpath )

I’d also like to thank Celia Carracedo for the game graphics.

And, finally, a disclaimer. There are some days when I find really dificult to express my thoughts in english. Today was one of them.

August 21, 2004

macromedia.com has gone mobile?

Well, maybe this is not new for many of you, but I've noticed today that the whole macromedia.com site can be browsed from my pocketpc. It's amazing!.

I've just created an avantgo channel to read the flash developer center articles offline. ;)

Congratulations. Good work!

August 20, 2004

Cool flash application ( pocketpc )

Mobilympics is a cool pocketpc application that will help you keep track of seven sports during the Olympic Games, developed by pc de bolso.

If you own a pocketpc, I think it's worth a try, but bear in mind that the program is provided as 'Ad-ware' meaning that you will find some information about the developer's sponsors ( mostly HP ) when entering and leaving Mobilympics.

August 13, 2004

Socket Server

Thanks to my brother César, I have noticed this Socket server at freshmeat. I have just downloaded it, and i´ll make some tests soon. It can be hosted in any machine running PHP5. It sounds interesting.


Project in freshmeat
CSS ( Cyber Socket Server )
freshmeat

The authors claim that it is similar to Flash Communication Server, and that it can be seamesly integrated in our flash applications.

August 12, 2004

Sound.onSoundComplete: ¿Bug or feature?

Maybe this is common place, but it's something that has surprised me.

The problem I've found is related to the last posts I've made about the state machines.

I've been testing a game that I developed some time ago. At a given moment, a transition must be executed when a sound is finished ( that means that something must happen when a sound is finished ). But, although the game always worked, today it didn't!!.

After a two hours debugging session, I've just tried to play the game in a different computer, and it worked!!. And then I remembered. I reinstalled the operating system of my development machine two days ago, after my holydays ( sniff :-( ), and the new system didn't recognize the sound card. In fact, if I look at my control panel, I see that there are not audio devices installed.

So what has happened?. It seems that the onSoundComplete event is never triggered. I don't know if it's the expected behaviour or not, but well, it's something I must remember!

July 12, 2004

The State pattern and game development ( III )

So, it's time for some code.

You can download the code here. But you should take a look also at the linked list and hashmap we published some time ago, because we will need them now.

We have implemented four classes
Transition ( transitions )
State ( states )
SMachine ( state machine )
BEngine( behaviour engine, it's the one that manages all the game's state machines )

Things will work the following way: first we'll create the state machine that we are going to need, then we'll add it its states and transitions, and then we'll register that state machine in the global behaviour engine ( BEngine ). That behaviour engine will have a timer, so it will control the state machines execution.

First, we'll take a look at this engine. To simplify, it's just a list that holds a reference to each state machine that has been registered. So we can add new state machines to that list, remove a machine from it…

class BEngine { private var machineListVal: List; public function BEngine( ) { this.machineListVal= new List( ); } public function registerSMachine( machine: SMachine ) { this.machineListVal.push( machine ); } public function unregisterSMachine( machine: SMachine ) { this.machineListVal.deleteElement( machine ); } public function doProcess( ) { var it: IIterator= this.machineListVal.iterator( ); while( it.hasNext( ) ) { SMachine( it.next( ) ).executeCycle( ); } } }

The state machine is not a collection with all the states and transitions. However, we hold only a reference to the first state and the current state. Why? Because the states will be linked by the transitions, so we don't need to know all the states of the state machine, only the first one, and the current one ( so we can evaluate its transitions). However, we have to know if the machine is running, or is stopped.

class SMachine { . . . . public function resetToInit( initState: State ) { this.currStateVal = initState; this.initStateVal= initState; } . . . . }

Each state will hold a callback and an array with a reference to all the transitions that start at that state

class State { . . . . public function addTransition( transition: Transition ) { if( transitionDoNotExist( transition ) ) { this.transitions.push( transition ); } } . . . public function evalState( paramater: Object ): fgPair { var nextState: State= undefined; var retPair: Pair; var nTam: Number= this.transitions.length; for( var nIx: Number= 0; nIx< nTam && nextState== undefined; nIx++ ) { var currentTransition: Transition= this.transitions[ nIx ]; if( currentTransition.evaluate( ) ) { if( this.__traceInfo__ ) { trace( "TRANSIT:"+ this.id+ "->"+ currentTransition.endState.id+ " BY "+ currentTransition.id ); } nextState= currentTransition.endState; retPair = new fgPair( nextState, currentTransition ); } } return retPair; } public function execute( parameter: Object ): Object { if( this.__traceInfo__ ) { trace( "S[A]:"+ this.id+"; "+ this.actionCallbackVal.callbackMethod ); } return actionCallbackVal.fire( parameter ); } . . . . }

And last, the transitions. Each transition holds a reference to the initial and the final state and has the ability to execute a callback

class Transition { . . . public function set initState( state: State ) { state.addTransition( this ); this.initStateVal= state; } public function set endState( state: State ) { this.endStateVal= state; } . . . public function execute( parameter: Object ): Object { if( this.__traceInfo__ ) { trace( "T[A]:"+ this.id+"; "+ this.actionCallbackVal.callbackMethod ); } return this.actionCallbackVal.fire( parameter ); } public function evaluate( ): Boolean { var retVal: Boolean= true; if( this.evaluationCallbackVal!= undefined ) { retVal= Boolean( evaluationCallbackVal.fire( this ) ); } return retVal; } . . . }

Well, now it's time or an example. But that will be in another post.

July 07, 2004

The State pattern and game development ( II )

As we explained in the previous post, we’ll try to manage the object’s behaviour as a collection of related states, so the entity that implements that collection of states ( or state machine ) will be able to transit from one state to another. So we’ll have a classs ( Bubble ) that aggregates a collection of objects ( the states ) and a graphic to manage its presentation ( a movieclip ).

We are going to implement a non-hierarchical, non-concurrent state machine. If you want to read a deeper essay about state machines, I strongly recommend to take a look at FlashSim or quantum-leaps ( thanks to Jonathan Kaye for the links ). We will try to make things as simple as possible for the shale of performance ( remember, we are developing a game ).

First, here are two UML diagrams ( statechart diagrams ):

The bubble statechart

The game world statechart

Let’s take a closer look at the last diagram. There can be seen the different states that we’ve defined:

1.- initGame: General game initialization.
2.- initRound: General initialization of each game round. There will be setted the exploded bubbles counter, the time counter,…
3.- gamePlay. The user is playing the game.
4.- endOfTime: The time is over. We’ll check is the player has exploded enough bubbles.
5.- defeat. The player has not exploded bubbles enough. Ohhhhhhh.
6.- newChallenge. We offer the player the chance to play again, or to leave the game. If the player chooses to play again, we’ll move to initRound, and if the player chooses to leave the game, we’ll move to endOfGame.
7.- endOfGame. The game is over. We can send the player score to a server side script, …

Well, now that the concept has been explained we’ll try to explain how the state machine works.

First of all, when we enter a state an action is executed. In the most common state machine implementation there are three actions for each state, one will be executed when entering the state, another one when the state is executed, and another one when we leave the state. In this example, we’ll try to make everything as simple as possible, for the shake of performance, and we’ll execute just one action for each state.

Each arrow represents a transition. Each state contains a collection of transitions. This transitions can be callbacks that return a Boolean value, so the state machine will move by the transitions that returns a value of true. Usually, these transitions evaluate a given property of the class, and return true or false. Let’s explain it a bit more.

The state machine is closely tightened to a timer. So with every tick of the timer, some logic is executed ( all the transitions that start at the actual state are evaluated ), and state machine will move using the first transition that evaluates as true. So it will move to another state, where ( when the next tick occurs ) it will execute that state action. And next, it will evaluate more transitions, and…

Before taking a look at some code, we’ll try to explain it better going back to the Bubble class ( and diagram ). Let’s remember that this class is not a MovieClip subclass, but a complex entity that aggregates its state machine, and a movieclip.

So, when we create an instance of this class, and we create and start its state machine, will be in the first state: initBall. So, the state action ( initBallAction ) will be executed, and this action will attach a movieclip, and place it on stage. Then it will set a class flag ( isInitFlag, for instance ) to true, and it will set another flag to false ( isOutOfBoundsFlag ). With every timer tick, the transitions associated to this state will be evaluated ( here, there’s only one transition, that starts at initBall, and ends at moveBall ). So if that transitions returns the value of isInitFlag, it will return true, so the state machine will transit to the next state ( moveBall ).

This state has three transitions: the first one , that ends at itself, aonther one that ends at outOfBounds, and another one that ends at destroyBall.

So these transitions will evaluate ( in order ) the following flags: isOutOfBounds== false; isOutOfBounds == true and isClickedFlag == true.

When this state action is executed, first, we’ll calculate the next position of the bubble. Then, we’ll check if that position is out of the stage ( that includes bouncing against the floor ). If the bubble is out of stage, well set isOutOfBounds to true. So, if the bubble as not gone out of the stage, that flag will still be false. So, the transition that will return true will be the one that moves the state machine to the same state ( isOutOfBounds == false ), so well enter again the same state, so we’ll calculate the next ball position again,….

If the ball goes out of the stage, the transition that ends at outOfBounds will be the one to return true. So, the state machine will move to that state, where we’ll change the ball position or its velocity, and then we’ll return again to the moveBall state.

In the next post, we’ll see the code to implement all this, but now, the most important thing is to understand that is the entity itself the one that, just checking the value of some internal flags, changes it’s behaviour. And that that behaviour is separated in a collection of different objects.

There will be more soon.

July 05, 2004

The State pattern and game development ( I )

We are going to try to implement the State pattern to help us develop complex games or games whose entities have a complex or reactive behaviour.

First, we must consider that this implementation is quite lazy, and the example we're going to explain is simple enough to be explained, but with some complexity, so we can consider to implement this solution. Obviously, as the complexity of the game behaviour, or the complexity of the game entities behaviour grows, this will become a better solution. And also remember that my English is very poor, so, please, be nice :$

So, let's start. First, let's see what "state pattern" means. The intent is: Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. ( here you can find a complete explanation )

So, this pattern should be a good solution when , for instance:
1.- The behaviour of an object depends of its internal state, and must change at runtime depending of that state.
2.- To describe the object's behaviour we use long conditional sentences, with multiple branches. We'll try to put each branch in a different object .

So, in other words, we will try to describe an object's behaviour as a collection of different states, in a way that the object itself could manage its behaviour moving from one state to another.

Sounds interesting, isn't it?. Let's try to build an example.

Now we need some imagination. Imagine we have to develop a game ( "Explode the bubble" ). There will be a given number of bubbles on the stage that bounce when they hit the ground, but that don't bounce against the walls ( I mean, if a bubble leaves the stage by its right side, it must appear again by the left side, and the opposite ). There's a given time to explode a given number of bubbles ( clicking them ). When a bubble explodes, another one appears, so there's always the same number of bubbles on stage. The initial position and velocity ( velocity as a vector, not speed ) are setted randomly. So, if we explode less than the minimum number of bubbles, we loose, but we explode more than that minimum number, we are offered to give it another try. Then we can leave the game, or try again, but we'll have to explode more bubbles in less time. And so on., until we loose, or we leave the game.

At first sight, we can separate our code into two different entities: the game world, and the bubble, so we could write two different classes. The first one will manage the top level logic ( putting bubbles on stage, checking if there have been enough exploded bubbles, checking if the time is over… ), and the second one will manage the bubble behaviour ( bounces, explosions,… ). Let's take a closer look at the last one.

Obviously, the graphic representation of the bubble will be a MovieClip. So we could think about the Bubble class as a subclass of MovieClip, where the onEnterFrame method will be responsible of checking if the ball has left the stage, if it must bounce against the floor, that places the ball on the stage depending of those circumstances ( in other words, that implements a mechanism to calculate the bubble's movement equation ), that detects when the user has clicked the ball, and tells it to the game world, that manages the explosion animation…..

Well, I guess this is not the moment to discuss about inheritance and composition ( I hope so, at least ). Anyway, I don't think there's a right way and a wrong way of doing things ( or of writing code ). But, in this case this approach doesn't seem to be the most appropriate.

First, our Bubble class will have to implement a wide open range of functionalities ( from physical behaviours to just graphics presentation ). So the cohesion will be very low. And that's not very good. ( in other words: keep complexity manageable ).

But also, the Bubble behaviour should be implemented using a long switch statement, or a lot of "if" sentences ( if it must bounce, make it bounce; if it leaves the stage, put the bubble in it's new position; if nothing else happens, just calculate its new position and place it ). And that's one of the scenarios to implement this pattern. And, not in this case, but if the entity's behaviour is reactive, everything makes even more sense.

Have we stimulated your curiosity?. There will be more soon.

June 09, 2004

An example of the proxy pattern

I want to save a list of registered users, but I don't know exactly where to save it. If the user selects a checkbox ( that represents the internet connection ), I'll send the data to a server-side script, in XML format. If the user unchecks the checkbox ( representing that there is not a physical internet connection ), I'll write the data to a Shared Object.

So, this is a mission for the Proxy Pattern!!. Why?. Because I want to isolate the proccess of saving data from the rest of the application, so I just want to say "hey, save this", and don't worry about how ( or where ) it is saved.

That's what this pattern does. The proxy class stores a reference to an object , that will be the real subject of the action. But, the proxy itself creates that object, so it can create an instance of one class or another depending on certain run-time conditions.

So, all the possible classes to be created by the proxy must implement the same interface. And, depending of the kind of proxy, it can be also a good idea to make the proxy class implement also the same interface, so, if needed, it can be replaced.

Some code will help to understand it. First the interface:

interface ISaveable { public function saveUserList( theList: Array ); }

Easy, isn't it?. We want to save a list of users, so we'll have to implement a saveUserList method

Now, the class that handles the "save to server" feature

class myXML extends XML implements ISaveable { private var userArray: Array; function myXML( ) { this.userArray = new Array( ); } function sendData( ) { //this.sendAndLoad( ); } public function saveUserList( theList: Array ) { trace( "The XML is handling the data" ); this.userArray = theList; //create the XML nodes, and send to server } }

Not too complicated. Just a public method to receive an array, and then I'll have to create the XMl nodes, and send the XML to the server.

Well, now the class that saves data to disk

class mySO implements ISaveable { private var theSO: SharedObject; private var userArray: Array; function mySO( ) { this.userArray = new Array( ); } public function saveUserList( theList: Array ) { trace( "The Shared Object handles the data" ); this.userArray = theList; } }

Again, this class implements ISaveable, so after receiving the data, it will try to save it to the contained Shared Object

Now, the tricky part. The value of the checkbox ( the connection status ) is represented here by a variable placed at _root. But, to get this variable value, I'll use a Singleton ( here you can find an implementation by Dave Yang ), That's just a way to have a global accesor to that value, but I prefer it that just using globals. Here is the singleton:

class singleton { private static var inst:singleton; private function singleton() {} public static function get instance():singleton { if (inst == null) inst = new singleton(); return inst; } public function isConnected( ): Boolean { return _root.connected; } }

And finally, the proxy class

class saveUserListProxy implements ISaveable { private var realClass: ISaveable; function saveUserListProxy( ) { var config: singleton = singleton.instance; var conFlag: Boolean = config.isConnected( ); if ( conFlag ) { this.realClass = ISaveable( new myXML( ) ); } else { this.realClass = ISaveable( new mySO( ) ); } } public function saveUserList( theList: Array ) { this.realClass.saveUserList( theList ); } }

So, finally, for this example, in the main timeline, we'll have

var connected: Boolean = false; var theUserList: Array = new Array( ); theUserList.push( { id: 0, name: "Cesar" } ); theUserList.push( { id: 1, name: "Javier" } ); var myProxy: saveUserListProxy = new saveUserListProxy( ); myProxy.saveUserList( theUserList );

And that's all. Test it changing the values of the variable "connected". And sorry for my poor english. It's been particularly poor tonight :(

May 30, 2004

Free sounds compilation

The spanish Ministry of Education offers about 5000 sounds in mp3 and wav format, that can be used freely in educational projects. If you can read spanish, it can be of your interest.

Here´s the link:
http://iris.cnice.mecd.es/bancoimagenes/sonidos/index.php

May 19, 2004

About class interfaces

Don't expect anything specially brilliant here. This is just an story that show how mastering interfaces can help you in your daily work ( as it has helped in mine )

I think I've blogged about it before, but here I go again. The last three months I've been working developing an AS2 framework to build games. We are approaching our first deadline ( next Friday ), so we don't have too much free time.

So, yesterday, I started the development of five games which are quite similar. We've called them "the disposition games", because, well, you have to place some items on screen in the right order. There are a given number of spots , and when you place one of the given items over it, some rules are checked, and then the item is placed or is moved back to its initial position.

There are five different games ( one is about placing children in the school bus, another one is about choosing the order of some tasks that must be completed before going on vacation… )

The architecture of the games is quite simple. There's a main class ( called "World" that aggregates another class called "Scenario" which contains the logic of the game ). So the world class is in charge of controlling the gaming time, sending data to server, loading the graphic and sound assets. The five games are so similar, that we've tried to build them with as much common code as possible.

We decided that we'll have a swf ( dispositionMotor )where the world is initialized, and that will load another swf ( nameOfGame.swf ), where the scenario and the game rules are contained. There will we only one "dispositionMotor" and five different "nameOfGame".

Right. So, now, there are two possibilities: first, we could have five different "world" classes, each one initializing the correct scenario, or we could try to have just one general "world" that could initialize different scenarios ( this one, this one!! )

Continuar leyendo "About class interfaces" »

May 03, 2004

Accordion component

This is a simple example of how the accordion component can contain other components. In fact it's the source code of the accordion implemented in this blog's homepage.

Here´s the final result:

It has three tabs, the first one contains a list component, the second one contains a tree component, and the third one contains a single movieclip

So, first of all, you have to drag an instance of the list component and an instance of the tree component to the stage, and after that, delete them both, so they are included in the lybrary

I've also placed on the stage an instance of the accordion component, and I've setted its width and height, and setted its instance name to "accordion" ( without the quotes ). Don't delete the accordion instance.

I've also created a movieclip that contains the contact information. It's linkage name is "contact" ( without the quotes )

I also want both the downloads and link sections to load its own data from XML files, so everything will be easier to maintain and update. So, you can see the downloads_en.xml here.

You can review the tree_en.xml file here

So, the actionscript code will load both the "downloads_en.xml" file and the "tree_en.xml" file and, when loaded, will set the dataproviders of the list and the tree:

import mx.controls.Tree; import mx.controls.List; //var language: String = "es"; _global.style.setStyle("fontFamily", "TrebuchetMS" ); _global.style.setStyle("fontSize", 12); _global.style.setStyle("themeColor", "haloOrange"); var ac = this.accordion; ac.createChild( List, "downloadsF", { label: "Downloads", _width: 200, _height: 236 } ); ac.createChild( Tree, "linksF", { label: "Links", _width: 200, _height: 236 } ); ac.createChild( "contact", "contactF", { label: "Contact" } ); var myList = ac.getChildAt( 0 ); myList.vScrollPolicy = "auto"; myList.dataProvider = [ { label: "loading data", data: 0 } ]; myListXML = new XML( ); myListXML.ignoreWhite = true; myListXML[ "theList" ] = myList; myListXML.onLoad = function( success ) { if ( success ) { var theDP: Array = new Array( ); var elements: Array = this.firstChild.childNodes; var numElem: Number = elements.length; for ( var k: Number= 0; k< numElem; k++ ) { theDP.addItem( { label: elements[ k ].attributes[ "label" ], data: elements[ k ].attributes[ "data" ] } ); } this[ "theList" ].dataProvider = theDP; } } if ( language=="es" ) { myListXML.load( "http://www.design-nation.net/enlaces/downloads.xml" ); } else { myListXML.load( "http://www.design-nation.net/enlaces/downloads_en.xml" ); } var myTree = accordion.getChildAt( 1 ); myTree.vScrollPolicy = "auto"; myTree.setStyle("openEasing", mx.transitions.easing.Back.easeInOut ); myTreeDataProvider = new XML(); myTreeDataProvider.ignoreWhite = true; if (language=="es"){ myTreeDataProvider.load("http://www.design-nation.net/enlaces/tree.xml?ran="+ Math.random()); }else{ myTreeDataProvider.load("http://www.design-nation.net/enlaces/tree_en.xml?ran=" + Math.random()); } myTreeDataProvider.onLoad = function(){ myTree.dataProvider = this; } eventListener = new Object(); eventListener[ "tree" ] = myTree; eventListener[ "list" ] = myList; eventListener.change = function(eventObject){ if ( eventObject.target._name == "linksF" ) { var theSelectedNode = eventObject.target.selectedNode; var theSelectedNodeLabel = theSelectedNode.attributes.label; var esLink = theSelectedNode.attributes.isLink; var esBranch = this.tree.getIsBranch( theSelectedNode ) if ( esBranch ){ if ( this.tree.getIsOpen( theSelectedNode ) ){ this.tree.setIsOpen( theSelectedNode, false, true ); }else{ this.tree.setIsOpen( theSelectedNode, true, true ); } }else{ if ( esLink ){ var theSelectedNodeURL = theSelectedNode.attributes.url; getURL( theSelectedNodeURL ); } } } if ( eventObject.target._name == "downloadsF" ) { getURL( myList.selectedItem.data ); } } myTree.addEventListener("change", eventListener); myList.addEventListener( "change", eventListener );

And that's all.

 

April 30, 2004

Button handler follow-up

A few weeks ago, I posted about the problem we were having, here at the office, with some buttons.

The feedback was great, but we decided to go on implementing the "solution" we found, just because of the few time we had.

But finally, we've had to make some changes in some buttons that are part of a modal dialog we are building

So, now we have a movieclip with three frames, labeled "normal", "over", and "click". The movieclip contains a textfield named "literal". We want to be able to assign the textfield contents, its format, and the onRelease handler, but we need to set that handler from a different point of the program execution ( I mean, we set the label text when the application initializes, but we set the onRelease handler depending on the execution flow )

So the button handler class is:

class net.designnation.UI.buttonHandler { public static function setBTHandlers( buttonInstance: MovieClip, texto: String ) { buttonInstance[ "textoParam" ] = texto; buttonInstance[ "literal" ].text = texto; buttonInstance.onRollOver = function( ) { this.gotoAndStop( "over" ); var theInstance: String = ""; this[ "literal" ].text = this[ "textoParam" ]; }; buttonInstance.onRollOut = function( texto ) { this.gotoAndStop( "normal" ); this[ "literal" ].text = this[ "textoParam" ]; }; buttonInstance.onPress = function( texto ) { this.gotoAndStop( "click" ); this[ "literal" ].text = this[ "textoParam" ]; }; } public static function setNewTextFormat( buttonInstance: MovieClip, format: TextFormat ) { buttonInstance.literal.setNewTextFormat( format ); } public static function setTextFormat( buttonInstance: MovieClip, format: TextFormat ) { buttonInstance.literal.setTextFormat( format ); } public static function setOnRelease( buttonInstance: MovieClip, value: Function ) { buttonInstance._onRelease = value; buttonInstance.onRelease = function () { this._onRelease( ); this.gotoAndStop( "normal" ); } } }

Have a nice weekend!

April 13, 2004

Button weirdness

The last time I had to work with buttons was at least two years ago, but today at work, we have received some graphic assets from a freelance designer, that has provided us with a lot of buttons.

These buttons have a textfield inside, and there are two different textfields, one for the "normal" state, and another for the "over state. So I wrote the following code to assign that dynamic fields text ( where "tf" is the textfield )

class net.designnation.UI.buttonHandler { public static function setHandlers( instanceName: MovieClip, text: String ) { instanceName[ "theText" ] = text; instanceName.onRollOver = function( ) { this.tf.text = this[ "theText" ]; } instanceName.onRollOut = function( ) { this.tf.text = this[ "theText" ]; } } }

It didn't work. So, I tried to trace the buton contents:

class net.designnation.UI.buttonHandler { public static function setHandlers( instanceName: MovieClip, text: String ) { instanceName[ "theText" ] = text; instanceName.onRollOver = function( ) { for ( var k in this ) { trace( k ); } this.tf.text = this[ "theText" ]; } instanceName.onRollOut = function( ) { this.tf.text = this[ "theText" ]; } } }

And here came my surprise. Maybe this is well know to all of you, but the result of the trace command was:

tabIndex
getDepth
enabled
useHandCursor
instance1

So, there was the textfield: instance2. But, when I rolled out, it traced "instance3". And when I rolled over again, it traced "instance4", and so on. It only happens when there are two different textfields. If there's only one textfield for all the button's states it always traces "instance1"

It was the first time I saw it, so it surprised me. By the way, the final solution was as easy as it seems ( althoguh it relies on something really weird ):

class net.designnation.UI.buttonHandler { public static function setHandlers( instanceName: MovieClip, text: String ) { instanceName[ "theText" ] = text; instanceName.onRollOver = function( ) { for ( var k in this ) { if ( k.substring( 0,8 )== "instance" && k.text != undefined ) { this[ k ].text = this[ "theText" ]; } } } instanceName.onRollOut = function( ) { for ( var k in this ) { if ( k.substring( 0,8 )== "instance" && k.text != undefined ) { this[ k ].text = this[ "theText" ]; } } } } }

But, how much time will it work?. I don't know

At least, I've found another reason to not use buttons, and use movieclips instead

April 06, 2004

Hash Table V2

About a month ago, I released an implementation of a Hash map ( or hash table ). Yesterday I found a bug when trying to delete an item under certain conditions, so here's the fix.

At the same time, I've made a few improvements.

You can see the original post here

And, of course, you can download the mxp file here

Happy easter! ( if it's a holiday for you, of course )

March 26, 2004

Is anybody using the mySQL panel?

About a month ago, we released an extension for the flash IDE, which contained a panel to browse a mySQL database, and a php class. ( you can read more about it here)

Well, there have been more than 1000 downloads yet, and we are a bit surprised, because we have not received any bug report, any report about installation problems,….

This has made us think what seems obvious: that nobody is using it.

Anyway, if you are using it, we'll like to know what do you think about it, what improvements, if any, you'd like to see in a future "release",….

March 25, 2004

Almost friday: a useless post

After a looooong day working on a class serializer, I needed to do something as light as possible. So here it is: a class that can be used as a timer.

You can execute any method, when a given time has passed, and after that reset the timer to use it as a timeout controller

It know that the actual architecture is based on events, but here you will also find a class to implement callbacks.

Continuar leyendo "Almost friday: a useless post" »

March 20, 2004

Developing an AS2 framework

For the last two months, I've been working on a huge AS2 framework, as part of a two year long project that includes the development of about two hundred games, apart from an e-learning platform.

This framework will be the base to develop those flash games. In fact, we are developing some simple games, with simple physics, in four ours.

We are basing our development in design patterns, mostly the state pattern, and also a lot of MVC, Singleton, Decorator and Facade patterns. We also are implementing all our backend in webservices.

I didn't find easy to adapt my coding practices and knowledge from my pure scripting background to such an abstract way of coding. But now, I must admit that not only the code will be really easy to maintain, but the development proccess is shorter and easier.

And, also, I've found that, apart from some problems with the compiler, the flash player ( or virtual machine ) has proved to be very reliable. Some of the games we've developed yet involve more than 200 classes, and the player has been managing them perfectly.

So, in fact, learning OOP is worth the effort ( and, at the end, this is flash, so there always comes the moment when you must / can apply all the things that really make me love this language: the flexibility, the ability to modify some of its core poperties, the procedural animations,....... ;P )

March 11, 2004

My coding standards

I've read about coding standards, or coding best practices recently ( like this one from Dominick ). Well, here are my coding standards:

First of all, code should be self-explanatory. So, in my place of work we don't write too many comments ( in fact we never write comments, although we write class diagrams, and a lot of UML ).

Here you can see an example class. I've commented it just to avoid a longer explanation:

/* The class name is cualified with the project name ( pn ) This class extends another class */ class net.designnation.pnTestClass extends pnSuperClass { /* Here are the private vars. They will be accesed through getter/setters so their name ends with "Val" */ private var strVal : String; private var boolVal : String; private var mcVal : MovieClip private var arg : Number; /* Then, you could find the class constructor */ function pnTestClass( argParam: Number ) { this.arg = argParam } /* Then the getter and setters We only define the methods that are needed to access the property from outside the class */ function set str( value: String ) { this.strVal = value; } function get str( ): String { return this.strVal; } /* Here we only define the setter. That's all we need */ function set bool( value: Param ) { this.boolVal = value; } function set mc( value: MovieClip ) { this.mcVal = value; } //The private methods private function privateMethod( Void ): Void { } // The rest of public and interface methods public function publicMethod( Void ): Boolean { //We are accessing a private property from //inside the class, so we don't need a getter var returnVal: Boolean = false; if ( this.boolVal ) { returnVal = true; } return returnVal; } /* And finally, all the callbacks and listeners */ public function onKeyUp( ) { } }

Some important points: We allways use the prefix "this.", so it's easier to see when a method or a property belongs to the class. If there is no "this" prefix, it means that it's a method or property of the superclass

Spacing is very important for us. It makes our code easier to read, and to understand. We don't mind about the code size, there are always a lot of whitelines.

Brackets are always paired. And there is also a white space between operators.

Also, all methods that return a value must have only one return point.

Hope it helps. Sure it does for us.

March 09, 2004

Hello, MXNA!

We've just recieved an e-mail telling us that this blog will be aggregated by MXNA. We feel really proud, and a bit scared, because of all the people that will read our posts from now on.

Anyway, we just wanted to say hi. We'll be glad to receive your comments, suggestions, rants, ....

And we hope you could find some useful information around here.

And last, but not least, a big "thank you" to the people at MXNA.

March 01, 2004

Design patterns: MVC ( the correct implementation? )

Yesterday, Darron Schall pointed that my implementation wasn't really a Model-View-Controller, because the view should listen to the events boradcasted by the model.

The fact is that I've been using the implementation I posted yesterday for so long, that I forgot that it wasn't correct. So, I've refactored my code, and here are the results.

Now, the controller aggregates an instance of the view, and and instance of the model. The view listens to the model's events, and uses the controller to access the model.

I'm not really sure about my code, I don't know if this is the best way to implement this pattern, so I'll be glad to hear any suggestions.

Anyway, you can download the source code here

Design patterns: almost MVC ( model-view-controller )

We'll build a reverse clock. The clock starts when the stage is clicked, and can be stopped clicking the stage again.

To read a really good article about what the MVC pattern is, click here

Basically, we'll try to break our application into three layers. The model (application data and logic ), the view ( the interface) and the controller ( responsible of updating the data when the interface changes, and responsible of updating the interface when the data changes ).

In this example, the model is a AS2 class, that will count the remaining time. With every second, this class fires an event, that is listened by the controller, that will update the view, which is a textfield that shows the remaining time. When we click the stage, the view tells de controller to change it's state, and the controller will tells the model to do so ( to stop if it was running, or to run if it was stopped ).

First, you must be sure that swf loading order ( File-> Publish settings-> swf-> loading order ) is set to "down to up". So, the controller will be created on the first frame of the first layer, and the view will be created in the first frame of the second layer.

To create the controller instance:

import net.designnation.patterns.* var myController: controller = new controller( this ); myController.init( 60 );

The controller aggragates an instance of the model:

public function init( time: Number ) { this.myClock = new clock( this.timeline, time ); this.myClock.addEventListener( "endOfTime", this ); this.myClock.addEventListener( "updateTime", this ); this.myClock.init( ); }

So, when the clock instance is created, it receives two parameters, a reference to _root, and the total time, so:

public function init( ) { this.clockClip = timeline.createEmptyMovieClip( "empty", this.timeline.getNextHighestDepth( ) ); this.clockClip[ "owner" ] = this; this.clockClip.onEnterFrame = function ( ) { if ( this[ "owner" ].workingFlag ) { if ( this[ "owner" ].actualTime>= 1 ) { this[ "owner" ].actualTime--; if ( this[ "owner" ].actualTime % FRAMERATE == 0 ) { this[ "owner" ].dispatchTime( this[ "owner"].actualTime ); } } else { this[ "owner" ].dispatchTime( ); delete this.onEnterFrame; } } } }

When I write

this.clockClip[ "owner" ] = this;

it's exactly the same than:

this.clockClip.owner = this;

The brackets just help me see that it's a dynamically created variable.

When a second has passed, an event is fired:

private function dispatchTime( actualTime: Number ) { if ( actualTime == null ) { var event = "endOfTime"; } else { var event = "updateTime"; } this.dispatchEvent( {type: event, target: this, time: ( actualTime/ FRAMERATE ) } ); }

The controller is registered as a clock listener so the following method is executed:

public function updateTime( arg: Object ) { this.timeline.clock.text = arg.time; }

so the view is updated.

When we click the stage:

this.onMouseUp = function( ) { myController.changeClockState( "clock" ); }

So, in the controller:

public function changeClockState( ) { this.myClock.changeClockState( ); }

And finally,

public function changeClockState( ) { this.workingFlag = !this.workingFlag; }

So, every message between the view and the model is carried by the controller. So the graphics and the application logic are separated, so our application will be easier to maintain, our code will be easier to understand....

And again, we've mixed AS2 and AS1 code.

Download the source files here

February 17, 2004

Data structures: Hash table

A hash table is a short of collection of linked lists. It allows us to store pairs data-object, and later retrieve the data using its key

You can view a detailled explanation of what a hash map is here

And you can download my AS2 implementation here

To test it you could try something like this:

import net.designnation.structs.* var a: HashMap= new HashMap( ); // Setitem // key= "4"; trace( "Adding "+ key ); a.setItem( key, new Object( key ) ); trace( "HashMap contents: "+ a ); key= "21"; trace( "Adding "+ key ); a.setItem( key, [ "a1", "a2" ] ); trace( "HashMap content: "+ a ); key= "5"; trace( "Adding "+ key ); a.setItem( key, new Object( key ) ); trace( "HashMap content: "+ a ); key= "8"; trace( "Adding "+ key ); a.setItem( key, new Object( key ) ); trace( "HashMap content: "+ a ); key= "81"; trace( "Adding "+ key ); a.setItem( key, new Object( key ) ); trace( "HashMap content: "+ a ); key= "8"; trace( "Adding "+ key ); a.setItem( key, new Object( key ) ); key= "8"; trace( "Retrieving "+ key ); trace( a.getItem( key ).toString( ) ); // Count // trace( "Count: "+ a.count( ) ); // Remove // key= "4"; trace( "Removing "+ key ); a.remove( key ); trace( "HashMap content: "+ a.toString( ) ); trace( "Count: "+ a.count( ) );

Good night!

February 09, 2004

Linked list V2

The FIVE of you that follow this blog, will remember my last post, about how to use my linked list class.

As promised, here's a better and cleaner implementation. It works exactly as the first version, except the method "insert", that now is called "insertOrdered".

So download it here

February 01, 2004

A linked list implementation

I hope this will be adult enough ;)

This is an implementation of a simple linked list. It needs some optimization (the method deleteElement relies on deleteElementAt, maybe I sholudn't use indexes to iterate trough the list,...) but it's a start. I will post an optimized version as soon as I finish it

Anyway, here's how it it works. To create an instance of the list, we have to pass it as a parameter an instance of a "comparator" class. That "comparator" class defines a lessThan() method that compares two objects. Depending of the kind of object we want to store in our list, we can define this method. For example, if we want to order the list depending on a property called "index", the "comparator class should look like this:

class net.designnation.structs.Comparador implements IOrder { function Comparador() { } public function lessThan( firstComp: Object, secondComp: Object): Boolean { if (firstComp.index< secondComp.index) { return true; } else { return false; } } }

So, we'll create an instance of the list like this:

import net.designnation.structs.*; var myList:List = new List(new Comparador());

And then, to populate it...

myList.push({index:6, prop:"propvalue6"}); myList.insert({index:3, prop:"propvalue3"}); trace("Lista " + myList); myList.insert({index:0, prop:"propvalue0"}); trace("Lista " + myList); myList.insert({index:2, prop:"propvalue2"}); trace("Lista " + myList); myList.insert({index:1, prop:"propvalue1"}); trace("Lista " + myList); myList.insert({index:4, prop:"propvalue4"}); trace("Lista " + myList); myList.insert({index:5, prop:"propvalue5"}); trace("Lista " + myList); myList.insert({index:7, prop:"propvalue7"}); trace("Lista " + myList); myList.insert({index:6, uno:"propvalue6"}); trace("Lista " + myList); Download it here .

January 19, 2004

A mySQL Flash panel

This is just something I'm using in my daily work.

This is a panel to browse the structure of a mySQL database. It's been tested only in a local environment, with both the webserver and the database server running at localhost.

This panel is not an administration interface. You cannot browse the tables records, and you cannot add, delete or modify those records.

Anyway, some kind of interactivity will be provided in the next release (maybe a "run query" funcionality).

Installation instructions
----------------------
1.- Unzip the content of the php folder and copy it to any folder of your webserver

Example: In a windows box, the destination folder could be

c:\apache\htdocs\databases\

2.- Using the Macromedia Extension manager, install the mxp file

3.- Start Flash. Open the panel form the menu Window->Other panels->databasesList_en

4.- Configuration:

4.1.-script: URL of the folder where the php files where copied:

http://localhost/databases/

Don't forget the final slash.

4.2.- host: mySQL server. Should be localhost

4.3.- User: mySQL user

4.4.- Password: mySQl password

If you have any suggestion, comment, bug report, please drop me a line.

Download the panel

January 16, 2004

Player or virtual machine?

I've just read a post by Darron Schall where he talks about the "virtual machine", instead of the "flash player".

The first difference between the flash player and the java virtual machine is size. Of course, that difference comes from the different funcionality provided. When programing in flash, we cannot acces the file system, the sytem configuration,....

But does it really make sense to try to do in flash the things that can be done in Java?. I'm not sure.

Maybe I'm wrong, but it seems that macromedia is trying to provide a new development platform. So we'll have Java (Sun), .Net (Microsoft) and Flash (Macromedia).

That sounds good, but I'm afraid we are really close to forget what flash has meant for all these years. I am very excited about our future as flash developers, but I don't want to forget about our past.

Any thoughts?

January 11, 2004

AS2 and prototypes

How could we make a method available to all movieclip instances?. It's easy, adding it to the movieclip prototype. But is it that easy when we code in AS2?

Now, we can't modify the movieclip class, we are only suppossed to extend it, addingh methods to its subclasses. ¿Sure?.

OOP theory says that, to add a method to the movieclip class, we should write something like this:

class net.designnation.exp.TestClass extends MovieClip{ function TestClass(){ trace("constructor"); } //This one is the new method we want to add private function methodAS1(){ trace("I'm the new method!"); } }

So this class inherits all the movieclip methods, and has a new method called methodAS1. But that method belongs only to TestClass. So, if we write a new class that inherits movieclip, we should define it's methodAS1 method.

Some of you, maybe have thought yet: we need many different classes implementing the same method, hmmmm, what about defining an interface?

interface net.designnation.exp.MCInterface{ public function methodAS1():Void; }

So, our class looks like this now:

import net.designnation.exp.*; class net.designnation.exp.TestClass extends MovieClip implements MCInterface{ function TestClass(){ trace("TestClass constructor"); } //Here we must implement method //that belongs to the interface private function methodAS1(){ trace("defined in the interface"); } }

Well, is our problem solved? Not completely. Now we are forced to implement a given method in all the classes that implement the interface. Just to remind you (and me): we want to implement a method only once, and make it accesible to all our classes.

Maybe the most elegant solutions will be to implement a class that inherits from movieclip, and implement our methodAS1 in that class. Then, we'll make all our classes inherit from that new class. But, you know, this is flash, let´s have some fun!.

So, in the first frame of our fla, we could write:

MovieClip.prototype.methodAS1 = function(){ trace("Done!. I'm the right method!"); };

And our class will look like this:

class net.designnation.exp.TestClass extends MovieClip{ function TestClass(){ trace("constructor"); } private function methodAS2(){ trace("I'm the class method"); }; public function onRollOver(){ //Runs the superclass method super.metodoAS1(); methodAS2(); }; }

To see this example in action, I've created a MovieClip drawing a circle inside it, that I'll use as a button. It's linkage name is ”MyClip” and the actionscript 2.0 class is “net.designnation.TestClass”.

So, back to the fla's first frame:

MovieClip.prototype.methodAS1 = function(){ trace("Done!. I'm the right method!"); }; //Attachs the movie, and instanciates TestClass this.attachMovie("MiClip", "instancia", 1);

So, what happens when moving the mouse over the clip?. Right!. We got it!. Well, not at all. We are running one of the superclass (MovieClip) methods, so what happens if we want to run another method of TestClass from its superclass?

If we change TestClass:

class net.designnation.exp.TestClass extends MovieClip{ function TestClass(){ trace("constructor"); } private function metodoAS2(arg){ trace("I'm the class method " + arg); }; public function onRollOver(){ //Runs the superclass method super.methodAS1(this); //methodAS2(); }; }

And if we change the method definition:

MovieClip.prototype.methodAS1 = function(ref){ trace("Done!. I'm the right method!"); ref.methodAS2("_width " + this._width); };

So, we've called a method of the superclass, passing it a reference to the class that called it. So, now, the superclass knows who's called it.

Congratulations if you didn't felt asleep.

Flare AS decompiler

Via swftools, i have found this tool. Take a look, this is an AS decompiler.

January 07, 2004

Resizable button

The problem: to make a button that could be resized without transforming the text.

The solution: building the button at runtime.

First, let's take a look at the final product:

Continuar leyendo "Resizable button" »

Defend your castle!

The Governor is trying to recover the castle!. Load your weapons!












We'll take a closer look at the source code in the following days.

Anyway, the graphics have been made by Celia Carracedo. Thanks, Celia!

December 30, 2003

My first jsfl (PublishAll)

Here's my first extension. A command that publishes all the open documents.

I know it's quite simple, but, well, you know, it's my first time...

Download PublishAll.mxp

December 29, 2003

Flexibility matters (AS2)

Yes, you guessed it, we can do something quite similar with the brand new AS 2.0

First of all, we’ll write a new class:

class net.designnation.exp.Dinamica{ public var prop1:String; public var prop2:String; public var prop3:String; function Dinamica(){ } public function metodo(Void):Void{ trace("method ------"); trace(prop1 + " " + prop2 + " " + prop3); } }

In the first frame of the main timeline, paste the following code:

import net.designnation.exp.*; var testClass:Dinamica = new Dinamica(); testClass.prop1 = "Hi!"; testClass["prop2"] = "I’m"; var cadena:String = "prop3"; testClass[cadena] = "testing"; //To retrieve tose values: for (var k=1;k<4;k++){ trace(testClass["prop"+k]); } //To execute the class method testClass.metodo(); //or testClass["metodo"](); //or var cadena2:String="metodo"; testClass[cadena2](); stop();

So, this is the way (at least one of the ways) to make one class method call another without even knowing it’s name, or to make one class call another one’s methods, ….

Anyway, this shows the power and flexibility of ActionScript.

Flexibility matters (AS1)

If we want to get or set any of the properties of an object, we can write something like this:

var miObj = new Object(); miObj.prop1 = "design-nation";

Although, we could have written something like:

var miObj = new Object(); miObj["prop1"] = "design-nation";

So, we can access an object properties dynamically, for example:

var miObj = new Object(); miObj.prop1 = "property1"; miObj.prop2 = "property2"; miObj.prop3 = "property3";

And we can retrieve those values like this:

for (var k=1;k<4;k++){ trace("prop"+k+ " = " + miObj["prop"+k]); }

But, what about the methods?. No problem. Let’s see:

var miObj = new Object(); miObj.metodo1 = function(){ trace("metodo1"); } miObj["metodo1"]();

That’s the way we can execute any given method of an object, without really knowing which one we are trying to access.

December 27, 2003

Tree component

Today, I've started to work in a new project where I need to use the new UI components

So, to test myself, I've made the little links thing that you can see on the right.

And I must say that everything has been fast and easy!:

_global.style.setStyle("fontSize", 12); myTree.setStyle("color", 0x999966); myTree.setStyle("borderStyle","solid"); myTree.setStyle("themeColor", "haloBlue"); // load and asign content myTreeDataProvider = new XML(); myTreeDataProvider.ignoreWhite = true; myTreeDataProvider.onLoad = function(){ myTree.dataProvider = myTreeDataProvider; } myTreeDataProvider.load("/enlaces/tree_en.xml"); myTreeListener = new Object(); myTreeListener.tree = myTree; myTreeListener.change = function(eventObject){ var theSelectedNode = eventObject.target.selectedNode; var theSelectedNodeLabel = theSelectedNode.attributes.label; var esLink = theSelectedNode.attributes.isLink; var esBranch = this.tree.getIsBranch(theSelectedNode) if (esBranch){ if (this.tree.getIsOpen(theSelectedNode)){ this.tree.setIsOpen(theSelectedNode, false, true); }else{ this.tree.setIsOpen(theSelectedNode, true, true); } }else{ if (esLink){ var theSelectedNodeURL = theSelectedNode.attributes.url; //trace("url " + theSelectedNodeURL); getURL(theSelectedNodeURL, "_blank"); } } } myTree.addEventListener("change", myTreeListener); stop();

The spanish version works also with the same swf.

Obviously the xml is generated as utf-8, so flash can display spanish and english characters.

Gravity (source code)

So here it is, with it's wonderful spanish comments :|.

As you could see, this code could and should be optimized to make it not so proccessor.intensive.

Anyway, it's a good example of how we can build our applications without referencing _root.

When the main class is initialized:

var miGravedad:Gravedad = new Gravedad(this);

A reference to the timeline where the main class is located is passed to the class constructor. So we avoid any future trouble.

So, download the source code (of course, if you wish to)

Gravity

Drag the circle, and watch it falling (it's relaxing, isn't it?).

Well, it's not a completely accurate model, but.....






December 26, 2003

Experiment 3.0

Still looking for some inspiration:






Experiment 2.0

I'm still bored, so....






Let's experiment!

Today, I've started to work in a new game, so I've been trying to recover my lost math skills

Until now, I've only written two siple functions: one that returns the distance between two points, and another one return the orientation of the vector defined by two points. And then, it was when I started to get extremely bored, so it's when I started to play. And here you have the result:







The code it's not optimized, but it's the first swf posted here, so....

You can download the source code (with some wonderful comments in spanish)here.

November 02, 2003

FlashCommand Flash 2004 Command Line Compiler

Mike Chambers has released this tool.

It can be easily integrated with the code editor of your choice, like EditPlus or SciTE|Flash

It needs the .Net Framework, and you can find all the information here

The new Flash IDE

This week I started working on my first full project developed in Flash MX 2004.

I'm a bit dissapointed with the new IDE. I expected a lot (of course, I had no reason to), but....

There's no class browser, no user classes codehints, no task list,.....

I know Macromedia has worked a lot on this, but I want a tool like IntelliJ IDEA

October 28, 2003

Let's move to Linux!

At last!!

Using CodeWeavers' CrossOver Office 2.1, Flash MX and Dreamweaver MX can run under Linux.

For many of us, it's a good chance to move to Linux.

Bye, Bill!!