在Action Script 3中添加一个键监听器

时间:2010-12-19 02:28:18

标签: flex flash actionscript

我对动作脚本相对较新,我正在尝试制作一个Snake游戏。显然我需要实现一个全局键监听器,但我遇到了奇怪的问题。我尝试将监听器添加到应用程序标签但它似乎没有任何效果(电影仍然能够编译)。每当我打电话

this.stage.addEventListener(KeyboardEvent.KEY_DOWN, key, true);

我的程序崩溃了。以下是我的main.mxml文件的内容:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
 xmlns:mx="http://www.adobe.com/2006/mxml" 
 layout="absolute"
 width="800" 
 height="600"
 frameRate="15"
 creationComplete="creationComplete();"
 enterFrame="enterFrame(event);"
 currentState="MainMenu">

 <mx:states>
  <mx:State 
   name="Game"   
   enterState="enterGame(event)"
         exitState="exitGame(event)">
  </mx:State>
  <mx:State 
   name="LevelEnd">
   <mx:AddChild relativeTo="{myCanvas}" position="lastChild">
    <mx:Button x="380" y="344" label="Continue" id="btnContinue" click="btnContinueClicked(event)" width="90" height="30"/>
   </mx:AddChild>
   <mx:AddChild relativeTo="{myCanvas}" position="lastChild">
    <mx:Label x="10" y="10" text="Congratulations, you finished the level."/>
   </mx:AddChild>
  </mx:State>
  <mx:State name="MainMenu">
   <mx:AddChild relativeTo="{myCanvas}" position="lastChild">
    <mx:Button x="381" y="344" label="Start" id="btnStart" click="startGameClicked(event)" width="90" height="30"/>
   </mx:AddChild>
   <mx:AddChild relativeTo="{myCanvas}" position="lastChild">
    <mx:Image x="10" y="49" source="@Embed('../media/mainmenu.png')"/>
   </mx:AddChild>
   <mx:AddChild relativeTo="{myCanvas}" position="lastChild">
    <mx:Label x="10" y="10" text="Snake Pro" fontSize="20" fontWeight="bold"/>
   </mx:AddChild>
  </mx:State>
 </mx:states>

 <mx:Canvas x="0" y="0" width="100%" height="100%" id="myCanvas"/>

 <mx:Script>
 <![CDATA[   

  protected var inGame:Boolean = false;
  protected var currentLevel:int = 1;
  import flash.events.KeyboardEvent; 

  public function creationComplete():void
     {
   LevelDefinitions.Instance.startup();
   addKeyEvent();
   //stage.focus = stage;
     }

  private function addKeyEvent():void
  {
   this.stage.addEventListener(KeyboardEvent.KEY_DOWN, key, true);
  }

     public function enterFrame(event:Event):void
     {
      if (inGame)
      {
       GameObjectManager.Instance.enterFrame();

       myCanvas.graphics.clear();
       myCanvas.graphics.beginBitmapFill(GameObjectManager.Instance.backBuffer, null, false, false);
       myCanvas.graphics.drawRect(0, 0, this.width, this.height);
       myCanvas.graphics.endFill();
      } 
     }

        private function key(event:KeyboardEvent):void {
            //t1.text = event.keyCode + "/" + event.charCode;

   GameObjectManager.Instance.setDirection(0, 1);
   currentState = "MainMenu";
   inGame = false;
        }

     protected function startGameClicked(event:Event):void
  {
   currentState = "Game"
  }     

     protected function enterGame(event:Event):void
  {
   Mouse.hide();
   GameObjectManager.Instance.startup();
   Level.Instance.startup(currentLevel);
   inGame = true;
     }

     protected function exitGame(event:Event):void
  {
   Mouse.show();
   Level.Instance.shutdown();
   GameObjectManager.Instance.shutdown();
   inGame = false;
  }  

  protected function btnContinueClicked(event:Event):void
  {
   currentLevel = LevelDefinitions.Instance.getNextLevelID(currentLevel);
   if (currentLevel == 0)
   {
    currentLevel = 1;
    currentState = "MainMenu";
   }
   else
   {
    currentState = "Game"
   }
     }
 ]]>
    </mx:Script>

</mx:Application>

此外,我似乎得到了这个堆栈跟踪:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at main/addKeyEvent()[C:\Users\Me\Desktop\Flash\Snake\src\main.mxml:58]
    at main/creationComplete()[C:\Users\Me\Desktop\Flash\Snake\src\main.mxml:52]
    at main/___main_Application1_creationComplete()[C:\Users\Me\Desktop\Flash\Snake\src\main.mxml:10]
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at mx.core::UIComponent/dispatchEvent()[E:\dev\4.x\frameworks\projects\framework\src\mx\core\UIComponent.as:12528]
    at mx.core::UIComponent/set initialized()[E:\dev\4.x\frameworks\projects\framework\src\mx\core\UIComponent.as:1627]
    at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.x\frameworks\projects\framework\src\mx\managers\LayoutManager.as:759]
    at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.x\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1072]

我在这里结束了我的智慧,我感谢你的时间和努力。谢谢!

3 个答案:

答案 0 :(得分:1)

您的应用程序可能尚未添加到舞台中,这就是为什么在addKeyEvent中抛出异常的原因。话虽这么说,在这种情况下你不需要将事件监听器添加到舞台,你可以将其添加到应用程序中,如下所示:

<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute"
    width="800" 
    height="600"
    frameRate="15"
    creationComplete="creationComplete();"
    enterFrame="enterFrame(event);"
    currentState="MainMenu"
    keyDown="key(event)">

正如暗示的那样,你还需要在creationComplete处理程序中删除对addKeyEvent的调用,否则你仍然会得到异常。

答案 1 :(得分:1)

您收到运行时错误,因为您将事件侦听器附加到“stage”属性,该属性在您尝试时为null。而不是在“creationComplete”事件上执行此操作,尝试在“applicationComplete”事件上执行此操作。然后阶段对象将可用。

答案 2 :(得分:0)

对我来说,实现这个游戏并不是很明显,你需要实现一个全局的关键监听器。从Flex应用程序的上下文中,将监听器添加到应用程序标签而不是阶段是不是更有意义?

您的完整堆栈跟踪是什么,您收到错误的是哪一行?很可能你只需要添加一个条件,这样你就不会访问尚未初始化的对象。