AS3 Как добавить Класс на сцену из таймера?

много помощи от вас, ребята :). Мой следующий вопрос здесь :).

У меня есть таймер в классе MyTimer.as и клипе Thief1_mc.as. Как я могу добавить ребенка (Thief1_mc) на сцену из MyTimer? С виду все просто, проблема только в свойстве "сцена". Класс MyTimer не может отправить «сцену» в качестве аргумента, потому что он не находится на самой сцене. Я попытался добавить MyTimer на сцену в классе Main, например addChild (MyTimer), трассировка говорит, что MyTimer находится на сцене, но я все еще не могу передать аргумент стадии Thief1_mc. Мне нужно, чтобы этот аргумент был отправлен, потому что класс Thief1_mc должен добавить себя на сцену, используя свойство «стадия».

Код:

public class Thief1_mc extends MovieClip
{

    //this variable type Stage will contain stage
    private var stageHolder:Stage;

    public function Thief1_mc()
    {
        //constructor
    }

    //function that creates this object with passed "stage" argument from the caller
    public function createItself(st):void
    {
        //variable that contain the stage so I can use this argument anywhere in the class 
        stageHolder = st;
        //i have to refer to the stage by passed "st" parameter to create this object
        stageHolder.addChild(this);
        //initial position
        this.x = 380;
        this.y = 230;
    }

}

}

Класс MyTimer и вызывающий объект "_thief1.createItself(stage)" с аргументом stage

public class MyTimer extends Sprite
{
    private static var nCount:Number = 120;
    private static var currentCount:Number;
    private static var _timer:Timer = new Timer(1000,nCount);

    private static var _timerDispather:Timer;
    private static var _thief1:Thief1_mc = new Thief1_mc ;

    public function MyTimer()
    {
        // constructor code
    }

    //another timer
    private static function increaseInterval(interval:int):void
    {
        _timerDispather = new Timer(interval);
        _timerDispather.addEventListener(TimerEvent.TIMER, onUpdateTimeAnotherTimer);
        _timerDispather.start();
    }
    //another timer;
    private static function onUpdateTimeAnotherTimer(e:Event):void
    {

        _thief1.createItself(stage);//the most important part
    }

    public static function activateTimer():void
    {
        currentCount = nCount;
        _timer.addEventListener(TimerEvent.TIMER, onUpdateTime);
        _timer.start();
    }

    public static function deactivateTimer():void
    {
        _timer.removeEventListener(TimerEvent.TIMER, onUpdateTime);
        _timer.stop();
        _timer.reset();
        currentCount = nCount;

        //another timer
        _timerDispather.removeEventListener(TimerEvent.TIMER, onUpdateTimeAnotherTimer);
        _timerDispather.stop();
        _timerDispather.reset();
    }

    private static function onUpdateTime(e:Event):void
    {
        currentCount--;


        if (currentCount == 0)
        {
            _timer.removeEventListener(TimerEvent.TIMER, onUpdateTime);
            _timer.stop();
            _timer.reset();

        }
    }
}

}


person irnik    schedule 17.04.2013    source источник
comment
Просто выбросив это, ваша функция createItself(st):void должна быть createItself(st:Stage):void.   -  person Jonny Henly    schedule 17.04.2013


Ответы (1)


Ваш код перевернут в нескольких местах. Это не очень приятно, и проблемы, которые у вас есть сейчас, будут десятикратно возрастать на каком-то этапе вашего проекта.

Во-первых, ваш класс MyTimer не должен расширять Sprite. Он не визуализируется и ничего не представляет графически.

Во-вторых, ваш класс таймера берет на себя больше, чем должен. Я бы пересмотрел его, чтобы управлять только вашими таймерами и событиями таймера. Создайте список в своем классе таймера, который будет содержать некоторые другие элементы, которые могут иметь триггеры метода для выполнения других действий, таких как создание и добавление Thief1_mc.

Упрощенная версия этого может выглядеть так:

public class Updater
{

    private var _timer:Timer;
    private var _toUpdate:Vector.<IUpdatable> = new Vector.<IUpdatable>();


    public function Updater()
    {
        _timer = new Timer(60);
        _timer.start();
        _timer.addEventListener(TimerEvent.TIMER, _notifyUpdatables);
    }


    private function _notifyUpdatables(e:TimerEvent):void
    {
        for each(var i:IUpdatable in _toUpdate)
        {
            i.update(this);
        }
    }


    public function addUpdatable(updatable:IUpdatable):void
    {
        _toUpdate.push(updatable);
    }


    public function removeUpdatable(updatable:IUpdatable):void
    {
        var index:int = _toUpdate.indexOf(updatable);
        if(index >= 0) _toUpdate.splice(index, 1);
    }

}

