AS3 Dispatch Custom Event from class to class - actionscript-3

I want to dispatch a custom event from the Country() sto the MenuButton();
CountryEvent
package {
import flash.events.Event;
public class CountryEvent extends Event {
public static const COUNTRY_HOVERED:String = "onCountryOver";
private var _countryName:String = "";
public function CountryEvent(type:String, countryName:String, bubbles:Boolean=true, cancelable:Boolean=false) {
super(type, bubbles, cancelable);
_countryName = countryName;
}
public function get countryName():String {
return _countryName;
}
public override function clone():Event
{
return new CountryEvent(type,countryName,bubbles,cancelable);
}
}
}
Country Class
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class Country extends MovieClip
{
private var countryEvent:CountryEvent;
public function Country()
{
this.addEventListener(MouseEvent.MOUSE_OVER,onMouseOver);
this.addEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
}
private function onMouseOver(e:MouseEvent):void
{
countryEvent = new CountryEvent("onCountryOver",this.name);
dispatchEvent(countryEvent);
}
}
private function onMouseOut(e:MouseEvent):void
{
}
}
}
MenuButton Class
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import CountryEvent;
public class MenuButton extends MovieClip {
public var countryName:String = "";
public function MenuButton() {
this.buttonMode = true;
this.addEventListener(MouseEvent.MOUSE_OVER,onMouseOver);
this.addEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
this.addEventListener(CountryEvent.COUNTRY_HOVERED,onCountryOver);
}
private function onCountryOver(e:CountryEvent):void {
if(e.countryName == countryName) {
this.gotoAndPlay(2);
}
}
private function onMouseOver(e:MouseEvent):void {
this.gotoAndPlay(2);
}
private function onMouseOut(e:MouseEvent):void {
this.gotoAndPlay(11);
}
}
}
When a country is hovered a custom event is dispatched which I want the MenuButton to listen and if the parameter passed is the same as its name to get highlighted. The Country Class is the Base Class for my countries movieclips I have on stage and the MenuButton the Base Class for the menu button
It seems that the event never gets through
Thanks in advance

You have to make two modifications:
First, set your event bubbles property to true, so when a Country clip dispatches an event it will go up to the top level.
Then your MenuButtons should listen to stage, not to themselves. So when a Country dispatches an event it goes up to stage and can be caught by the buttons. If you want to listen to the stage you have to do a slight change in your code:
public function MenuButton() {
this.buttonMode = true;
this.addEventListener(MouseEvent.MOUSE_OVER,onMouseOver);
this.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
stage.addEventListener(CountryEvent.COUNTRY_HOVERED,onCountryOver);
}

the best and easy way for solving this issue is by simply pass the stage reference as class level parameter and add event to the stage reference and dispatch event to the stage reference.
Country Class
package{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class Country extends MovieClip
{
private var countryEvent:CountryEvent;
private var _stageRef:Stage;
public function Country(pStageRef:Stage)
{
_stageRef = pStageRef;
this.addEventListener(MouseEvent.MOUSE_OVER,onMouseOver);
this.addEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
}
private function onMouseOver(e:MouseEvent):void
{
countryEvent = new CountryEvent("onCountryOver",this.name);
_stageRef.dispatchEvent(countryEvent);
}
}
private function onMouseOut(e:MouseEvent):void
{
}
}
MenuButton Class
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import CountryEvent;
public class MenuButton extends MovieClip {
public var countryName:String = "";
private var _stageRef:Stage;
public function MenuButton(pStageRef:Stage) {
_stageRef = pStageRef;
this.buttonMode = true;
this.addEventListener(MouseEvent.MOUSE_OVER,onMouseOver);
this.addEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
_stageRef.addEventListener(CountryEvent.COUNTRY_HOVERED,onCountryOver);
}
private function onCountryOver(e:CountryEvent):void {
if(e.countryName == countryName) {
this.gotoAndPlay(2);
}
}
private function onMouseOver(e:MouseEvent):void {
this.gotoAndPlay(2);
}
private function onMouseOut(e:MouseEvent):void {
this.gotoAndPlay(11);
}
}

Related

ADDED_TO_STAGE function never called

