Сцена и занятия - PullRequest
       1

Сцена и занятия

1 голос
/ 18 июля 2011

Я новичок в AS3 и пытаюсь использовать OOP.У меня проблемы с пониманием того, как выйти на сцену с отдельными классами.

Вот пример того, что я пытаюсь сделать:

package game{
import flash.display.*;

public class Main extends MovieClip{

    function Main(){
        var player = new Player();
        var playerBullets = new playerBullet();
        addChild(player.players);
    }

}

package game{
import flash.display.*;

public class Bullet extends Main // also tried with MovieClip and Sprite{

    function Bullet(){
        // empty
    }


    function blah(){
        var someSprite = new someSprite();

        Main.addChild(someSprite);
        stage.addChild(someSprite);
        root.addChild(someSprite);


    }
}
}

Я пропустил другой класс, который вызывает метод бла, так как я чувствую, что он не имеет отношения.

По сути, я хочу знать, как добавлять вещи на сцену в классах, как будто я упускаю что-то решающее.

* РЕДАКТИРОВАТЬ, ЧТОБЫ ВКЛЮЧИТЬ ОШИБКУ *

TypeError: Ошибка # 1009: Невозможно получить доступ к свойству или методу пустой ссылки на объект.в игре :: Bullet / blah () в игре :: Player / fire ()

Ответы [ 4 ]

5 голосов
/ 18 июля 2011

Не обязательно расширять main, чтобы создать что-то вроде класса bullet, это может быть собственный класс, который расширяет Sprite или MovieClip.Объект stage считается глобальным объектом, так как он является одноэлементным (за исключением случая Adobe AIR, где вы можете иметь один этап на NativeWindow, который вы создаете).Таким образом, любой объект, который расширяет DisplayObject или имеет DisplayObject в своей цепочке наследования, будет по умолчанию иметь ссылку на стадию через геттер, который заполняется автоматически при добавлении displayObject в список отображения.Это может произойти либо путем добавления клипа непосредственно к корневому объекту сцены, либо путем добавления клипа в качестве дочернего элемента другого клипа, который в конечном итоге подключается к сцене.Например:

var clip1:MovieClip = new MovieClip();

stage.addChild(clip1); //Clip 1 can now access the stage reference internally.

ver clip2:MovieClip = new MovieClip(); //Right now, clip2 cannot access the stage reference interally.

clip1.addChild(clip2); //Now clip2 can access the internal stage reference because it has been connected to the display list through clip1.

Другая ошибка, которую совершают люди, - это доступ к этапу в типизированном классе DisplayObject (например, в вашем основном классе) без предварительного подтверждения того, что сам объект был добавлен на этап.Вы делаете это, слушая событие Event.ADDED_TO_STAGE в конструкторе класса, например так:

public class Main extends MovieClip{

    function Main(){
        if(stage){
            //The stage reference is present, so we're already added to the stage
            init();
        }else{
            addEventListener(Event.ADDED_TO_STAGE, init);
        }
        var player = new Player();
        var playerBullets = new playerBullet();
        addChild(player.players);
    }

    private function init(e:Event = null)
    {
         trace("Added to stage, the stage reference is now populated and stage can be accessed");
    }

}

Это может быть вашей проблемой, но трудно сказать, так как вы не указалилюбые ошибки.Тем не менее, это, вероятно, проблема или будет для вас, так как это довольно часто.Внутри метода init () вы можете установить флаг, чтобы при вызове внешним классом вашего метода Main.blah () вы могли убедиться, что ссылка на этап существует, прежде чем пытаться что-то добавить к этапу.Однако учтите, что в вашем основном классе вы просто говорите:

addChild (someChild);

или

this.addChild (someChild);

вы не добавляете этого дочернего элемента в рабочую область, а скорее в объект Main, который является объектом на основе MovieClip или Sprite, который автоматически присоединяется к рабочей области, когда вы устанавливаете его в качестве класса Document.Надеюсь, эта информация поможет.

Обновление
Чтобы объяснить список отображения немного подробнее:

Думайте обо всех ваших видеоклипах как о блюдах, а о сцене - как о столе.,Доступ к столу можно получить только из блюда, если блюдо размещено непосредственно на столе или если блюдо сложено поверх другого блюда, которое касается стола.Если у вас есть 10 тарелок, наложенных друг на друга, все они в конечном итоге касаются стола, соединяясь друг с другом.По сути, это визуализация списка отображения Flash.Вы ставите посуду на стол, используя addChild (блюдо).Если вы не поместили объект где-нибудь на стол и попытаетесь получить доступ к таблице из этого объекта, вы потерпите неудачу.Вы получаете ошибку «доступ к неопределенному», потому что вызываете метод «blah ()», который обращается к этапу (таблице) до того, как пуля (блюдо) была добавлена ​​к этапу (таблице).Поэтому вы должны сначала либо добавить пулю на сцену, либо добавить ее к другому объекту, который уже был добавлен на сцену.Измените свой код следующим образом:

var myBullet:Bullet = new Bullet();
stage.addChild(myBullet);
//Or, if this class, assuming it's the player class, has already been added to the stage, just do this:
this.addChild(myBullet);
myBullet.blah();