Отсюда нам нужно создать интерфейс, который мы реализуем для классов, которые мы хотим иметь возможность вызывать update() каждый раз, когда тикает таймер Updater:

public interface IUpdatable
{
    function update(updater:Updater):void;
}

Теперь, что я бы сделал в вашем случае, это класс, который расширяет Sprite и управляет графикой приложения/игры. Он будет реализовывать интерфейс IUpdatable, как я описал, а также может иметь дело с добавлением вашего Thief1_mc:

public class View extends Sprite implements IUpdatable
{

    public function update(updater:Updater):void
    {
        // Create a Thief.
        var thief:Thief = new Thief();

        updater.addUpdatable(thief);
        addChild(thief);
    }

}

Ваш Thief может использовать интерфейс IUpdatable, который у нас есть, и быть добавленным в очередь обновлений при его создании, как я сделал выше. Просто чтобы иметь полный пример, вот класс Thief:

public class Thief extends Sprite implements IUpdatable
{

    public function update(updater:Updater):void
    {
        // Make this Thief so some stuff.
        //
    }

}

И вот как вы можете связать все это вместе в своем классе документа:

public class App extends Sprite
{

    private var _updater:Updater;
    private var _view:View;


    public function App()
    {
        _updater = new Updater();
        _view = new View();

        _updater.addUpdatable(_view);

        stage.addChild(_view);
    }

}

Поначалу это может показаться немного ошеломляющим, и вам может показаться, что это большая работа, но теперь у вас есть хорошая чистая основа для легкого добавления дополнительных элементов.

Вместо того, чтобы ваш один класс пытался управлять таймерами и добавлять воров, как это было изначально, мы разделили обязанности и немного упростили процесс. Updater имеет дело исключительно с хранением IUpdatable экземпляров и вызовом их метода update() каждый раз, когда Timer в нем тикает. Класс View управляет графикой, а также добавляет Thief каждый раз, когда он обновляется через класс Updater. View был добавлен на сцену изначально, поэтому все, что вам нужно сделать, это добавить воров в себя, чтобы они появились.

Если вы возьмете это и реструктурируете работу таймеров в Updater, я думаю, вы окажетесь там, где хотели, но со значительно лучшим пониманием и структурой.

person Marty    schedule 17.04.2013
comment
Спасибо за Ваш ответ. Я изучу ваш код, но он кажется мне немного сложным для такой простой задачи. В основном мне нужно создавать объект на сцене каждый раз, когда MyTimer тикает. Меня больше всего беспокоит то, что MyTimer не может получить доступ к стадии свойства, даже если MyTimer добавлен на сцену классом Main!?! Ну, я знаю, что если объект находится на сцене, он должен иметь доступ к свойству сцены ??? Еще раз спасибо Марти - person irnik; 17.04.2013
comment
@irnik Конечно, чтобы решить вашу конкретную проблему как можно скорее, просто создайте статический метод в своем классе MyTimer, например public static function setState(stage:Stage), который затем устанавливает свойство в классе, которое вы можете использовать для ссылки на сцену. - person Marty; 17.04.2013
comment
@irnik Простите мой длинный ответ, но я уверен, что вы вернетесь сюда в ближайшем будущем, когда ваш код станет неуправляемым, и возьмете из него несколько указателей :) - person Marty; 17.04.2013
comment
:) Я знаю Марти, но как новичок я предпочитаю работать с персоналом, с которым я знаком :) - person irnik; 17.04.2013
comment
@irnik Верно, но лучше познакомиться с хорошими стилями программирования на раннем этапе, чем делать это самому и многим другим разработчикам, которые сначала изучают «простой» способ, а затем вынуждены отступать и в конце изучать правильный путь. так или иначе. - person Marty; 17.04.2013
comment
Согласен, но Марти, как ты собираешься объяснить эту проблему: я добавил MyTimer на сцену с помощью addChild(MyTimer), и у него все еще нет доступа к свойству stage!?! - person irnik; 17.04.2013
comment
@irnik Скорее всего, ваше событие таймера срабатывает один раз, прежде чем вы получите доступ к сцене. - person Marty; 17.04.2013
comment
да, в этом может быть проблема. Спасибо. Я не могу понять, как использовать эту общедоступную статическую функцию setState(stage:Stage)? - person irnik; 17.04.2013
comment
@irnik Посмотрите здесь. По сути, я установил переменную уровня класса _stage, которой будет назначен этап через setStage(). Затем в классе вы можете просто использовать _stage для обозначения сцены. - person Marty; 17.04.2013