1

So I am creating a space shooter game. My document class is Engine and it looks like this:

package Classes
{

import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;

public class Engine extends MovieClip
{

    private var startMenu:StartMenu;
    private var numberOfStars:int = 80;
    public static var enemyList:Array = new Array();
    private var spaceShip:Ship;
    private var hud:HUD;

    public function Engine()
    {
        startMenu = new StartMenu();
        stage.addChild(startMenu);
        startMenu.x = (stage.stageWidth / 2);
        startMenu.y = (stage.stageHeight / 2);
    }

    private function startGame()
    {
        stage.removeChild(startMenu)
        spaceShip = new Ship(stage);
        stage.addChild(spaceShip);
        spaceShip.x = (stage.stageWidth / 2);
        spaceShip.y = (stage.stageHeight / 2);

        spaceShip.addEventListener("hit", shipHit);

        hud = new HUD(stage); //create the HUD
        stage.addChild(hud); //and display it.

        for (var i:int = 0; i < numberOfStars; i++)
        {
            stage.addChildAt(new Star(stage), 1);
        }

        addEventListener(Event.ENTER_FRAME, createFighter);
    }
}

So as you can see I am calling on another class called StartMenu. This is where I am having trouble: Here is the code (Or lack there of)

package  Classes
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.*;

public class StartMenu extends MovieClip
{

    public function StartMenu()
    {
        button1.addEventListener(MouseEvent.CLICK, buttonClicked);
    }

    private function buttonClicked(e:MouseEvent)
    {

    }



}

}

(Ignore the indentation errors, it is correct in the real code) Okay so imagine a button being displayed on the screen. This button is part of the StartMenu Class and is listening for a MouseEvent.CLICK.

Once the button is clicked I need to somehow travel back to the Engine class and call the function startGame() , but I can't just do Engine.startGame() , I have tried setting the function to a public function, and I have tried setting the function to a public static function. no luck. HELP PLEASE?? Any method will be fine, I just need a way for this class to go to the startGame function once the button is clicked!

BenMorel
  • 34,448
  • 50
  • 182
  • 322

4 Answers4

2

Probably the quickest way to do this is to add an Engine variable into the StartMenu class and pass the engine through the start menu's constructor. Here's a short code sample:

StartMenu

public class StartMenu extends MovieClip
{

   private var _engine:Engine // add a new variable to the start menu class
   public function StartMenu(engine:Engine) // add a new parameter to the constructor
   {
      _engine = engine; // set the variable to the value passed through the constructor
      button1.addEventListener(MouseEvent.CLICK, buttonClicked);
   }

   private function buttonClicked(e:MouseEvent)
   {
      _engine.startGame()
   }
}

Engine

public function Engine()
{
    startMenu = new StartMenu(this); 
    // pass through the current instance of engine using the this keyword
    ...
}

public function startGame() // change private to public
{
    ...
}

I hope that helps

Ethan Worley
  • 685
  • 7
  • 13
0

In your Engine.as class, you can put :

public static var instance:Engine;

public static function getInstance():Engine
{
  return instance as Engine;
}

and in constructor of engine class put :

instance = this;

now you can use instace of Engine class and all the public functions and variables anywhere in your project by :

Engine.getInstance().startGame();

It can help you.

Vipul
  • 431
  • 1
  • 5
  • 16
0

There are two types of solving such a case. One is using parent reference or specific reference to call a certain function, as Ethan Worley andwered, the other is using a customizable public clicker setter like this:

public class StartMenu extends MovieClip
{

    private var button1:MovieClip; // or whatever type your button is
    private var startGameFunction:Function;
    public function StartMenu()
    {
        // some initialization code if needed, including allocating button1
        startGameFunction=null;
        button1.addEventListener(MouseEvent.CLICK, buttonClicked);
    }

    public function set startGameClicked(value:Function):void {
        if (value==startGameFunction) return; // nothing to set
        startGameFunction=value;
    }
    private function buttonClicked(e:MouseEvent)
    {
        if (startGameFunction) startGameFunction(); // if there's a function assigned, call it
    }
}

Engine class:

public function Engine()
{
    startMenu = new StartMenu(); 
    startMenu.startGameFunction=this.startGame; 
    // no "()" here, as we are giving a function reference
    ...
}

public function startGame() // change private to public
{
    ...
}
Vesper
  • 18,599
  • 6
  • 39
  • 61
0

I am a bit surprised that no one mentioned an Events based approach yet. That's what I would have used for such a requirement, since I don't really find the idea of passing an entire class instance for just a function call to be that appealing (that would mean that I may be a bit biased towards this approach so please feel free to point out the drawbacks it has, if any).

Inside your Engine class:

public function Engine()
{
    startMenu = new StartMenu();

    startMenu.addEventListner('StartGame', startGame);
    stage.addChild(startMenu);

    ..

}

private function startGame(e:Event)
{

   startMenu.removeEventListner('StartGame', startGame);

   ..

}

Inside your StartMenu class:

private function buttonClicked(e:MouseEvent)
{

   this.dispatchEvent(new Event('StartGame'));

   ..

}
localhost
  • 169
  • 6