I have this class which should take a button from stage (xBtn).
package com.stx.utils {
import flash.display.MovieClip;
import flash.events.*;
public class STXbutonx extends MovieClip {
private var xBtn : MovieClip;
public function STXbutonx() {
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event=null) : void {
trace("int!"); //this is never called
xBtn = stage.getChildByName('ics') as MovieClip;
xBtn.addEventListener(MouseEvent.CLICK, onX);
removeEventListener(Event.ADDED_TO_STAGE, init);
}
private function onX(e:MouseEvent) : void {
trace("x Clicked!");
}
}
}
and in Document class I called like this :
import flash.display.MovieClip;
import com.stx.utils.*;
public class Main extends MovieClip {
var xx : STXbutonx;
public function Main() {
xx = new STXbutonx();
}
}
Why my init function is never called?
Thank you!
Because you never add it to the stage.
Change your Document class to
public function Main() {
xx = new STXbutonx();
addChild(xx);
}
Main holds the reference to the stage, adding a child to Main will add the child to the stage. Thus the event listener in STXbutonx will fire.
xBtn = stage.getChildByName('ics') as MovieClip; // now I have acces of undefined property stage...
You don't have access to the stage because STXButon is not on the stage, it is not an DisplayObject. To get around this, do this:
package com.stx.utils {
import flash.display.MovieClip;
import flash.events.*;
public class STXbutonx{
private var xBtn : MovieClip;
private var stage : Stage;
public function STXbutonx(stage:Stage) {
this.stage = stage;
init();
}
private function init() : void {
trace("int!");
xBtn = stage.getChildByName('ics') as MovieClip;
xBtn.addEventListener(MouseEvent.CLICK, onX);
removeEventListener(Event.ADDED_TO_STAGE, init);
}
private function onX(e:MouseEvent) : void {
trace("x Clicked!");
}
}
}
And of course
import flash.display.MovieClip;
import com.stx.utils.*;
public class Main extends MovieClip {
var xx : STXbutonx;
public function Main() {
xx = new STXbutonx(stage);
}
}

as3 StageWebView in a class not displaying

I am sure this is an easy one. I have one Main.as class calling a another class that is loading a StageWebView. If called by itself the StageWebView works fine, but when I call it from another class it will not display. What simple thing am I forgetting?
Perhaps it has something to do with the "stage" in the loaded class?
Main.as
public function addPopeNews()
{
thePopeNews = new popeNews();
addChild(thePopeNews);
}
PopeNews.as
package com
{
import flash.display.MovieClip;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.*;
import flash.net.URLRequest;
import flash.media.StageWebView;
import flash.geom.Rectangle;
public class popeNews extends MovieClip
{
public var backBar:popeNewsBar;
public var webView:StageWebView;
public function popeNews()
{
webView=new StageWebView();
webView.stage = this.stage;
webView.loadURL("www.myUrl.com");
trace("POPE NEWS!!!"); /// trace works!
backBar = new popeNewsBar();
backBar.width = Main._screenX;
backBar.scaleY = backBar.scaleX;
webView.addEventListener(Event.COMPLETE, webLoaded);
webView.addEventListener(LocationChangeEvent.LOCATION_CHANGING,onChanging);
}
public function webLoaded(e:Event)
{
trace("web loaded"); // trace works!!
if (webView.isHistoryBackEnabled)
{
addChild(backBar);
backBar.bb.addEventListener(MouseEvent.CLICK, goBack);
webView.viewPort = new Rectangle(0,backBar.height,Main._screenX,Main._screenY - backBar.height);
}
else
{
webView.viewPort = new Rectangle(0,0,Main._screenX,Main._screenY);
}
}
public function goBack(e:Event)
{
if (webView.isHistoryBackEnabled)
{
trace("Called GO BACK");
webView.historyBack();
removeChild(backBar);
backBar.bb.removeEventListener(MouseEvent.CLICK, goBack);
return;
}
if (webView.isHistoryForwardEnabled)
{
webView.historyForward();
return;
}
}
public function onError(e:ErrorEvent):void
{
//infoBox.text="Page is not available. Try reloading.";
}
public function onChanging(e:LocationChangeEvent):void
{
//webView.viewPort = null;
trace("Called CHANGING!!!");
}
///
}
}
You are right, the stage is null in the PopeNews constructor. You should put your initialization code into a new method, and listen for the ADDED_TO_STAGE event.
public function popeNews()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(ev:Event):void
{
webView=new StageWebView();
webView.stage = this.stage;
webView.loadURL("www.myUrl.com");
trace("POPE NEWS!!!"); /// trace works!
backBar = new popeNewsBar();
backBar.width = Main._screenX;
backBar.scaleY = backBar.scaleX;
webView.addEventListener(Event.COMPLETE, webLoaded);
webView.addEventListener(LocationChangeEvent.LOCATION_CHANGING,onChanging);
}
Also, by convention class names are capitalized.

