I am developing player which has several my own custom developed buttons which has their own classes. Also the player has its own class which is the main class and instansiate all the buttons I have.
So this is a simple example of "has a" relationship i.e composition.
I used to past a reference of the player trought every buttons constructor in order buttons to be able to access properties and methods from the players class. This method is working good, but the problem is it has a lot of duplicate code than needs to be added to every button class.
So I tried to workit out by using inheritance, i.e buttons extend the playes main class.
But this way although i declare all properties protected I get the final swf blank white. So there must a problem.
Am I doing the structure wrong or what? Any idea?
Here is a sample code
public class Player extends MovieClip{
protected var prop1:Number;
protected var prop2:String;
protected var playButton:PlayButton;
....
public function Player(){
// with composition
playButton=new PlayBUtton(this);
// with inhgeritance
playButton=new PlayButton();
addChild(playBUtton);
}
}
//first implementation with composition
public class PlayButton extends MovieCLip{
public function PlayButton(player:Player){
//access Player trough player parameter
}
}
//second implementation with inheritance
public class PlayButton extends Player{
public function PlayButton(){
//access Player trough inheritance
}
}
You could use the state design pattern like in the following example I made:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var player:Player = new Player();
addChild(player);
}// end function
}// end class
}// end package
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
internal class TextButton extends Sprite
{
public function TextButton(text:String)
{
graphics.beginFill(0xFF0000);
graphics.drawRect(0, 0, 100, 25);
graphics.endFill();
var textField:TextField = new TextField();
textField.text = text;
textField.mouseEnabled = false;
textField.x = this.width / 2 - textField.textWidth /2;
textField.y = this.height / 2 - textField.textHeight / 2;
addChild(textField);
}// end function
}// end class
internal interface IState
{
function play():void
function stop():void
}// end interface
internal class Player extends Sprite
{
private var _playState:IState;
private var _stopState:IState;
private var _state:IState;
private var _playButton:TextButton;
private var _stopButton:TextButton;
public function get playState():IState { return _playState }
public function get stopState():IState { return _stopState }
public function get state():IState { return _state }
public function set state(state:IState):void { _state = state }
public function Player()
{
_playState = new PlayState(this);
_stopState = new StopState(this);
_state = stopState;
_playButton = new TextButton("PLAY");
_playButton.addEventListener(MouseEvent.CLICK, onClick);
addChild(_playButton);
_stopButton = new TextButton("STOP");
_stopButton.addEventListener(MouseEvent.CLICK, onClick);
_stopButton.x = 110;
addChild(_stopButton);
}// end function
private function onClick(e:MouseEvent):void
{
var textButton:TextButton = e.target as TextButton;
switch(textButton)
{
case _playButton : _state.play(); break;
case _stopButton : _state.stop(); break;
}// end function
}// end function
}// end class
internal class PlayState implements IState
{
private var _player:Player;
public function PlayState(player:Player)
{
_player = player;
}// end function
public function play():void
{
trace("player already playing");
}// end class
public function stop():void
{
_player.state = _player.stopState;
trace("stopping player");
}// end function
}// end class
internal class StopState implements IState
{
private var _player:Player;
public function StopState(player:Player)
{
_player = player;
}// end function
public function play():void
{
_player.state = _player.playState;
trace("playing player");
}// end function
public function stop():void
{
trace("player already stopped");
}// end function
}// end class
Related
I have already set a variable in my document class "Main.as". I am now trying to access that variable and read its value from a different Class and Function, take that value and email it.
For example in my "Main.as" file I have this function:
public var _myVar:String;
function create() {
_myVar = "hello";
}
Now from my other class "EmailtoFriend.as" I have a new function to try and get the value of that pre set variable:
function getVar() {
trace(_myVar);
}
Why will it not output "hello"? Instead I get an error saying: Access of undefined property _myVar. If I could just get this simple example working, I think it will help me understand a lot of things. Thanks!
The error your getting really says it all. Although _myVar is defined in your Main class public var _myVar:String;, it isn't defined in your Emailtofriend class. If you want access to _myVar you need to do one of the following:
Parse a reference of your Main object(using this) to your EmailToFriend class:
Main.as(document class):
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
public var _myVar:String;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
public function create():void
{
_myVar = "hello";
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
create();
var emailToFriend:EmailToFriend = new EmailToFriend(this);
emailToFriend.getVar();
}// end function
}// end class
}// end package
internal class EmailToFriend
{
private var _main:Main;
public function EmailToFriend(main:Main)
{
_main = main;
}// end function
public function getVar():void
{
trace(_main._myVar);
}// end function
}// end class
Or to make _myVar a public static property of Main and access it via Main._myVar:
Main.as(document class):
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
public static var _myVar:String;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
public function create():void
{
_myVar = "hello";
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
create();
var emailToFriend:EmailToFriend = new EmailToFriend();
emailToFriend.getVar();
}// end function
}// end class
}// end package
internal class EmailToFriend
{
public function EmailToFriend() {}
public function getVar():void
{
trace(Main._myVar);
}// end function
}// end class
Also one small thing, when using underscores for class properties, you should only use them for private properties, not public. Well I say only but I really mean it's more common.
[UPDATE]
This is in response to your comment:
Main.as:
package
{
import EmailToFriend;
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
public static var _myVar:String;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
public function create():void
{
_myVar = "hello";
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
create();
var emailToFriend:EmailToFriend = new EmailToFriend();
emailToFriend.getVar();
}// end function
}// end class
}// end package
EmailToFriend.as:
package
{
import Main;
public class EmailToFriend
{
public function EmailToFriend() {}
public function getVar():void
{
trace(Main._myVar);
}// end function
}// end class
}// end package
All variables implicitly have a target, unless explicitly specified. Variables without an explicit target will commonly look in the local scope of the function (in this case, getVar()) and the global scope of the class (in this case, EmailToFriend).
I assume that these don't exist in your code, judging by the error. You will need something like the following to access the var:
function getVar() {
var main:Main = new Main();
main.create();
trace(main._myVar);
}
Assuming Main.as is your document class:
public var _myVar:String;
public function create():String {
//we specify that this function will return a String using the :String in the above line
//now give the variable a value
_myVar = "hello";
//and send it back to the caller of the function
return _myVar;
}
Within your other class
function getVar():void {
//MovieClip(root) is another way of referencing your document class.
trace(MovieClip(root).create());
}
OR...
public var _myVar:String;
public function create():void {
//now give the variable a value
_myVar = "hello";
}
Within your other class
function getVar():void {
//call the function that actually gives myVar a value
MovieClip(root).create();
//now you can trace the value
trace(MovieClip(root)._myVar);
}
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public var _myVar:String;
public function Main(){
create();
}
private function create() {
_myVar = "hello";
}
}
}
}
in EmailtoFriend.a
import Main.as
var myMain = new Main();
trace(myMain._myVar);
What you should do is have a OOP approach, meaning use encapsulation in your classes. If you don;t know what that means, its ok. For instance, if you have a variable, that you want to be accessible, then you should really make it private, and the set up its own public function that returns the variable. Like this:
package {
public class SomeClass {
private var someVar:Number = 12; // A private variable, which means only this class can
// use the reference someVar, and only other outiside classes can use the function getSomeVar.
... // skip some regular class stuff
public function getSomeVar():Number {
return this.someVar; //returns the variable someVar from this class to whoever is accessing it.
//This function is public which means that anyone can call it and get the variable someVar.
}
}
}
To access that variable, you just reference a class instance:
var someClass:SomeClass = new SomeClass(); // create the instance using the variable someClass
var myVar:Number = someClass.getSomeVar(); // ACCESSES the variable that you want from the class,
//by first using the class instance reference, and then calling its public function that returns the value you want.
How to trace that "section1.btnback" was clicked?
section1.btnback.addEventListener(MouseEvent.CLICK, getBack)
function getBack(event:MouseEvent):void
{
// trace: "section1.btnback"
}
Thanks.
Uli
I'm not sure what actualy you are asking for. If my suggestion is not the right for you, please excuse me. If you write
trace(event.target)
you will see the complete name of the instance of the button.
I am guessing that you want it to say something like:
"Button was clicked!" to console each time the button is pressed?
trace("Section1.btnback was clicked!");
I believe.
(Wasn't really sure what you were asking for)
-Expanded in comments below-
If you want the "complete path" like meddlingwithfire suggested in his comment on 3lionz's answer, then you can use a class I created that does it for you. The class is called DOPath(short for display object path). The following is an example of it being used to get the complete path of a display object:
Main.as(document class):
package
{
import com.example.display.DOPath;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var container1:Sprite = new Sprite();
container1.name = "container1";
var container2:Sprite = new Sprite();
container2.name = "container2";
var square:Square = new Square();
square.name = "square";
square.addEventListener(MouseEvent.CLICK, onSquareClick);
addChild(container1);
container1.addChild(container2);
container2.addChild(square);
}// end function
private function onSquareClick(e:MouseEvent):void
{
var square:Square = e.target as Square;
var doPath:DOPath = new DOPath(square);
trace(doPath); // output: stage.root1.container1.container2.square
}// end function
}// end package
}// end package
import flash.display.Sprite;
internal class Square extends Sprite
{
public function Square()
{
graphics.beginFill(0xFF0000);
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
}// end function
}// end class
DOPath.as:
package com.example.display
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Stage;
public class DOPath
{
private var _parents:Vector.<DisplayObjectContainer>;
private var _d:DisplayObject;
public function DOPath(d:DisplayObject):void
{
_d = d;
init();
}// end function
private function init():void
{
_parents = new Vector.<DisplayObjectContainer>;
pushParent(_d);
}// end function
private function pushParent(d:DisplayObject):void
{
if(d.parent)
{
_parents.push(d.parent);
pushParent(d.parent);
}// end if
}// end function
public function toString():String
{
var path:String = _d.name;
for (var i:uint = 0; i < _parents.length; i++)
{
var name:String = (_parents[i] is Stage) ? "stage" : _parents[i].name;
path = name + "." + path;
}// end for
return path;
}// end function
}// end class
}// end package
You can use a quite simple recursive function like this one:
private function getDOname(dob : DisplayObject) : String
{
var result : String = dob.name;
if (dob is UIComponent)
{
result = UIComponent(dob).id;
}
if(dob.parent && dob.parent is DisplayObjectContainer)
{
result = getDOname(dob.parent) + "." + result;
}
return result;
}
You can pass event.target to the function and acquire the button that was clicked. If you are using these techniques for debug purposes, you can simply add and event listener for click event to the stage or the SandboxRoot itself, if you are unsure which visual element you are actually clicking.
I'm working on an AS3 project that must load a lot of external files; images, sound clips, movie clips etc. The program first loads an XML file that contains the file names of all assets needed by each class. From that point on I'm not sure what would be the best way to distribute those assets.
I thought about making a dedicated assets class that will load everything the XML object describes, and then pass it to each class' constructor so they can access the objects they need. This seems like the "tidiest" option, but is there a best practice way for managing loaded assets?
You could create a class that handles loading the assets and storing them as bytes. Then you can get an asset from that class via a reference(e.g. name) and do what you need with it. I've created an example to demonstrate this:
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.utils.ByteArray;
import flash.events.Event;
public class Main extends Sprite
{
private var _assets:Assets;
private var _counter:int;
private var _assetsXml:XML;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_assetsXml = <assets>
<asset name="chrysanthemum" url="assets/chrysanthemum.jpg"></asset>
<asset name="kalimba" url="assets/kalimba.mp3"></asset>
<asset name="wildlife" url="assets/wildlife.wmv"></asset>
</assets>;
_assets = new Assets();
for each(var asset:XML in _assetsXml.children())
{
_assets.addEventListener(Event.COMPLETE, onAssetComplete);
_assets.load(asset.#name, asset.#url);
}// end for each
}// end function
private function onAssetComplete(e:Event):void
{
if (++_counter == _assetsXml.children().length()) addImage();
}// end function
private function addImage():void
{
var loader:Loader = new Loader()
loader.loadBytes(_assets.getAssetBytesByName("chrysanthemum"));
addChild(loader);
}// end function
}// end class
}// end package
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;
internal class Assets extends EventDispatcher
{
private var _assetLoaders:Vector.<AssetLoader>;
public function Assets():void
{
_assetLoaders = new Vector.<AssetLoader>();
}// end class
public function load(name:String, url:String):void
{
var assetLoader:AssetLoader = new AssetLoader(name);
assetLoader.addEventListener(Event.COMPLETE, onAssetLoaderComplete);
assetLoader.load(url);
}// end function
public function getAssetBytesByName(name:String):ByteArray
{
for each(var assetLoader:AssetLoader in _assetLoaders)
{
if (assetLoader.name == name) break;
}// end for each
return assetLoader.bytes;
}// end function
private function onAssetLoaderComplete(e:Event):void
{
var assetLoader:AssetLoader = e.target as AssetLoader;
_assetLoaders.push(assetLoader);
dispatchEvent(new Event(Event.COMPLETE));
}// end function
}// end class
internal class AssetLoader extends EventDispatcher
{
private var _name:String;
private var _url:String;
private var _bytes:ByteArray;
public function get name():String { return _name }
public function get url():String { return _url };
public function get bytes():ByteArray { return _bytes };
public function AssetLoader(name:String):void
{
_name = name;
}// end function
public function load(url:String):void
{
_url = url;
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, onUrlLoaderComplete);
urlLoader.load(new URLRequest(_url));
}// end function
private function onUrlLoaderComplete(e:Event):void
{
var urlLoader:URLLoader = e.target as URLLoader;
_bytes = ByteArray(urlLoader.data);
dispatchEvent(new Event(Event.COMPLETE));
}// end function
}// end class
For loop contains an event listener function. but loop iteration is quicker than listener function.Before the listener function completes next iteration starts. how to handle this???
Sounds like you don't need a "for" loop.
According to your description, it looks like you need some form of event chain where after the first event complete you set up a new listener and so on...
If the answer your looking for is as PatrickS described, I've create an example of how to implement it:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Main extends Sprite
{
private var _queue:Queue;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var queueItems:Vector.<QueueItem> = new Vector.<QueueItem>();
for (var i:uint = 0; i < 5; i++)
{
var timer:Timer = new Timer(2 * 1000, 1);
queueItems.push(new QueueItem(timer, TimerEvent.TIMER_COMPLETE, onTimerComplete));
}// end for
_queue = new Queue(queueItems);
var currentTimer:Timer = Timer(_queue.currentQueueItem.eventDispatcher);
currentTimer.start();
_queue.shift();
}// end function
private function onTimerComplete(e:TimerEvent):void
{
if (_queue.currentQueueItem)
{
var currentTimer:Timer = Timer(_queue.currentQueueItem.eventDispatcher);
currentTimer.start();
if (_queue.length > 0) _queue.shift();
}// end if
}// end function
}// end class
}// end package
import flash.events.IEventDispatcher;
import flash.events.Event;
internal class Queue
{
private var _queueItems:Vector.<QueueItem>;
public function get currentQueueItem():QueueItem { return (_queueItems.length > 0) ? _queueItems[0] : null }
public function get length():int { return _queueItems.length }
public function Queue(queueItems:Vector.<QueueItem>)
{
_queueItems = queueItems;
}// end function
public function shift():void
{
var eventDispatcher:IEventDispatcher = _queueItems[0].eventDispatcher;
var type:String = _queueItems[0].type;
var listener:Function = _queueItems[0].listener;
var useCapture:Boolean = _queueItems[0].useCapture;
var priority:int = _queueItems[0].priority;
var useWeakReference:Boolean = _queueItems[0].useWeakReference;
eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
_queueItems.shift();
}// end function
}// end class
internal class QueueItem
{
private var _eventDispatcher:IEventDispatcher;
private var _type:String;
private var _listener:Function;
private var _useCapture:Boolean;
private var _priority:int;
private var _useWeakReference:Boolean;
public function get eventDispatcher():IEventDispatcher { return _eventDispatcher }
public function get type():String { return _type}
public function get listener():Function { return _listener }
public function get useCapture():Boolean { return _useCapture }
public function get priority():int { return _priority }
public function get useWeakReference():Boolean { return _useWeakReference }
public function QueueItem(eventDispatcher:IEventDispatcher, type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false)
{
_eventDispatcher = eventDispatcher;
_type = type;
_listener = listener;
_useCapture = useCapture;
_priority = priority;
_useWeakReference = useWeakReference;
}// end function
}// end class
Simply put, this creates a queue like system that adds an event listener to the IEventListener object at the front of the queue and when its added the queue is shifted.
The above shows how you can use this with Timer objects.
I have one folder(Projects), which contains 2 files: FirstPro.fla, FirstClass.as
The goal of my question is interaction with two different objects (MovieClip) from class, which i created by myself, i have only one class, and it class for only one MovieClip, my goal is interaction, for MovieClip second which has name(letterPanel) has no class, its only MovieClip on scene;
In FirstClass.as i have the next code:
package
{
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.MovieClip;
import flash.events.*;
import flash.display.Stage;
public class FirstClass extends MovieClip
{
public function FirstClass()
{
var NewMyTimer:Timer = new Timer(100);
NewMyTimer.addEventListener(TimerEvent.TIMER, hm);
NewMyTimer.start();
}
public function hm(TimerEvent):void
{
this.y += 5;
if(this.hitTestObject(letterPanel))
{
trace("Coincidens");
}
}
}
}
And in FirstPro.fla file i have on the scene i have two MovieClip (Images), one of them has firstobj name, which has link with my created class, and it works, my object firstobj going down with the timer, but i would like to interaction with the second object(MovieClip-letterPanel) - if(this.hitTestObject(letterPanel)) { trace("Coincidens"); }
If i write this code in my class this output mistake (letterPanel) is not undefined, what can i do with interactions of those two object in one class,?
You have to assign the MovieClip and you also can not start the timer untill that var has been set
package{
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.MovieClip;
import flash.events.*;
import flash.display.Stage;
public class FirstClass extends MovieClip{
private var _letterPanel:MovieClip;
public function FirstClass(){
}
public function startConter( ):void{
var NewMyTimer:Timer=new Timer(100);
NewMyTimer.addEventListener(TimerEvent.TIMER, hm);
NewMyTimer.start();
}
public function hm(TimerEvent):void{
this.y+=5;
if(this.hitTestObject(this._letterPanel)){
trace("Coincidens");
}
}
public function set letterPanel( val:MovieClip ):void{
this._letterPanel = val;
}
}
}
var firstClass:FirstClass = new FirstClass( );
firstClass.letterPanel = letterPanel;
firstClass.startCounter( );
My initial response(other than being confused, since your explaination of your project is a bit hard to understand) is that you don't have a good grasp on OOP. There was an answer for this question before that I believed to be correct. If I remember correctly you rejected it simply because it didn't utilize classes. OOP is about knowing how to as well as when to implement OOP concepts such as abstraction, encapsulation, inheritance, polymorphism etc.
In your case I think the simple answer to your question is the following:
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(e:Event):void
{
if(displayObject1.hitTestObject(displayObject2)
trace("hit");
}// end function
However if you feel the need to truely use classes, I've created a similar flash application to demonstrate how you would go about it. Its basically 3 draggable red, green and blue circle display objects on the stage and when you drag a circle display object and it overlaps/intersects another circle display object a trace is made to describe the collision. You can run the application by simply copying and pasting the following code into your document class:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var redCircle:Circle = new Circle(Color.RED, 50);
redCircle.name = "redCircle";
redCircle.x = 100;
redCircle.y = 100;
addChild(redCircle);
var greenCircle:Circle = new Circle(Color.GREEN, 50);
greenCircle.name = "greenCircle";
greenCircle.x = 300;
greenCircle.y = 100;
addChild(greenCircle);
var blueCircle:Circle = new Circle(Color.BLUE, 50);
blueCircle.name = "blueCircle";
blueCircle.x = 500;
blueCircle.y = 100;
addChild(blueCircle);
var collision:Collision = new Collision(stage, redCircle, greenCircle, blueCircle);
collision.addEventListener(CollisionEvent.COLLISION, onCollision);
}// end function
private function onCollision(e:CollisionEvent):void
{
var collision:Collision = Collision(e.target);
collision.removeEventListener(CollisionEvent.COLLISION, onCollision);
trace("There was a collision between " + e.displayObject1.name + " and " + e.displayObject2.name);
}// end function
}// end class
}// end package
internal class Color
{
public static const RED:uint = 0xFF0000;
public static const GREEN:uint = 0x00FF00;
public static const BLUE:uint = 0x0000FF;
}// end class
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.EventDispatcher;
import flash.events.Event;
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.MouseEvent;
internal class Circle extends Sprite
{
public function Circle(color:uint, radius:Number)
{
graphics.beginFill(color);
graphics.drawCircle(0,0,radius);
graphics.endFill();
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}// end function
private function onMouseDown(e:MouseEvent):void
{
parent.setChildIndex(this, parent.numChildren - 1);
startDrag();
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp)
}// end function
private function onMouseUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stopDrag();
}// end function
}// end class
internal class Collision extends EventDispatcher
{
private var _stage:Stage;
private var _doVector:Vector.<DisplayObject>;
public function Collision(stage:Stage, ...displayObjects)
{
_stage = stage;
_doVector = getDOVector(validateArgs(displayObjects, DisplayObject));
init();
}// end function
private function init():void
{
_stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}// end function
private function onEnterFrame(e:Event):void
{
for(var i:uint = 0; i < _doVector.length; i++)
{
for(var j:uint = 0; j < _doVector.length; j++)
{
if (_doVector[i] != _doVector[j])
{
if (_doVector[i].hitTestObject(_doVector[j]))
dispatchEvent(new CollisionEvent(CollisionEvent.COLLISION, _doVector[i], _doVector[j]));
}// end if
} // end for
}// end for
}// end function
private function validateArgs(args:Array, type:Class):Array
{
for each(var arg:* in args)
if(!(arg is type))
throw new ArgumentError("Argument must be of type " + type);
return args;
}// end function
private function getDOVector(array:Array):Vector.<DisplayObject>
{
var doVector:Vector.<DisplayObject> = new Vector.<DisplayObject>();
for each(var displayObject:DisplayObject in array)
doVector.push(displayObject);
return doVector;
}// end function
}// end class
internal class CollisionEvent extends Event
{
public static const COLLISION:String = "collision";
private var _displayObject1:DisplayObject;
private var _displayObject2:DisplayObject;
public function get displayObject1():DisplayObject { return _displayObject1 };
public function get displayObject2():DisplayObject { return _displayObject2 };
public function CollisionEvent(type:String,
displayObject1:DisplayObject,
displayObject2:DisplayObject,
bubbles:Boolean = false,
cancelable:Boolean = false):void
{
_displayObject1 = displayObject1;
_displayObject2 = displayObject2;
super(type, bubbles, cancelable);
}// end function
override public function clone():Event
{
return new CollisionEvent(type, displayObject1, displayObject2, bubbles, cancelable);
}// end function
}// end class