Posts filed under 'actionscript'

How to create a PureMVC app with Actionscript 3

Update at: How to Add and Remove Mediators in an Actionscript 3 PureMVC App

PureMVC imageSo I have been working alot w/ PureMVC, well everyday for the last month to be exact. I’m going to try to explain PureMVC the best way I know how. It may not be the best, but I hope it can get you started. And when you learn something let me know.

So the example I am doing is a simple one using Lee Brimelow’s code from the ActionScript 3 Advanced XML example. The only difference between his and what I changed is some method name changes and putting it in PureMVC.

So if you don’t know what PureMVC is or you are quite confused on how to use it…well so am I . I’m still learned and hopefully can teach some stuff. I’m not going to go into the specifics of this framework but think of it as a way to introduce a lot separation of code using the Model, View, Controller. I’ll explain what I see as the benefits after I explain the example.

Look at lee’s example:

[as]var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onLoaded);

stage.addEventListener(MouseEvent.CLICK, changeColor);

var xml:XML;
var kuler:Namespace = new Namespace(”http://kuler.adobe.com/kuler/API/rss/”);
var ka:Array = new Array();
var cc:int = 0;

function onLoaded(e:Event):void
{

xml = new XML(e.target.data);
var il:XMLList = xml.channel.item;
for(var i:uint=0; i<il.length(); i++)
{
var sl:XML = il.kuler::themeItem.kuler::themeSwatches[i];
var co:Object = new Object();
co.c1 = sl.kuler::swatch.kuler::swatchHexColor.text()[0];
co.c2 = sl.kuler::swatch.kuler::swatchHexColor.text()[1];
co.c3 = sl.kuler::swatch.kuler::swatchHexColor.text()[2];
co.c4 = sl.kuler::swatch.kuler::swatchHexColor.text()[3];
co.c5 = sl.kuler::swatch.kuler::swatchHexColor.text()[4];
ka.push(co);
}
drawColors(ka[0]);
}

function drawColors(c:Object):void
{
graphics.beginFill(parseInt(”0x” + c.c1));
graphics.drawRect(0, 0, 200, 200);
graphics.beginFill(parseInt(”0x” + c.c2));
graphics.drawRect(200, 0, 200, 200);
graphics.beginFill(parseInt(”0x” + c.c3));
graphics.drawRect(400, 0, 200, 200);
graphics.beginFill(parseInt(”0x” + c.c4));
graphics.drawRect(600, 0, 200, 200);
graphics.beginFill(parseInt(”0x” + c.c5));
graphics.drawRect(800, 0, 200, 200);
}

function changeColor(e:Event):void
{
if(cc == ka.length – 1)
cc = 0;
else
cc++;
drawColors(ka[cc]);
}

loader.load(new URLRequest(”http://kuler.adobe.com/kuler/API/rss/get.cfm?listtype=rating&itemsperpage=20″));
[/as]

most everything but the drawColors() function are going into the dataProxy.
What’s a dataProxy…hold on.

Make sure you download the swc or classes.

Here is what we are working with:

  1. PurelyKuler (Main Class)
    1. call the facade
    2. pass the DisplayObject to the app (a PureMVC method)

    [as]package {
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;

    //your main class file. you know that!
    public class PurelyKuler extends Sprite
    {
    public function PurelyKuler()
    {
    stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;
    //get facade instance
    var facade:PurelyKulerFacade = PurelyKulerFacade.getInstance();
    // make sprite that will be the viewcomponent to the mediator
    var colorContainer:Sprite = new Sprite();
    addChild(colorContainer);
    //start it up and pass the sprite to the app.
    facade.startup(colorContainer);
    }
    }
    }
    [/as]

  2. facade (PurelyKulerFacade)
    1. create singleton
    2. starts the app
    3. registers the command (StartUpCommand) I haven’t explained that yet
    4. notify – PurelyKulerConstants.STARTUP and pass the DisplayObject

    [as]package
    {
    import com.joshspoon.etc.purelyKuler.PurelyKulerConstants;
    import com.joshspoon.etc.purelyKuler.controller.*;

    import org.puremvc.interfaces.IFacade;
    import org.puremvc.patterns.facade.Facade;
    import org.puremvc.patterns.observer.Notification;

    public class PurelyKulerFacade extends Facade implements IFacade
    {
    // Singleton Method
    public static function getInstance(): PurelyKulerFacade {
    if (instance == null) {
    instance = new PurelyKulerFacade( );
    }
    return instance as PurelyKulerFacade;
    }

    // Broadcast the STARTUP Notification
    public function startup(app:Object):void {

    notifyObservers(new Notification(PurelyKulerConstants.STARTUP, app));
    }

    // Register Commands with the Controller
    // like EVENT this is listening for STARTUP to excute the StartUpCommand
    override protected function initializeController():void {
    super.initializeController();
    registerCommand(PurelyKulerConstants.STARTUP, StartUpCommand);
    }

    }
    }[/as]

  3. SimpleCommand (StartUpCommand) – similar to your event handler
    1. registerProxy (KulerDataProxy) not spoke about yet
    2. registerMediator(PurelyKulerMediator) – not spoken of yet

    [as]package com.joshspoon.etc.purelyKuler.controller
    {
    import com.joshspoon.etc.purelyKuler.model.KulerDataProxy;
    import com.joshspoon.etc.purelyKuler.view.PurelyKulerMediator;

    import flash.display.*;

    import org.puremvc.interfaces.ICommand;
    import org.puremvc.interfaces.INotification;
    import org.puremvc.patterns.command.SimpleCommand;

    public class StartUpCommand extends SimpleCommand implements ICommand
    {
    override public function execute(notification:INotification):void
    {
    // Create and register proxy

    facade.registerProxy(new KulerDataProxy());

    // Create and register the mediator, colorContainer passed as the viewcomponent of the Mediator

    facade.registerMediator(new PurelyKulerMediator(notification.getBody() as Sprite));

    }

    }
    }[/as]

  4. Proxy (KulerDataProxy) – connects to databases/REST/and the like
    1. setup connection for xml
    2. expose a loadInfo method for request of data
    3. onKulerLoad method just like lee’s except it notifies DATA_LOADED and passes the array of colors

    [as]package com.joshspoon.etc.purelyKuler.model
    {
    import com.joshspoon.etc.purelyKuler.PurelyKulerConstants;

    import flash.events.Event;
    import flash.net.*;

    import org.puremvc.interfaces.IProxy;
    import org.puremvc.patterns.observer.Notification;
    import org.puremvc.patterns.proxy.Proxy;

    public class KulerDataProxy extends Proxy implements IProxy
    {

    public static const NAME:String = “KulerDataProxy”;
    private var _loader:URLLoader;
    private var _xml:XML;
    private var kuler:Namespace;
    private var _ka:Array;

    public function KulerDataProxy( data:Object = null )
    {
    super ( NAME, data );

    setupNetwork();
    trace(NAME + ” ready”);
    }
    // has everything to prepare the data request to Kuler.
    private function setupNetwork():void
    {
    kuler = new Namespace(”http://kuler.adobe.com/kuler/API/rss/”);
    _ka = new Array();
    _loader = new URLLoader();
    _loader.addEventListener(Event.COMPLETE, onKulerLoad);

    }

    // function called to start action of dataProxy
    public function loadInfo():void
    {
    _loader.load(new URLRequest(”http://kuler.adobe.com/kuler/API/rss/get.cfm?listtype=rating&itemsperpage=20″));
    }
    // this is an overriden inherited function from PureMVC
    override public function getProxyName():String
    {
    return NAME;
    }

    //when data is loaded
    private function onKulerLoad(e:Event):void
    {
    //for more info see: http://www.gotoandlearn.com/player.php?id=65
    _xml = new XML(e.target.data);
    var il:XMLList = _xml.channel.item;
    for(var i:uint=0; i<il.length(); i++)
    {
    var sl:XML = il.kuler::themeItem.kuler::themeSwatches[i];
    var co:Object = new Object();
    co.c1 = sl.kuler::swatch.kuler::swatchHexColor.text()[0];
    co.c2 = sl.kuler::swatch.kuler::swatchHexColor.text()[1];
    co.c3 = sl.kuler::swatch.kuler::swatchHexColor.text()[2];
    co.c4 = sl.kuler::swatch.kuler::swatchHexColor.text()[3];
    co.c5 = sl.kuler::swatch.kuler::swatchHexColor.text()[4];
    _ka.push(co);

    }
    trace(”co.c1: ” + _ka[0].c1);

    //once all the color data is pushed in to the array
    //send notifications
    facade.notifyObservers(new Notification(PurelyKulerConstants.DATA_LOADED, _ka));
    }

    }
    }
    [/as]

  5. Mediator (PurelyKulerMediator) -the view of the application
    1. create loading textField and add it to viewComponent(colorComponent)
    2. when data returns allow click
    3. draw colors.

    [as]// code created by Lee Brimelow http://www.gotoandlearn.com/player.php?id=65
    // modified by Josh Weatherspoon: http://etc.joshspoon.com/wp-content/uploads/2008/02/purelykuler_puremvc_example.zip
    package com.joshspoon.etc.purelyKuler.view
    {
    import com.joshspoon.etc.purelyKuler.PurelyKulerConstants;
    import com.joshspoon.etc.purelyKuler.model.KulerDataProxy;

    import flash.display.*;
    import flash.events.*;
    import flash.text.*;

    import org.puremvc.interfaces.IMediator;
    import org.puremvc.interfaces.INotification;
    import org.puremvc.patterns.mediator.Mediator;

    public class PurelyKulerMediator extends Mediator implements IMediator
    {
    public static const NAME:String = “PurelyKulerMediator”;
    private var _tf:TextField; // will display loading…
    private var _ka:Array = []; //array to hold color data from the Proxy
    private var cc:int = 0; // index in th _ka array

    public function PurelyKulerMediator(viewComponent:Object=null)
    {
    _tf = new TextField();

    super(viewComponent);// the colorContainer
    DisplayObjectContainer(viewComponent).addChild(_tf);
    loading();
    trace(NAME + ” started”);
    }
    // a PureMVC override
    override public function getMediatorName():String
    {
    return NAME;// passes name to access this in the app
    }
    // a PureMVC override
    override public function getViewComponent():Object
    {
    return viewComponent;
    }
    // what this mediator is listening for
    override public function listNotificationInterests():Array
    {
    return [PurelyKulerConstants.DATA_LOADED]
    }

    override public function handleNotification(notification:INotification):void
    {
    switch (notification.getName())// like Event.CHANGE
    {
    case PurelyKulerConstants.DATA_LOADED:
    _ka = (notification.getBody() as Array) // like evt.data
    changeColor();
    DisplayObjectContainer(viewComponent).addEventListener(MouseEvent.CLICK, changeColor, false, 0, true); //real events should only be in mediator and call change through notifications
    break;
    }
    }
    // calling the load method for the xml in teh proxy
    private function loading():void
    {
    _tf.text = “Loading…”;
    KulerDataProxy(facade.retrieveProxy(KulerDataProxy.NAME)).loadInfo();
    }
    //see lee’s example
    private function changeColor(e:MouseEvent = null):void
    {
    if(cc == _ka.length – 1)
    cc = 0;
    else
    cc++;
    drawColors(_ka[cc]);
    }
    //see lee’s example
    private function drawColors(c:Object):void
    {
    _tf.text = “”;
    viewComponent.graphics.clear();
    viewComponent.graphics.beginFill(parseInt(”0x” + c.c1));
    viewComponent.graphics.drawRect(0, 0, 200, 200);
    viewComponent.graphics.beginFill(parseInt(”0x” + c.c2));
    viewComponent.graphics.drawRect(200, 0, 200, 200);
    viewComponent.graphics.beginFill(parseInt(”0x” + c.c3));
    viewComponent.graphics.drawRect(400, 0, 200, 200);
    viewComponent.graphics.beginFill(parseInt(”0x” + c.c4));
    viewComponent.graphics.drawRect(600, 0, 200, 200);
    viewComponent.graphics.beginFill(parseInt(”0x” + c.c5));
    viewComponent.graphics.drawRect(800, 0, 200, 200);
    }
    }
    }
    [/as]

  6. Lastly the constants I use in PurelyKulerConstants

[as]package com.joshspoon.etc.purelyKuler
{
// a little excess for this example but I like having a global place to store contants
public class PurelyKulerConstants
{
public static const DATA_LOADED:String = “DataLoaded”;
public static const STARTUP:String = “Startup”;
}
}[/as]

You can expand this and make another proxy or mediator and plug and play pieces, since you code is not tightly coupled. That is what I see as benefit.

That should be it. I hope that helps

Enjoy!

source

4 comments February 13th, 2008

Yahoo Maps ActionScript 3.0 Released

I didn’t think this was going to happen with Yahoo Maps going Ajax and the maps hack they released last year (Yahoo! Maps API Flex 2 Communication Kit).

Check it out: http://developer.yahoo.com/flash/maps/

Add comment February 11th, 2008

Update: Flash/Flex Tidbit #2 How to use Alpha Mask in Flash CS3

Someone asked me to give an example of the alpha masking in flash. So here is an example.

Source

Add comment January 8th, 2008

I bought Actionscript 3.0 Design Paterns

My wife’s parents gave me the annual gift certificate to Barnes and Noble, so this year I got Actionscript 3.0 Design Patterns. I am excited about it. Last Christmas I got Advanced AS3 Design Patterns but I was just learning AS3 so I couldn’t figure out Design Patterns also.

I have since understood a good deal of the book but I think this one is a little more basic and has more examples. I hope I can apply these new ideas in to my new job as I am coding in a low-level manner so that the work can be used in either Flash or Flex.

Add comment December 26th, 2007

Custom ColorPicker Component – How to extend a Flash CS3 Component Class

Ok so at my last job I was working on a boat client’s site. They asked for me to do a color option flash piece in two days. So I thought what was the quickest and easiest way to convey color options to a potential buyer…A color picker. But I thought a conventional ColorPicker was ugly and had a lot of things I didn’t need like the hex code input. Secondly the ColorPicker has a bunch of colors and I only needed a few in one row. So I started getting into the Flash CS3 components code, found ColorPicker and ColorPickerEvent Class and extended them to do what I wanted. The result is the CustomColorPicker.

It uses almost everything the ColorPicker does except this color picker stays open for a time after you have selected a color. The picker event passes which index in the Array was selected and you can use that to listen for a color change and trigger an Array in you app to be used in tandem.

Only problem so far is it doesn’t register the first one selected (on INIT, which is 0) inside of the class yet. You have to do it in your app.

Custom Color Picker Image

In the working example, it loads xml and that is broken up in to VOs. Each VO’s color is pushed into an Array to be pushed into the CustomColorPicker’s colors property and when clicked it sends a message to change the view of the car, color text and color swatch of the corresponding index. For example if you click index 3, it get VOS_array[3].image, text and displays it.
All this is done on the inside all you have to do is grab the color and array index from the CustomColorPickerEvent.COLOR_CHANGE and you are good to go.

Please excuse the mess, I stripped the client data and grabbed images off of a google search of 08 Honda Civics, and changed up some stuff to look a little different. Leaving it ugly, but it looks good enough for you to get the use of the component.
Hope you like it and let me know if you have any improvements or question.

Source | Example

1 comment December 13th, 2007

Tidbit #3 – testing additions to your code – Control Variable

When when you add features to a class and they aren’t seeming to work, STOP. Your doing something that doesn’t jive w/ you code. You are overwhelmed w/ all the code you already have. You are missing something or your code just doesn’t work w/ what your trying to do.

Solution:

Simple, create a new class. Name it controlVariable (yep, just like in Science class). Try that troublesome code there all by its self. That way if it works in controlVariable then you know you code is correct and just the implimenation in you project is off. I feel this is very helpful when I’m in the trenches. Cause sometimes some code chunks don’t play well w/ others.
Don’t be prideful and recompile a swf for 2hrs just because you think, “I declared that Blue Rectangle, it should be there”. When you didn’t addChild or import or instantiate the Shape Class.
Hope this helps someone.

Add comment November 28th, 2007

Flash/Flex Tidbit #2 How to use Alpha Mask in Flash CS3

So the other day I spent 2hrs looking for how to and trying to do an alpha mask (I’ve done on once). So like an idiot I was trying to do it the Photoshop way with level of gray.

My method of thinking

  • Black = 100 and White = 0
  • but it doesn’t matter what color only the opacity.

If you have never mad a alpha mask in Flash before or CS3 it’s easy.

  1. open a fla
  2. draw a shape
  3. Make that shape a MovieClip
  4. name it maskee_mc
  5. draw a second shape
  6. use a linear gradient
  7. choose color
  8. set one linear color alpha at say, 40
  9. Make that second shape another MovieCilp
  10. name it mask_mc

[as]

this.mask_mc.cacheAsBitmap = true;
this.maskee_mc.cacheAsBitmap = true;
// as2 was maskee_mc.mask(mask_mc);
maskee_mc.mask = mask_mc;

[/as]
That’s it!

6 comments October 21st, 2007

How to make a Rotating Cube in Papervision 3d

I have been trying to understand Papervision 3d for the last couple of months, but all the examples are using collada or some elaborate functionality. I just wanted to test something simple. So I made a rotating box it rotates on the y axis.

Here how it goes in Flash CS3:

  1. add an image into the library
  2. set the linkage name to test.
  3. make sure width = 336 / height = 335 (for this example)
  4. and add this script

[as]

import org.papervision3d.objects.*;
import org.papervision3d.materials.*;
import org.papervision3d.scenes.*;
import org.papervision3d.cameras.*;

var container:Sprite = new Sprite();
container.x = stage.stageWidth * 0.5;
container.y = stage.stageHeight * 0.5;
addChild(container);

var scene:Scene3D = new Scene3D(container);
var camera:Camera3D = new Camera3D(p, 10);

var bam:BitmapAssetMaterial = new BitmapAssetMaterial(”test”)
bam.oneSide = false;
bam.smooth = true;

var p:Cube = new Cube(bam, 336, 335, 335, 5, 5, 5);

scene.addChild(p);

scene.renderCamera(camera);

addEventListener(Event.ENTER_FRAME, onFrame);

function onFrame(event:Event):void
{
p.rotationX % 360 == 0 ? p.rotationX = 1 : p.rotationX += 1;
trace(p.rotationX)
//p.rotationY = stage.mouseY – (stage.stageHeight * 0.5);

scene.renderCamera(camera);
}

[/as]

thats it

Add comment October 20th, 2007

Flash/Flex Tidbit #1

I have noticed some times I’m an idiot spending an hour on something that would have take five minutes if I’d have paid attention. Well I’m going to start sharing some things I’ve learned from these times.

  1. in Flash/Flex when using the TextEvent.LINK make sure your textfield is set to selected = true.
    the link is clickable even when selected = false, just nothing will happen. Very fishy that should be changed. It is very misleading.

Add comment October 18th, 2007

How to use FlashVars in Flash CS3 and Actionscript 3

In Actionscript 3 you have to do a little more work then AS2.

When working in AS2 you could easily use a random object:

[as]
_flashVar = flashVar

//rest of code
[/as]

With AS3 you could run into IOERRORs and everything in between. The client app could end up with the ugly Runtime Error box, so being proactive about it is better.

Cause you never know, it may work great in your perfect world but when the PHP guy builds the XML structure wrong or the production artist forgets to upload the pictures. All the client will see is you dropped the ball on the flash.
So if you want to use FlashVars in AS3 I’ve found this to be a good solution.

You can compile this script out right or use Flash CS3 (that’s why it extends MovieClip)

[as]
package {
//lazy way to import MovieClip and future display package classes
import flash.display.*;
//lazy way to import Event.COMPLETE, IOErrorEvent.IO_ERROR,
//SecurityErrorEvent.SECURITY_ERROR and future event package classes
import flash.events.*;
import flash.text.TextField;

//extends movie clip to be compatible with flash
public class FlashVarsExample extends MovieClip
{
public function FlashVarsExample()
{
//the application’s flashvars is typed as a LoaderInfo object
// ready to do stuff!
var xmlData:LoaderInfo = root.loaderInfo as LoaderInfo;
// now xmlData listen for many event
// I pushed this to a method idea I got from an Adobe Tutorial
// It is great cause you can centralized all your events
// a re-add listeners to multiple objects
addListeners(xmlData);
}

//if domain error
private function securityErrorHandler(event:SecurityErrorEvent):void {
//declare local variable, it allows me to apply to many objects
// what ever object is listening will be the currentTarget
// makes the code more flexible instead making lots of event handler
//of a private _xmlData variable

//Thought there would never bee another set of FlashVars
var xmlData:LoaderInfo = LoaderInfo(event.currentTarget)
//clean up all the listener
removeListeners(xmlData)
xmlData = null;
trace(”securityErrorHandler: ” + event);
}

//if flashvars do not exist
private function ioErrorHandler(event:IOErrorEvent):void {
var xmlData:LoaderInfo = LoaderInfo(event.currentTarget)
removeListeners(xmlData)
xmlData = null;
trace(”ioErrorHandler: ” + event);
}
//when flashvars are loaded
private function loadFlashVars(evt:Event):void
{

trace(”loaded: ” + evt);
var xmlData:LoaderInfo = LoaderInfo(evt.currentTarget)

// if there is a property w/ xmlData load that as a string into loadXML
// if not loadXML will say “no dice”
var loadXML:String = (xmlData.parameters.hasOwnProperty(”xmlData”)) ? xmlData.parameters.xmlData as String: “no dice”;
removeListeners(xmlData)
xmlData = null;
trace(xmlData);
trace(loadXML);
// create a text field and display loadXML
var _txt:TextField = new TextField()
_txt.background = true;
_txt.text = loadXML;
addChild(_txt);

}

private function addListeners(dispatch:EventDispatcher):void
{
//when the data from the flashvars is now loaded call loadFlashVars method
dispatch.addEventListener(Event.COMPLETE, loadFlashVars);

//when there is no flashvars call loadFlashVars ** prevents the ugly runtime error box **
dispatch.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);

//when data is been loaded from an untrusted domain ** prevents the ugly runtime error box **
dispatch.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
}

private function removeListeners(dispatch:EventDispatcher):void
{
// clean up after yourself you don’t need wasted memory
// listening for some thing that already happend and will not happen again
dispatch.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
dispatch.removeEventListener(Event.COMPLETE, loadFlashVars);
dispatch.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
}

}
}
}
[/as]
All you need to do now is make a php, html, jsp or whatever that has a flashvar with the name xmlData.
Hopefully this helped someone who doesn’t want to you object as a DataType for every variable or nasty error pop-ups.

Next we will actually load some XML

4 comments September 6th, 2007

Next Posts Previous Posts


    Blog Calendar

    July 2010
    M T W T F S S
    « Jun    
     1234
    567891011
    12131415161718
    19202122232425
    262728293031  

    Posts by Month

    Posts by Category