舞台和课程

Bab*_*rat 1 actionscript-3

我是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);


    }
}
}
Run Code Online (Sandbox Code Playgroud)

我已经省略了另一个调用blah方法的类,因为我觉得它不相关.

基本上我想知道的是如何在课堂上添加东西,因为它看起来像我错过了一些关键的东西.

*编辑包含错误*

TypeError:错误#1009:无法访问空对象引用的属性或方法.在游戏:: Bullet/blah()在游戏:: Player/fire()

小智 5

你不一定要扩展main来创建类似子弹类的东西,这可以是它自己的类,它扩展了Sprite或MovieClip.stage对象被认为是一个全局对象,因为它是一个单例(除了Adobe AIR,你可以为每个NativeWindow生成一个阶段).因此,任何扩展DisplayObject或在其继承链中具有DisplayObject的对象默认都会通过getter引用该stage,当displayObject添加到显示列表时会自动填充该getter.这可以通过将剪辑直接添加到根阶段对象或通过添加剪辑作为另一个剪辑的子节点来实现,最终连接到舞台.例如:

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.
Run Code Online (Sandbox Code Playgroud)

人们犯的另一个错误是在DisplayObject类型的类(例如您的Main类)中访问阶段,而不首先确保对象本身已添加到舞台中.您可以通过在类的构造函数中侦听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");
    }

}
Run Code Online (Sandbox Code Playgroud)

这可能是您遇到的问题,但由于您没有指定任何错误,因此很难说.但是,这可能是一个问题,也可能适合您,因为它很常见.在init()方法中,您可以设置一个标志,以便在外部类调用Main.blah()方法时,可以确保在尝试向舞台添加内容之前存在舞台引用.但请注意,在您的主课程中,当您只是说:

的addChild(someChild);

要么

this.addChild(someChild);

您不是将该子项添加到舞台上,而是添加到Main对象,该对象是一个MovieClip或基于Sprite的对象,当您将其设置为Document类时,该对象本身会自动附加到舞台上.希望此信息有所帮助.

更新
要更多地解释显示列表:

将所有的影片剪辑视为菜肴,将舞台视为桌子.如果菜肴直接放在桌子上,或者如果菜肴堆放在另一个接触餐桌的菜肴的顶部,您只能从菜肴中取出餐桌.如果你有10块板堆叠在一起,它们最终都会通过它们相互连接而触及桌面.这实际上是闪存显示列表的可视化.你把菜放在桌子上的方法是使用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();
Run Code Online (Sandbox Code Playgroud)

即便如此,您仍应在"blah"方法中进行一些错误检查,以确保该阶段可用:

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

但是你还应该注意到,通过将这个子节点添加到Main,然后是stage,然后按顺序添加root,这不会复制someSprite对象.将显示对象添加到新的父对象时,该对象将自动从其当前父对象中拉出并移动到新对象.因此,所有这些代码都会最终将someSprite添加到root,我相信这会失败,因为root不是显示对象,而是一个主要用于访问全局对象的全局引用,例如用于加载SWF的stage和Loader对象.