Propagate custom event to Parent - actionscript-3

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'));
}
}
}

Related

Symbol class to document class AS3

I have this code in my document class:
package {
import flash.events.Event;
public class Main extends MovieClip {
public var mainMenu = new MainMenu();
public function Main() {
// constructor code
startGame();
}
public function startGame(){
mainMenu.x = stage.stageWidth/2
addChild(mainMenu);
}
public function initGame(event){
//Adding player with and stuff
}
}
}
And this in my MainMenu class:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MainMenu extends MovieClip {
private var logo = new Logo();
public function MainMenu() {
// constructor code
logo.x = - logo.width/2;
logo.y = 50;
logo.addEventListener(MouseEvent.CLICK, initGame);
addChild(logo);
}
}
}
I get this message when i try to test the game; 1120: Access of undefined property initGame.
Why can't the mainMenu.as access the public function initGame?
Thanks
You require a reference to the Main object inside MainMenu. You can pass it through the constructor:
mainMenu = new MainMenu(this);
And inside MainMenu you can now register an event to a method inside Main.
public function MainMenu(main:Main) {
logo.addEventListener(MouseEvent.CLICK, main.initGame);
//...
}

Actionscript 3 - Class Referring Errors

I a document class (Main) and a class connected to a symbol (MainMenu), and I get an error I just can't figure how to solve.. I get this error:
1136: Incorrect number of arguments. Expected 1.
it is reffering to "public var mainMenu = new MainMenu();" in my document class.
Anyways, here are my classes:
Main(document class):
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Stage;
public class Main extends MovieClip {
public var mainMenu = new MainMenu();
public function Main() {
// constructor code
startGame();
}
public function startGame(){
addChild(mainMenu);
}
public function initGame(event){
//Adding player and such..
}
}
}
MainMenu:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MainMenu extends MovieClip {
private var logo = new Logo();
public function MainMenu(main:Main) {
// constructor code
mainMenu = new MainMenu(this);
logo.addEventListener(MouseEvent.CLICK, main.initGame);
placeButtons(event);
}
public function placeButtons(event:Event){
logo.addEventListener(MouseEvent.CLICK, initGame);
logo.x = - logo.width/2;
logo.y = 50;
addChild(logo);
trace ("MainMenu added");
}
}
}
Thanks
A few pointers...
Be mindful of your indentation.
Datatype your variables, arguments, and function returns.
Your MainMenu class was self instantiating itself (that's an infinite loop)
If you really need direct access to another classes function, consider making the child class extend the parent class. Alternatively, you could make the specific function a static function and call the function directly off the class without passing variable references. For example: Main.initGame()
Here are your classes, with a potential solution...
Main:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Stage;
public class Main extends MovieClip {
public var mainMenu:MainMenu;
public function Main() {
mainMenu = new MainMenu();
addChild(mainMenu);
}
public function initGame(e:Event):void {
//Adding player and such..
}
}
}
MainMenu:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MainMenu extends MovieClip {
private var logo:Logo;
public function MainMenu() {
// Wait for it to be added to the parent.
logo = new Logo();
addChild(logo);
addEventListener(Event.ADDED_TO_STAGE, placeButton);
}
private function placeButton(e:Event):void {
// We only need this to happen once, so remove the listener
removeEventListener(Event.ADDED_TO_STAGE, placeButton);
// Now that we've formed the connection, we can reference the function dynamically
logo.addEventListener(MouseEvent.CLICK, this["parent"].initGame);
logo.x = - logo.width/2;
logo.y = 50;
}
}
}
I've left the structure as similar to your original intent as possible, but the above function reference is poor form. As a general rule, children should not have connections to their parents as it's a potential memory leak. You might instead add the event listener from your Main class.

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;
}
}

AS3 Object appears onClick where the mouse clicks on the stage

I want in actionscript to place an object in my library onto the stage where I clicked. Seems easy? Right? TOTALLY BLANKING. any help would be awesome :)
my code thus far is:
package code {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class Main extends MovieClip {
public var redBox: Box = new Box(mouseX, mouseY);
public function Main() {
// constructor code
stage.addEventListener(MouseEvent.CLICK, mouseClickEvent);
}
public function mouseClickEvent(e:MouseEvent):void {
addChild(redBox);
}
}
}
that is the main and then the box code is:
package code {
import flash.display.MovieClip;
public class Box extends MovieClip{
public function Box(myX:Number, myY:Number) {
// constructor code
myX = x;
myY = y;
}
}
}
Just do this :
package code {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class Main extends MovieClip {
public var redBox: Box = new Box();
public function Main() {
// constructor code
stage.addEventListener(MouseEvent.CLICK, mouseClickEvent);
}
public function mouseClickEvent(e:MouseEvent):void {
redBox.x = stage.mouseX;
redBox.y = stage.mouseY;
addChild(redBox);
}
}
}

AS3 Dispatch Custom Event from class to class

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);
}
}