Adding a key listener in Action Script 3

和自甴很熟 提交于 2019-12-11 14:18:25

问题


I am relatively new to Action Script, and I am trying to make a game of Snake. Obviously I need to implement a global key listener, but I am having odd problems. I tried adding the listener to the application tag but it didn't seem to have any effect (the movie was still able to compile). Whenever I call

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

my program crashes. Below is the content of my main.mxml file:

<?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>

Also, it seems I am getting this stack trace:

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]

I am at my wit's end here, and I appreciate your time and efforts. Thanks!


回答1:


You are getting a runtime error because you attach an event listener to the "stage" property, which is null at the time you try it. Instead of doing this on the "creationComplete" event, try to do this on the "applicationComplete" event. The stage object will be available then.




回答2:


Your application is probably not added to the stage yet, which is why there's an exception being thrown in addKeyEvent. That being said, you don't really need to add the event listener to the stage in this case, you can add it to the application instead, like so:

<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)">

As is implied, you also need to remove the call to addKeyEvent in your creationComplete handler, otherwise you'll still get the exception.




回答3:


It is not obvious to me that to implement this game you need to implement a global key listener. From a context of a Flex Application, wouldn't it make more sense to add the listener to the application tag, not the stage?

What is your full stack trace, what line are you getting the error on? Most likely you just need to add a condition so that you aren't accessing an object that hasn't been initialized yet.



来源:https://stackoverflow.com/questions/4481314/adding-a-key-listener-in-action-script-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!