Flash CS5在舞台上显示不同的“屏幕”作为动画片段

时间:2011-08-02 21:26:49

标签: flash actionscript-3 flash-cs5

this thread提升到新的水平,现在制作一个Main.as课程,以显示我游戏的不同“屏幕”。目前我只有一个名为ControlPanel的屏幕,但最终会有多个级别(每个级别将是一个单独的屏幕)和一个级别选择屏幕等。因此,在这一点上,我失去了对如何让事情进入舞台的控制权(换句话说......它变得非常厚,有多个级别,这个noob的大脑正在被重载lol)。

首先,我拍摄了默认情况下我在舞台上的所有图形(按钮,灯光,仪表,乐谱文本等)并创建了一个新的符号(MovieClip),我称之为ControlPanel并且已选中“导出” for ActionScript“,类名为ControlPanel。所以现在我的游戏舞台是黑色的,我制作了它的文档类Main.as.看起来像这样:

public class Main extends MovieClip {

    public var controlPanel:ControlPanel;

    public function Main() {
        addEventListener(Event.ADDED_TO_STAGE, added);
    }

    private function added(evt:Event):void {
        removeEventListener(Event.ADDED_TO_STAGE, added);

        controlPanel = new ControlPanel(this);
        addChild(controlPanel);
    }
}

运行此功能完美,我的控制面板屏幕右侧弹出到屏幕上。当然所有按钮都不起作用,但这是下一步。所以我修改了我的旧Game.as,现在被称为ControlPanel,并且如下所示:

public class ControlPanel extends MovieClip {
    private var docRef:Main;

    private var _player:Player;
    private var _controller:Controller;

    public function ControlPanel($docRef:Main):void {
        this.docRef = $docRef;

        addEventListener(Event.ADDED_TO_STAGE, added);
    }

    private function added(evt:Event):void {
        removeEventListener(Event.ADDED_TO_STAGE, added);

        _player = new Player(docRef);
        _controller = new Controller(_player, docRef);

        addChild(_player);
    }

现在这是添加我的Player类和我的Controller类。他们基本上有类似的化妆,所以我将在这里展示Player.as课程:

public class Player extends MovieClip {
    private var docRef:Main;
    private var _lights:uint;

    public function Player($docRef:Main):void {
        this.docRef = $docRef;

        addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    }

    private function lightsOut():void {
        switch(_lights) {
        case 1:
        docRef.controlPanel.greenLight1.visible=false;
        break;
        case 2:
        docRef.controlPanel.greenLight2.visible=false;//works
        break;
        case 3:
        docRef.controlPanel.greenLight3.visible=false;//works
        break;
        }
    }

问题是,现在我尝试测试它,我不再获得我之前看到的控制面板图形,但我现在收到错误消息:

  

TypeError:错误#1009:无法访问空对象引用的属性或方法。   在ControlPanel()   在Main / added()

此外,我在Main中注释掉了controlPanel行,并且只是做了一个跟踪(这个);它返回了

  

[object Main]

不应该是舞台或类似的东西吗?从来没有尝试过,所以我不知道它曾经是什么。我在哪里出错?

更新:好的所以我的Controller不仅仅是Player类,而是需要舞台和传递给它的视图的实例可能???那么这就是我所拥有的控制器和一些所需的事件监听器:

public class Controller extends MovieClip {
    private var _model:Object;
    private var _dHandle:Object;
    private var panelView:ControlPanelView; //started playing with this idea but maybe that is the wrong way to go?? Stick with docRef here? or both?