Тем не менее, вы должны все еще иметь некоторую проверку ошибок в вашем методе "бла", чтобы убедиться, что этап доступен:

  function blah(){
        var someSprite = new someSprite();
        if(stage){
            Main.addChild(someSprite);
            stage.addChild(someSprite);
            root.addChild(someSprite);
        }else{
            trace("error, stage not present");
        }
    }

Однако выСледует также отметить, что добавление этого потомка в Main, затем stage, затем root в последовательности, это не дублирует объект someSprite.Когда вы добавляете экранный объект к новому родительскому объекту, объект автоматически извлекается из его текущего родителя и перемещается к новому.Таким образом, весь этот код в конечном итоге добавит someSprite в root, что, как я полагаю, не удастся, поскольку root - это не экранный объект, а глобальная ссылка, в основном используемая для доступа к глобальным объектам, таким как stage и объект Loader, используемый для загрузки SWF..

3 голосов
/ 18 июля 2011

Вы никогда не должны звонить stage.addChild. Должен быть только один дочерний элемент рабочей области, и это класс документа.

Вы делаете отображение MovieClip на экране, добавляя его в список отображения сцены.

Stage
   + Main Timeline
       +Anything
       +Else
       +You
       +Want

Предполагая, что Main - это ваш класс документов для основной временной шкалы ...

 // inside of Main's constructor...

 public function Main(){
   var anything:MovieClip = new MovieClip();
   var Else:TextField = new TextField();
   var you:SimpleButton = new SimpleButton();
   var want:Sprite = new Sprite();
   this.addChild(anything);
   this.addChild(Else);
   this.addChild(you);
   this.addChild(want);
 }       

Тогда для того, чтобы добавить детей еще ниже, например, если вы хотите, чтобы что-то было потомком "всего" такого, что у вас есть ...

Stage
   + Main Timeline
       +Anything
            +And
            +Everything
       +Else
       +You
       +Want




 public function Main(){
   var anything:MovieClip = new MovieClip();
   var Else:TextField = new TextField();
   var you:SimpleButton = new SimpleButton();
   var want:Sprite = new Sprite();

   this.addChild(anything);
   this.addChild(Else);
   this.addChild(you);
   this.addChild(want);

   var And:Sprite = new Sprite();
   var everything:Sprite = new Sprite();
   anything.addChild(And);
   anything.addChild(everything);
 }  

РЕДАКТИРОВАТЬ: Ascension Systems спрашивает, почему вы никогда не должны добавлять какой-либо экранный объект непосредственно как дочерний элемент сцены. Самый простой ответ заключается в том, что вы никогда не сможете гарантировать, что то, что, по вашему мнению, вы создаете в качестве класса документа или основной временной шкалы, фактически будет использоваться как таковое. Использование вами стадии может впоследствии помешать загрузке вашего SWF как дочернего элемента более крупного приложения, в зависимости от того, что именно вы сделали. Если вы прямо полагаетесь на сцену, это может означать, что вы делаете некоторые предположения о характере списка отображения, который может не сохраниться в будущем. Это способ, которым он нарушает модульность (что не то же самое, что ломать oop).

Зачем добавлять на сцену, когда вы можете просто создать все свое приложение в виде мувиклипа, которое будет полностью автономным, не полагаясь на концепцию «стадии», выходящей за рамки того, что требуется для изучения координат мира? Таким образом, вы можете быть намного более модульным в своем дизайне и ничего не жертвовать.

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

2 голосов
/ 18 июля 2011

Каждый экранный объект имеет свойство с именем stage, которое является нулевым, пока этот объект не будет добавлен в дерево отображения.

Когда вы не уверены, был ли объект добавлен на сцену, для этого можно использовать слушателя:

public class Main extends MovieClip
{
    import flash.events.Event;

    public function Main():void
    {
        if(stage) {
            init();
        } else {
            this.addEventListener(Event.ADDED_TO_STAGE,init);
        }
    }

    private function init(evt:Event = null):void
    {
        this.removeEventListener(Event.ADDED_TO_STAGE,init);
        //object is now definitely on the display tree
    }
}
1 голос
/ 18 июля 2011

Я собираюсь сделать дикий удар в темноте.

stage - это свойство, реализованное примерно так:

public function get stage():Stage {
    var s:DisplayObject = this;
    while(s.parent) s = s.parent;
    return s as Stage;
}

root очень похоже, но останавливаетсяуровень ниже stage (root - это потомок stage).

Эти свойства работают только , когда объект, для которого вы их вызываете , находится где-то на сцене .Не имеет значения, где, потому что цикл while будет идти вверх по иерархии, чтобы добраться до узла stage наверху.Но если он не на сцене, то parent будет нулевым.

Так что, если ваш мувиклип не на сцене, то его ссылка на stage будет нулевой.То же самое касается root.

Я предполагаю, что вы звоните blah до того, как пули будут добавлены на сцену?В этом случае ваш вызов stage.addChild(someSprite) будет содержать ошибку Null Reference (stage - ноль).

Поэтому вам нужно либо сначала добавить маркеры на сцену, либо вам нужно передать stage в качестве параметра:

function blah(s:Stage){
    var someSprite = new someSprite();
    s.addChild(someSprite);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...