在主文档类中为外部类添加事件侦听器

时间:2013-02-11 23:30:30

标签: actionscript-3

我有一个小项目,我正在努力帮助学习as3。它是与基础游戏设计与Actionscript 3.0的书的变化。我只使用fla来拥有一个文档类。所有艺术都在as文件中加载。在书中,他只是将所有代码放在文档类中,我跟着它并按预期工作。我试图将代码分解为单独的类来获取OOP的句柄。一个类创建一个背景 - Background.as,一个创建一个字符 - Character.as,一个创建一个按钮,我为6个不同的按钮实例化6次 - GameButton.as。当然还有GameWorld.as这是文档类。一切都加载并按预期显示。但是,当我尝试为按钮添加eventListener时,我没有得到任何响应。我已经尝试将eventListener放在GameButton.as中,并且还在GameWorld.as中尝试过,但两者都没有。我在实例化各种类时也传递了对舞台的引用,因为当我在GameWorld.as中尝试addChild时,什么都不会出现。我搜索了网站,发现了类似的东西,但似乎没有帮助。提前感谢您的任何建议。这是代码:

GameWorld.as

package 
{
    import flash.net.URLRequest;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.DisplayObject
    import flash.events.MouseEvent;
    import GameButton;
    import Character;
    import Background;

    [SWR(width = "550", height = "400", backgroundColor = "#FFFFFF", frameRate = "60")]

    public class GameWorld extends Sprite
    {
        //public variables
        //Background
        public var gameBackground:Background;

        //Character
        public var catCharacter:Character;

        //Buttons
        public var upButton:GameButton;
        public var downButton:GameButton;
        public var growButton:GameButton;
        public var shrinkButton:GameButton;
        public var vanishButton:GameButton;
        public var spinButton:GameButton;

        public function GameWorld ()
        {
            //Add the background to the stage
            gameBackground = new Background("../images/background.png", stage);

            //Add the character(s) to the stage
            catCharacter = new Character("../images/character.png", stage);

            //Set initial character position
            catCharacter.CharacterPos(225, 150);

            //Add the buttons to the stage
            upButton = new GameButton("../images/up.png", stage, 25, 25);
            downButton = new GameButton("../images/down.png", stage, 25, 85);
            growButton = new GameButton("../images/grow.png", stage, 25, 145);
            shrinkButton = new GameButton("../images/shrink.png", stage, 425, 25);
            vanishButton = new GameButton("../images/vanish.png", stage, 425, 85);
            spinButton = new GameButton("../images/spin.png", stage, 425, 145);

            //Button event handlers
            upButton.addEventListener(MouseEvent.CLICK, upButtonHandler);

        }


        public function upButtonHandler(event:MouseEvent)
        {
            trace("You clicked the up button!");
            catCharacter.CharacterMove(15);
        }

    }

}

GameButton.as

package 
{
    import flash.net.URLRequest;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.events.MouseEvent;

    public class GameButton extends Sprite
    {
        //public variables
        public var stageRef:Stage;
        public var urlRequest:URLRequest;
        public var gameButtonLoader:Loader;
        public var gameButtonSprite:Sprite;

        //Constructor
        public function GameButton (urlRequest:String, stageRef:Stage, xPos:Number, yPos:Number)
        {
            this.stageRef = stageRef

            this.urlRequest = new URLRequest();
            gameButtonLoader = new Loader();
            gameButtonSprite = new Sprite();

            this.urlRequest.url = urlRequest;
            gameButtonLoader.load(this.urlRequest);
            gameButtonSprite.addChild(gameButtonLoader);
            this.stageRef.addChild(gameButtonSprite);

            gameButtonSprite.buttonMode = true;

            gameButtonSprite.x = xPos;
            gameButtonSprite.y = yPos;
        }

    }

}

Character.as

package 
{
    import flash.net.URLRequest;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.Stage;

    public class Character
    {
        //private variables
        private var stageRef:Stage;
        private var urlRequest:URLRequest;
        private var characterLoader:Loader;
        private var characterSprite:Sprite;

        //public variables
        public var character_x_pos:Number;
        public var character_y_pos:Number;

        //Constructor
        public function Character (urlRequest:String, stageRef:Stage)
        {
            this.stageRef = stageRef;
            this.urlRequest = new URLRequest();
            characterLoader = new Loader();
            characterSprite = new Sprite();

            this.urlRequest.url = urlRequest;
            characterLoader.load (this.urlRequest);
            characterSprite.addChild (characterLoader);
            this.stageRef.addChild (characterSprite);
            characterSprite.mouseEnabled = false;
        }

        //Set the position of the character
        public function CharacterPos(xPos:Number, yPos:Number):void
        {
            characterSprite.x = xPos;
            characterSprite.y = yPos;
        }

        //Move the position of the character
        public function CharacterMove( yPos:Number):void
        {
            characterSprite.y -= yPos;
        }

    }

}

Background.as

package 
{
    import flash.net.URLRequest;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.Stage;

    public class Background
    {
        //Private variables
        private var stageRef:Stage;
        private var urlRequest:URLRequest;
        private var backgroundLoader:Loader;
        private var backgroundSprite:Sprite;

        //Constructor
        public function Background (urlRequest:String, stageRef:Stage)
        {
            this.stageRef = stageRef;
            this.urlRequest = new URLRequest();
            backgroundLoader = new Loader();
            backgroundSprite = new Sprite();

            this.urlRequest.url = urlRequest;
            backgroundLoader.load (this.urlRequest);
            backgroundSprite.addChild (backgroundLoader);
            this.stageRef.addChild (backgroundSprite);
            backgroundSprite.mouseEnabled = false;
        }

    }

}