how to bring movie clip on front in as3

I have two movieclips one over other. using mouse click event I want to bring one of them in the front. It works 1 or 2 times then it just stops responding to mouse clicks. I don't know what is happening. I tried hard but could not get it work.
Here is my code for document class :
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.SimpleButton;
public class THREE2DP extends MovieClip {
public var page11:page1;
public var page22:page2;
public var scene11:scene1;
public var scene22:scene2;
public function THREE2DP() {
// constructor code
stop();
createscene();
createpage2();
createpage1();
this.addEventListener(Event.ENTER_FRAME, enterframehandler);
}
public function enterframehandler(e:Event):void
{
if(scene11.front)
{
bringToFront(page11);
scene22.front = false;
}
if(scene22.front)
{
bringToFront(page22);
scene11.front = false;
}
}
private function bringToFront(mcl:MovieClip)
{
mcl.parent.setChildIndex(mcl,mcl.parent.numChildren - 1);
}
public function createpage1()
{
page11 = new page1();
addChild(page11);
page11.x = 0;
page11.y = 0;
}
public function createpage2()
{
page22 = new page2();
addChild(page22);
page22.x = 0;
page22.y = 0;
}
public function createscene()
{
scene11 = new scene1();
addChild(scene11);
scene11.x = 0;
scene11.y = 635;
scene22 = new scene2();
addChild(scene22);
scene22.x = 400;
scene22.y = 635;
}
}
}
here is code for scene11 movieclip custom class
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.SimpleButton;
public class scene1 extends MovieClip {
public var front:Boolean = false;
public function scene1() {
// constructor code
stop();
this.addEventListener(MouseEvent.CLICK, clickhandler, false, 0, true);
}
public function clickhandler(event:MouseEvent): void
{
front = true;
}
}
}
code for scene22 custom class is
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.SimpleButton;
public class scene2 extends MovieClip {
public var front:Boolean = false;
public function scene2() {
// constructor code
stop();
this.addEventListener(MouseEvent.CLICK, clickhandler, false, 0, true);
}
public function clickhandler(event:MouseEvent):void
{
front = true;
}
}
}
Upon click on movieclips scene11 and scene22, movieclip page11 and page22 should come on front of stage respectively but that happens only once for each page, after that nothing changes.
my earlier logic for custom classwas faulty. took me 2 day. added mouse_down event to make it work.
i some how managed to do this right by changing custom class code to this
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.SimpleButton;
public class scene1 extends MovieClip {
public var front:Boolean = false;
public function scene1() {
// constructor code
stop();
this.addEventListener(MouseEvent.MOUSE_DOWN, presshandler, false, 0, true);
this.addEventListener(MouseEvent.CLICK, clickhandler, false, 0, true);
}
public function presshandler(event:MouseEvent): void
{
front = true;
}
public function clickhandler(event:MouseEvent): void
{
front = false;
}
}
}
also modified document class code by calling pagechange() function from enterframehandler() function for sake of simplicity
public function pagechange()
{
if (scene11.front && scene22.front == false)
{
bringToFront(page11);
}
if (scene22.front && scene11.front == false)
{
bringToFront(page22);
}
}
private function bringToFront(mcl:MovieClip)
{
mcl.parent.setChildIndex(mcl,mcl.parent.numChildren - 1);
}
Instead of using that bringToFront method, you could just readd page11 and page22 on stage with addChild(). addChild always adds a child on front of everything else in the parent.
public function enterframehandler(e:Event):void
{
if(scene11.front)
{
addChild(page11);
scene22.front = false;
}
if(scene22.front)
{
addChild(page22);
scene11.front = false;
}
}

