将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图形的访问?
答案 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.stage
,view.stage
和this.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。对于任何其他标准显示对象,您应该扩展Sprite或Shape,前者如果您打算添加子项,后者如果您只打算绘制矢量图形。如果您的对象永远不会出现在显示树上,那么通常您需要扩展EventDispatcher或者根本不扩展任何内容。