Symbol class to document class AS3 - actionscript-3

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

Related

Starling Weird Error when Adding Child

I'm Following along with Lynda Tutorial Building Flash Games with Starling
and at some point i got very Weird Error.
I've a Class Background In Package objects:
package objects
{
import core.Assets;
import starling.display.Image;
import starling.display.Sprite;
public class Background extends Sprite
{
private var sky1:Image;
private var sky2:Image;
public function Background()
{
sky1 = new Image(Assets.skyTexture);
addChild(sky1);
sky2 = new Image(Assets.skyTexture);
sky2.y = -800;
addChild(sky2);
}
public function update():void
{
sky1.y += 4;
if(sky1.y == 800)
{
sky1.y = -800;
}
sky2.y +=4;
if(sky2.y == 800)
{
sky2.y = -800;
}
}
}
}
and Menu class in Package states:
package states
{
import flash.display.Sprite;
import core.Game;
import interfaces.IState;
import objects.Background;
import starling.events.Event;
public class Menu extends Sprite implements IState
{
private var game:Game;
private var background:Background;
public function Menu(game:Game)
{
this.game = game;
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(event:Event):void
{
background = new Background();
addChild(background);
}
public function update():void
{
}
public function destroy():void
{
}
}
}
on the line
addChild(background);
I get this weird Error and I'm sure there's no any Errors in any other Class
Implicit coercion of a value of type Background to an unrelated type DisplayObject. Menu.as /Spacer/src/states line 31 Flex Problem
When i debug without this Line i get no Errors.
Your Menu class extends flash.display.Sprite but Background class extends starling.display.Sprite. The Menu class should be extended from the starling Sprite.

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.

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

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