hitTestObject in a saprate class

i am making a simple game. here is the problem i am facing, but first i will tell you my class structure.
(i am using flash cs5.5)
Enemy.as : this class is linked with a MovieClip(in library), having code of simple enemy movment and directions.
Hero.as : Linked with a MovieClip in library. Code of Hero simple Movment
EnemyManager.as : Creates new enemy Every 20 Second.
HeroManager.as : Creates Hero(Only Once, other functionality will be added later).
HittingManager.as : checks for collusions(Problem Here)
Now My Problem is in HittingManager.as class because i want to add HitTestObject Functionalty in this class. i will post code of 3 important classes. (EnemyManager.as, HeroManager.as, HittingManager.as )
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class HeroManager extends MovieClip
{
private var hManager:HittingManager = new HittingManager();
public static var hero:Hero = new Hero();
public function HeroManager()
{
addEventListener(Event.ADDED_TO_STAGE, added);
}
private function added(event:Event):void
{
trace("hero manager added");
}
}//class
}//package
Here is the code of EnemyManager.as class
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.sampler.Sample;
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.sampler.NewObjectSample;
public class EnemyManager extends MovieClip
{
private var hManager:HittingManager = new HittingManager();
private var timer:Timer = new Timer(2000);
public static var hitting:Boolean = false;
public static var enemy:Enemy;
public function EnemyManager()
{
addEventListener(Event.ADDED_TO_STAGE, added);
}
public function addEnemy(newEnemy:Enemy):void
{
addChild(newEnemy);
hManager.registerEnemy(newEnemy);
}
private function added(event:Event):void
{
addEventListener(Event.ENTER_FRAME, update);
trace("added enemy manger");
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
}
private function onTimer(event:TimerEvent):void
{
enemy = new Enemy();
this.addEnemy(enemy);
}
private function update(event:Event):void
{
}
}
}
And here Hittest.as class (i have tried many techniqes but all in vain ) so i am leaving if statment empty
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class HittingManager extends MovieClip
{
private var eManager:EnemyManager;
private var hEnemy:Enemy = new Enemy();
private var _enemies:Array;
private var _hero:Hero;
public function HittingManager()
{
//trace("Hitting Manager working");
_enemies = [];
addEventListener(Event.ADDED_TO_STAGE, added);
}
public function registerEnemy(newEnemy:Enemy):void
{
_enemies.push(newEnemy);
}
public function registerHero():void
{
//trace("heroRegisterd");
_hero = HeroManager.hero;
addChild(_hero);
}
private function added(event:Event):void
{
if(!_hero)
{
this.registerHero();
}
trace("Hitting manger added");
addEventListener(Event.ENTER_FRAME, update);
}
private function update(event:Event):void
{
if(_hero)
{
for each( newEnemy:Enemy in _enemies)
{
if(_hero.hitTestObject(newEnemy) )
{
trace("Hitting")
}
}
}
}
}//class
}//package
The revision below gets your code working with as few changes as possible, however it is in no way an ideal solution.
You should probably refactor your code so that the enemy manager doesn't need a public static reference to the HittingManager
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class HeroManager extends MovieClip
{
public static var hero:Hero = new Hero();
public function HeroManager()
{
addEventListener(Event.ADDED_TO_STAGE, added);
}
private function added(event:Event):void
{
trace("hero manager added");
}
} //class
} //package
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.sampler.Sample;
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.sampler.NewObjectSample;
public class EnemyManager extends MovieClip
{
public static var hManager:HittingManager;
private var timer:Timer = new Timer(2000);
public static var hitting:Boolean = false;
public static var enemy:Enemy;
public function EnemyManager()
{
addEventListener(Event.ADDED_TO_STAGE, added);
}
public function addEnemy(newEnemy:Enemy):void
{
addChild(newEnemy);
hManager.registerEnemy(newEnemy);
}
private function added(event:Event):void
{
addEventListener(Event.ENTER_FRAME, update);
trace("added enemy manger");
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
}
private function onTimer(event:TimerEvent):void
{
enemy = new Enemy();
this.addEnemy(enemy);
}
private function update(event:Event):void
{
}
}
}
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class HittingManager extends MovieClip
{
private var _enemies:Array;
private var _hero:Hero;
public function HittingManager()
{
//trace("Hitting Manager working");
_enemies = [];
addEventListener(Event.ADDED_TO_STAGE, added);
}
public function registerEnemy(newEnemy:Enemy):void
{
_enemies.push(newEnemy);
}
public function registerHero():void
{
//trace("heroRegisterd");
_hero = HeroManager.hero;
addChild(_hero);
}
private function added(event:Event):void
{
if (!_hero)
{
this.registerHero();
}
trace("Hitting manger added");
addEventListener(Event.ENTER_FRAME, update);
}
private function update(event:Event):void
{
if (_hero)
{
for each (var newEnemy:Enemy in _enemies)
{
if (_hero.hitTestObject(newEnemy))
{
trace("Hitting")
}
}
}
}
} //class
} //package
In your main document class, you should have something like:
var hittingManager:HittingManager = new HittingManager();
EnemyManager.hManager = hittingManager;
var enemyManager:EnemyManager = new EnemyManager();
var heroManager:HeroManager = new HeroManager();
addChild(heroManager);
addChild(enemyManager);
addChild(hittingManager);

