AS3 - Проблемы с базовым игровым классом

Итак, я создаю космический шутер. Мой класс документа — Engine, и он выглядит так:

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

Итак, как видите, я вызываю другой класс под названием StartMenu. Вот где у меня проблемы: вот код (или его отсутствие)

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)
    {

    }



}

}

(Не обращайте внимания на ошибки отступов, это правильно в реальном коде) Итак, представьте, что на экране отображается кнопка. Эта кнопка является частью класса StartMenu и ожидает события MouseEvent.CLICK.

После нажатия кнопки мне нужно каким-то образом вернуться к классу Engine и вызвать функцию startGame() , но я не могу просто сделать Engine.startGame() , я попытался установить функцию в общедоступную функцию, и у меня есть попытался установить функцию в общедоступную статическую функцию. неудачно. ПОМОГИТЕ, ПОЖАЛУЙСТА?? Любой метод подойдет, мне просто нужен способ, чтобы этот класс мог перейти к функции startGame после нажатия кнопки!


person smarteepants    schedule 13.03.2013    source источник


Ответы (4)


Вероятно, самый быстрый способ сделать это — добавить переменную Engine в класс 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()
   }
}

Двигатель

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
{
    ...
}

Надеюсь, это поможет

person Ethan Worley    schedule 13.03.2013

В вашем классе Engine.as вы можете поместить:

public static var instance:Engine;

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

и в конструкторе класса двигателя поместите:

instance = this;

теперь вы можете использовать экземпляр класса Engine и все общедоступные функции и переменные в любом месте вашего проекта:

Engine.getInstance().startGame();

Это может помочь вам.

person Vipul    schedule 13.03.2013

Есть два типа решения такого случая. Один использует родительскую ссылку или конкретную ссылку для вызова определенной функции, как Итан Уорли и Веред, другой использует настраиваемый общедоступный установщик кликера, подобный этому:

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

Класс двигателя:

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
{
    ...
}
person Vesper    schedule 13.03.2013

Я немного удивлен, что никто еще не упомянул подход, основанный на событиях. Это то, что я бы использовал для такого требования, поскольку я действительно не нахожу идею передачи всего экземпляра класса только для вызова функции такой привлекательной (это означало бы, что я могу быть немного предвзятым к этому подходу, поэтому Пожалуйста, не стесняйтесь указать на недостатки, которые у него есть, если они есть).

Внутри вашего класса Engine:

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

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

    ..

}

private function startGame(e:Event)
{

   startMenu.removeEventListner('StartGame', startGame);

   ..

}

Внутри вашего класса StartMenu:

private function buttonClicked(e:MouseEvent)
{

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

   ..

}
person localhost    schedule 14.03.2013