Ссылочные объекты на сцене / кадре из класса документа - PullRequest
1 голос
/ 08 июня 2011

Я искал вокруг и нашел похожие вопросы к этому, но ответы (даже принятые, даже!) Либо хакерские, похоже, имеют мало общего с реальным вопросом, либо просто не работают, когда я пытаюсь их.

Я пытаюсь ссылаться на объекты на сцене в текущем кадре из класса документа в ActionScript 3 в Flash CS3. В этом примере я пытаюсь получить динамическое текстовое поле с именем экземпляра «question_txt», но есть также кнопки и другие вещи, которые мне понадобятся, чтобы включить прослушиватели событий и тому подобное.

Я установил флажок «Автоматически объявлять этапные экземпляры» в настройках публикации, поэтому ссылки должны быть там - фактически, если я пытаюсь объявить их в классе, я получаю ошибки о конфликте с именем - но когда я пытаюсь сослаться на эти объекты (одним из нескольких способов, которые я сейчас пробовал!), я ВСЕГДА ПОЛУЧУ НЕДЕЙСТВИТЕЛЬНО.

package {
    import flash.display.MovieClip;
    import flash.display.SimpleButton;
    import flash.display.Stage;
    import flash.text.TextField;
    import flash.net.navigateToURL;
    import flash.net.URLRequest;
    import flash.net.URLLoader; 
    import flash.events.Event;

    public class DecisionTree extends MovieClip {

        private var tree_xml:XML;
        private var current_node:String;

        public function DecisionTree():void {
            trace("Constructor");
            tree_xml = new XML();
            tree_xml.ignoreWhitepace = true;
            loader = new URLLoader();
            loader.addEventListener(Event.COMPLETE,
                function(e:Event):void {
                    tree_xml = new XML(e.target.data);
                    goToNode('main');
                });
            loader.load(new URLRequest("decision_tree.xml"));
        }

        private function goToNode(name:String):void {
            trace("goToNode " + name);
            current_node = name;
            node_xml = tree_xml.node.(attribute('name') == name)[0];
            node_frame = parseInt(node_xml.attribute('frame'));
            node_question = node_xml.question.text();
            gotoAndPlay(node_frame); // will goto frame 35 where the stuff is

            // ARRRRRGH EVERYTHING'S COMING UP NULL!!!
            // TypeError: Error #1009: Cannot access a property or method of a null object reference.
            question_txt.text = node_question;

            //q = question_txt as TextField;
            //q.text = node_question;

            //qtxt = stage.getChildByName('question_txt') as TextField;
            //qtxt.text = node_question;

        }
    }
}

Ответы [ 4 ]

4 голосов
/ 08 июня 2011

Простой факт заключается в том, что вы не можете полагаться на это, чтобы работать:

gotoAndStop(2);
thing_on_frame_2.foo(); // no guarantee this will work.

Скорее всего, другие ответы, которые вы видели, выглядят смешными, потому что - это , но лучше нетобойти это.Фактически не будет гарантировано, что точка воспроизведения будет находиться во фрейме 2 сразу после вызова gotoAndFoo (), и если это не так, то нет гарантии, что объекты, помещенные в fla, будут созданы к моменту, когда вы попытаетесьчтобы получить к ним доступ.Раньше это было допустимо и допустимо в AS2, но в AS3 его уже нет.

Как правило, для решения этой проблемы вам необходимо выполнить одно из следующих действий:

  1. Убедитесь, что на него ссылаютсяобъект существует во всех кадрах временной шкалы.
  2. Добавьте скрипт для работы в качестве обратного вызова, который позволяет узнать, когда вы достигли рассматриваемого кадра.Это может быть либо сценарий фрейма, написанный на fla, либо тот, который вы добавляете на уровне класса с помощью функции addFrameScript.

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

Хаки или нет, вот как это делается.

РЕДАКТИРОВАТЬ с дополнительной информацией:

Я знаю, что если вы проследите текущий кадр, то будет возвращен номер, на который вы только что дали указание игровой головке перейти.Проблема в том, что нет никакой гарантии, что объекты на сцене в fla будут или не будут созданы к моменту, когда вы запросите их в коде.Вот почему вы используете рамочный скрипт, поскольку к тому времени гарантированно будут созданы объекты.

Что касается вопроса о том, есть ли события, которые вы можете прослушивать, которые гарантированно будут отправлены после построения, ответ таков:"Может быть. На какую версию Flash Player вы ориентируетесь?"Наиболее известным событием фрейма является ENTER_FRAME, поскольку оно поддерживается с самого начала.Со временем мы получили EXIT_FRAME, FRAME_CONSTRUCTED и т. Д., Которые все отправляют в разное время.FRAME_CONSTRUCTED - это тот, который вы хотите прослушать, но не очень громоздко и не практично добавлять слушателя FRAME_CONSTRUCTED всего на одну долю секунды, в которой он вам нужен, и затем немедленно его удалять, и, конечно, он не будет компилироваться, если вас принудительно заставятработать в CS3 (и приведет к падению FP9).

Я использую addFrameScript как лучший способ сделать это.Это было недокументировано в течение долгого времени (может быть, на самом деле все еще может быть), но это тот способ, которым флеш-компилятор внутренне присоединяет скрипт, который вы пишете в fla на временной шкале, к «кадрам» фрагмента ролика.

0 голосов
/ 08 июля 2015

Объект должен существовать на сцене для одного целого кадра, прежде чем вы сможете ожидать какого-либо значимого взаимодействия с ним через код. Это верно всегда. Если есть сомнения, подождите один кадр.

0 голосов
/ 15 июля 2011

Я стараюсь не использовать класс документа и ставить пустой символ на сцене с базовым классом, а затем рассматривать этот класс как класс документа.

0 голосов
/ 08 июня 2011

U не может получить доступ к элементам, которые находятся в другом фрейме, кроме самого скрипта / кода. В этом случае основной класс находится на первом кадре. Так что, в сущности, лучшим руководством является то, что вы помещаете все элементы в 1. рамку, а затем скрываете / отображаете их при необходимости.

Но если вы не можете этого сделать по какой-либо причине, я советую, чтобы в любом фрейме, в котором есть элементы, в главном документе была установлена ​​переменная, указывающая на этот элемент.

Например:

в кадре 2. у вас есть элемент question_txt, и в этом кадре укажите код:

MovieClip(root).question_txt = question_txt

и в основной класс поставьте переменную question_txt: TextField:

public var question_txt:TextField;

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

...