Propagate custom event to Parent

I have got a custom event set up (see below), but when I listen for the event in my main class, and it gets dispatched from the child class, it never gets captured.
TRIED:
this.b.addEventHandler(GameLaunchEvent.GAME_LAUNCH_EVENT, this.eventHandler)
package com.thom.events
{
import flash.display.MovieClip;
import flash.events.Event;
/**
* ...
* #author
*/
public class LaunchEventAbstract extends Event
{
public var parent:MovieClip;
public function LaunchEventAbstract(type:String, parent:MovieClip = null)
{
super(type, true);
this.parent = parent;
}
}
}
package com.thom.events
{
import flash.display.MovieClip;
import flash.events.Event;
/**
* ...
* #author
*/
public class GameLaunchEvent extends LaunchEventAbstract
{
public static const GAME_LAUNCH_EVENT:String = "GameLaunchEvent";
public function GameLaunchEvent(parent:MovieClip = null) {
trace("GameLaunchEvent");
super(GAME_LAUNCH_EVENT, parent);
}
}
}
//example code
package {
import com.thom.events.*;
public class A extends MovieClip{
public var b:B;
public function A(){
addEventListener(GameLaunchEvent.GAME_LAUNCH_EVENT, eventHandler);
this.b = new B();
addChild(b);
}
public function eventHandler(e:GameLaunchEvent){
trace("Success");
}
}
}
package {
import com.thom.events.*;
public class B extends MovieClip{
public function B() {
dispatchEvent(new GameLaunchEvent(this));
}
}
}
Event Bubbling is what you want:
Parent:
childClip.addEventListener('CUSTOM_EVENT', handler);
Child:
this.dispatchEvent(new Event('CUSTOM_EVENT', true, true));
This will propagate it up the display list. The problem with listening to a loader directly is that it looks like this:
Loader
- Content
Without bubbling you'd have to listen to the content directly, which is kind of pointless since you can't listen to it until the content has been loaded.
You don't really need to pass the parent as a parameter , particularly if you intend to listen to your event in the parent itself. What you can do is pass a dispatcher as a parameter and let the dispatcher both dispatch & listen to the event.
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.EventDispatcher;
public class A extends MovieClip
{
public var b:B;
private var _dispatcher:EventDispatcher = new EventDispatcher();
public function A()
{
_dispatcher.addEventListener('test', eventHandler);
this.b = new B(_dispatcher);
}
public function eventHandler(e:Event):void
{
trace("Success");
}
}
}
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.EventDispatcher;
public class B extends MovieClip
{
private var _dispatcher:EventDispatcher;
public function B(dispatcher:EventDispatcher)
{
this._dispatcher = dispatcher;
_dispatcher.dispatchEvent(new Event('test'));
}
}
}