    public function Controller(model:Object, dHandle:Object, $view:ControlPanelView):void {
        this._model = model;
        this._dHandle = dHandle;
        this.panelView = $view;

        docRef.stage.addEventListener(KeyboardEvent.KEY_DOWN, processKeyDown);
        docRef.stage.addEventListener(MouseEvent.MOUSE_DOWN, processMouseDown);
        docRef.ControlPanelView.fireButton.addEventListener(MouseEvent.CLICK, processFirePress);
        docRef.ControlPanelView.cWButton.addEventListener(MouseEvent.CLICK, processCWPress);
        docRef.ControlPanelView.cCWButton.addEventListener(MouseEvent.CLICK, processCCWPress);

正如您所看到的,这是在docRef和View构思之间徘徊的大杂烩。我需要访问我的鼠标和键盘监听器的舞台,但我还需要访问ControlPanelView符号中的按钮。我需要在这里传递视图和docRef吗?如何维护对舞台和ControlPanelView图形的访问?

1 个答案:

答案 0 :(得分:1)

您无法从库中导出某些内容以及具有相同名称的类文件。当您将库项目设置为'Export for ActionScript'时,Flash会创建一个该名称的类来表示该对象,因此要自己创建一个同名的类会导致冲突。

您有两种选择:

<强>继承

您可以使用为ControlPanel创建的类作为库中符号的代码库。要做到这一点,首先给它一个不同的名称,比如ControlPanelBase。然后,您可以将其指定为符号的基类。您可以在IDE中执行此操作,方法是进入符号属性并将Base类从flash.display.MovieClip更改为ControlPanelBase(或您选择的任何名称)。单击小绿色勾号以确保找到该类,然后单击“确定”。

现在,当您使用new ControlPanel(this)表示法创建新的ControlPanel时,它将创建一个使用图形的对象,但也会创建基类中的代码。因为您正在继承,所以您需要将单词private的所有出现更改为protected,以允许任何后代类看到它们。

分隔视图

这是我的偏好,因为当您停止使用IDE而不是生成资产包时,您可以避免在更改代码时重新编译资产。

将图书馆符号的名称更改为更具描述性的名称,例如ControlPanelView。现在,当您使用new ControlPanel(this)创建ControlPanel时,它不会附加任何图形,因此您需要自己执行此操作:

public class ControlPanel extends MovieClip {
    private var docRef:Main;

    private var _player:Player;
    private var _controller:Controller;

    public var view:ControlPanelView; //note that this is public

    public function ControlPanel($docRef:Main):void {
        this.docRef = $docRef;

        addEventListener(Event.ADDED_TO_STAGE, added);
    }

    private function added(evt:Event):void {
        removeEventListener(Event.ADDED_TO_STAGE, added);

        view = addChild(new ControlPanelView()) as ControlPanelView; //add the graphics

        _player = new Player(docRef);
        _controller = new Controller(_player, docRef);

        addChild(_player);
    }
}

现在,要从Player内部访问这些灯光,你会说

docRef.controlPanel.view.greenLight1.visible=false;

你可以看到这变得有点拗口,但是为了缩短它,你可以在创建播放器时传递对ControlPanel而不是Main的引用,或者实际上你可以传递对视图的引用(如果是所有你需要交谈的。

在ControlPanel中:

_player = new Player(view);

新玩家类:

public class Player extends MovieClip {
    private var panelView:ControlPanelView;
    private var _lights:uint;

    public function Player($view:ControlPanelView):void {
        this.panelView = $view;

        addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    }

    private function lightsOut():void {
        switch(_lights) {
        case 1:
        panelView.greenLight1.visible=false;
        break;
        case 2:
        panelView.greenLight2.visible=false;//works
        break;
        case 3:
        panelView.greenLight3.visible=false;//works
        break;
        }
    }
}

关于您的更新,请记住您的Main类和舞台不是一回事。每个显示对象都有一个stage属性,它们都指向同一个东西。这意味着要将您的听众添加到舞台,Main.stageview.stagethis.stage之间没有区别(假设控制器在舞台上)。所以你的控制器看起来像这样:

public class Controller extends EventDispatcher {
    private var _model:Player;
    private var panelView:ControlPanelView;

    public function Controller($model:Player, $view:ControlPanelView):void {
        this._model = $model;
        this.panelView = $view;

        panelView.stage.addEventListener(KeyboardEvent.KEY_DOWN, processKeyDown);
        panelView.stage.addEventListener(MouseEvent.MOUSE_DOWN, processMouseDown);
        panelView.fireButton.addEventListener(MouseEvent.CLICK, processFirePress);
        panelView.cWButton.addEventListener(MouseEvent.CLICK, processCWPress);
        panelView.cCWButton.addEventListener(MouseEvent.CLICK, processCCWPress);
    }
}

在ControlPanel中,您可以像这样创建它:

_controller = new Controller(_player, view);

请注意,我还让你的控制器扩展EventDispatcher而不是MovieClip。优秀的做法是从您需要的最低级别扩展,所以如果它永远不会出现在舞台上但它会发布事件,EventDispatcher是最低限度的。如果它永远不需要分派事件,只将侦听器添加到其他人,那么它不需要扩展任何东西。

基本上,如果您需要时间轴功能,或者您的类将成为库中某些内容的基类,则只扩展MovieClip。对于任何其他标准显示对象,您应该扩展SpriteShape,前者如果您打算添加子项,后者如果您只打算绘制矢量图形。如果您的对象永远不会出现在显示树上,那么通常您需要扩展EventDispatcher或者根本不扩展任何内容。