1 个答案:

答案 0 :(得分:0)

  

所有艺术都加载在as文件中。

这不是我推荐的方法。上帝给了我们Flash IDE是有原因的 - 而且不是编写代码!除非您有实际要求在运行时更改视觉效果,否则任何时候在代码中花费布局和视频时都会浪费。您的路径都是硬编码的事实表明您没有这个要求。

让我们退后一步,想象你有一个包含6个符号的符号,你只需要创建Flash按钮(当你选择Button作为符号类型时)。这些将是SimpleButtons,但在下面的类中,我们只是将它们键入DisplayObject。 Class不关心它们是什么,但是使用Simplebutton会给它们提供up,down,down和hit状态,不需要代码。

请注意,下面假设你已经“自动声明舞台实例”,这是IMO最好的办法。

package view {
   public class NavBar extends Sprite {
      //because you put these on stage in the Symbol, they will be available in the constructor
      public var upButton:DisplayObject;
      public var downButton:DisplayObject;
      public var growButton:DisplayObject;
      public var shrinkButton:DisplayObject;
      public var rotateButton:DisplayObject;
      public var vanishButton:DisplayObject;
      //makes it easier to do the same setup on all buttons
      protected var allButtons:Vector.<DisplayObject> = <DisplayObject>([upButton, downButton, growButton, shrinkButton, rotateButton, vanishButton]);
      public function NavBar() {
         super();
         for each (var btn:DisplayObject in allButtons) {
             btn.buttonMode = true;
             btn.mouseChildren = false;
             btn.addEventListener(MouseEvent.CLICK, onButtonClick);
         }
      }
      protected function onButtonClick(e:MouseEvent):void {
          switch (e.target) {
             case upButton:
                dispatchEvent(new CharacterEvent(CharacterEvent.UP));
                break;
             case downButton:
                dispatchEvent(new CharacterEvent(CharacterEvent.DOWN));
                break;
             case growButton:
                dispatchEvent(new CharacterEvent(CharacterEvent.GROW));
                break;
             case shrinkButton:
                dispatchEvent(new CharacterEvent(CharacterEvent.SHRINK));
                break;
             case rotateButton:
                dispatchEvent(new CharacterEvent(CharacterEvent.ROTATE));
                break;
             case vanishButton:
                dispatchEvent(new CharacterEvent(CharacterEvent.VANISH));
                break;
             default:
               break;
          }
      }

   }
}

请注意,布局代码为零。此代码依赖于自定义事件类。我要写那个事件类,以便它总是起泡。这样,它可以在显示列表上的任何位置发送,并在顶层接收:

package control {
    class CharacterEvent extends Event {
       public static var UP:String = 'characterUp';
       public static var DOWN:String = 'characterDown';
       public static var GROW:String = 'characterGrow';
       public static var SHRINK:String = 'characterShrink';
       public static var ROTATE:String = 'characterRotate';
       public static var VANISH:String = 'characterVanish';
       public function CharacterEvent(type:String) {
          super(type, true, true);//always bubbles
       }
       public function clone():Event {
          return new CharacterEvent(type);
       }
    }
}

现在,如果要手动处理将view.NavBar作为其基类的Symbol的实例化,它将如下所示:

package {
   public var navBar:NavBar;
   class GameWorld {
      public function GameWorld() {
         try {
            var navClass:Class = getDefinitionByName('NavBarSymbol') as Class;
         } catch (e:Error) {
             trace('You need to have a Library symbol called NavBarSymbol');
         }
         if (navClass) {
            navBar = new navClass() as NavBar;
            //unnecessary layout code here
            //Note that this is NOT the responsibility of the child Class!
            addChild(navBar);
         }
         //instantiate character
           ...
         //by listening to the whole Document, you can add other things that
         //dispatch Character events on the display list, like a keyboard listener
         addEventListener(CharacterEvent.UP, moveCharacterUp);
         //listeners for the rest of the character events...
      }
      public function moveCharacterUp(e:CharacterEvent):void {
          //character move logic
      }
      //other handlers
   }
}

就个人而言,我只是将navBar添加到舞台上,然后根本不需要管理它(甚至不用变量引用它),只需为各种角色事件添加事件监听器。

问题的根源似乎不是字符代码。但是,我会给你一些关于它的“最佳实践”指示。

  • AS3中的约定是类成员(属性和方法)是以小写字母开头的驼峰式大小写。所以,characterPos()characterMove()
  • 您的类已在名称中包含字符,因此实际上这些字符应为pos()move()(尽管现在不需要缩短position())。
  • 您的子类在对父项的引用中所做的唯一事情就是添加自己。他们不需要也不应该为此目的引用父母。添加子项是父级的责任(如果您使用舞台,则为Flash Player的责任)。
  • 也就是说,您可以为您的角色提供对类型为IEventDispatcher的父类的引用,并允许角色收听此频道。这个概念称为event bus

请注意,有这么多人做你正在做的事情的原因是Adobe未能记录如何properly use OOP with the timeline。不幸的是,到2009年末/ 2010年初我们中的一些started documenting时,损坏已经完成,并且每个人都认为如果你想编写好的代码,你必须假装时间轴和阶段不存在。

我知道我已经涵盖了很多理由,而且我所说的大部分内容都与你认为的知识直接相矛盾,所以请不要犹豫,提出任何问题。