Question

I have two classes

A main class - Class Game

Public Class Game
{

    private var m_navButtons:NavButtons;

    public function Game( )
    {
         setUpLevelSelect();


    }

    public function setUpLevelSelect():void
    {
        addChild(levelsMovieClip);
        // when i click a level it plays the game

    }
    public function playGame():void
    {
       // plays game and add navButtons
       m_navButtons = new NavButtons( this.stage );

    }

}

another class that adds small navigation buttons to the game stage called navButtons

public class NavButtons extends MovieClip
{
  public function NavButtons( stage:Stage )
  {
      // addNavigation to stage
      m_stage = stage;

      m_stage.addChild( icon );

      // addeventlisteners
      icon.backButton.addEventListener( MouseEvent.CLICK, goBackToLevelSelect );

  }

  public function goBackToLevelSelect( event:MouseEvent ):void
  {

// now i would like to call Game.setUpLevelSelect();


// but when i click the icon.backButton it says Cannot access a property or method of a null reference 
  }

}

at the top of NavButtons i have put public var game:Game;

I'v got a feeling its because im tring to go back to my main document class "Game" but im not sure how to get round it.

Was it helpful?

Solution

There are a few ways you can do this.

The first way is to dispatch an event. This is the proper way for a child to communicate with its parent.

in Game:

navButtons.addEventListener( "customEventTypeHere", this.setUpLevelSelect ); 

in NavButtons:

public function goBackToLevelSelect( event:MouseEvent ):void
{
    this.dispatchEvent( new Event( "customEventTypeHere" ) );
}

You could also attach a MouseEvent listener directly to the button from Game rather than in NavButtons. You would need to make the backButton public, obviously. This is technically proper, but it removes a level of abstraction since the parent now relies on that backButton object being within the class

In Game:

navButtons.backButton.addEventListener( MouseEvent.CLICK, this.setUpLevelSelect );

You could pass in setUpLevelSelect through the constructor. This is referred to as a callback, rather than a listener. This is a good way to handle this as it means the NavButtons class can be used by other classes with ease. You just pass in an appropriate callback and it works the way you expect it to. It does have the drawback of having a reference to the function, meaning another thing to clean up for Garbage Collection, however.

public var backButtonCallback:Function;
public function NavButton( stage:Stage, backButtonCallback:Function ) {
    this.backButtonCallback = backButtonCallback;
}

public function goBackToLevelSelect( event:MouseEvent ):void
{
    this.backButtonCallback();
}

The last way is a way that shouldn't be used here or in many places at all, honestly. But it is an option, even if it does go against basic OOP principles. Basically, you turn Game into a partial Singleton by storing the instance of it in a static property and access your public function through there. This is not recommended unless you have a specific reason for doing so and can only work if there is only one instance of Game.

In Game:

public static var instance:Game;

public function Game() {
    instance = this;
}

In NavButtons:

public function goBackToLevelSelect( event:MouseEvent ):void
{
    Game.instance.setUpLevelSelect();
}

I can think of a few other ways to do this, but these would definitely be the four you should consider. My personal recommendation is to use the first suggestion

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top