2010-12-19 4 views
0

Ich bin relativ neu in Action Script und versuche ein Spiel mit Snake zu machen. Offensichtlich muss ich einen globalen Schlüsselhörer implementieren, aber ich habe seltsame Probleme. Ich habe versucht, den Listener zum Application-Tag hinzuzufügen, aber es schien keinen Effekt zu haben (der Film konnte immer noch kompilieren). Jedes Mal, wenn ich rufeHinzufügen eines Tastenhörers in Action Script 3

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

mein Programm stürzt ab. Im Folgenden ist der Inhalt meiner main.mxml Datei:

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

Auch scheint es, ich diesen Stack-Trace bin immer:

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] 

ich an meinem Latein am Ende bin hier, und ich schätze Ihre Zeit und Bemühungen. Vielen Dank!

Antwort

1

Sie erhalten einen Laufzeitfehler, weil Sie einen Ereignis-Listener an die Eigenschaft "stage" anhängen, die zu dem Zeitpunkt, zu dem Sie sie testen, null ist. Versuchen Sie dies stattdessen beim "creationComplete" -Ereignis im Ereignis "applicationComplete". Das Bühnenobjekt wird dann verfügbar sein.

+0

Ah, ich habe es jetzt funktioniert. Danke vielmals! – kiryu1101

0

Es ist nicht offensichtlich für mich, dass Sie ein globales Schlüssel-Listener implementieren müssen, um dieses Spiel zu implementieren. Ist es aus einem Kontext einer Flex-Anwendung nicht sinnvoller, den Listener dem Application-Tag hinzuzufügen, nicht der Bühne?

Was ist Ihre vollständige Stack-Trace, welche Zeile erhalten Sie den Fehler auf? Wahrscheinlich müssen Sie nur eine Bedingung hinzufügen, damit Sie nicht auf ein Objekt zugreifen, das noch nicht initialisiert wurde.

+0

Ich habe meinen Beitrag bearbeitet, um die vollständige Stapelverfolgung anzuzeigen. Ich habe versucht, den Listener zum Anwendungs-Tag hinzuzufügen, aber es schien keine Wirkung zu haben. – kiryu1101

1

Ihre Anwendung wurde wahrscheinlich noch nicht zur Bühne hinzugefügt, weshalb in addKeyEvent eine Ausnahme ausgelöst wird. Aber sagen, dass Sie nicht wirklich brauchen, den Ereignis-Listener auf die Bühne in diesem Fall hinzufügen möchten, können Sie es hinzufügen, auf die Anwendung statt, etwa 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)"> 

Wie angedeutet ist, müssen Sie auch entfernen der Aufruf von addKeyEvent in Ihrem creationComplete-Handler, andernfalls erhalten Sie immer noch die Ausnahme.

+0

Das Hinzufügen des keyDown-Attributs hat auch nicht geholfen. Es scheint, dass ich etwas vermisse oder mein Film einen logischen Fehler hat. Gibt es eine Methode, die eine Nachricht auslöst (ähnlich der alert() -Funktion von Javascript), die ich in mein Schlüsselereignis einfügen kann? – kiryu1101

+0

Wenn Sie das keyDown-Ereignis zum Haupt-Anwendungs-Tag hinzufügen, müssen Sie auch den Code entfernen, um den Ereignis-Listener manuell hinzuzufügen. – JeffryHouser

+0

@ www.Flextras.com ist korrekt, Sie müssen den Aufruf von addKeyEvent auch in Ihrem creationComplete-Handler entfernen. Ich habe es nicht erwähnt, aber es ist impliziert. Ich werde die Antwort aktualisieren, um expliziter zu sein. –