0

我有一个小项目试图帮助学习 as3。它是《Foundation Game Design with Actionscript 3.0》一书的变体。我使用 fla 只是为了拥有一个文档类。所有艺术作品都加载到 as 文件中。在书中,他只是将所有代码放在文档类中,我跟着,它按预期工作。我正在尝试将代码分解为单独的类以处理 OOP。一类制作背景 - Background.as,一类制作角色 - Character.as,一类制作按钮,我为 6 个不同的按钮 - GameButton.as 实例化 6 次。当然还有 GameWorld.as,它是文档类。一切都按预期加载并显示。但是,当我尝试为按钮添加 eventListener 时,我没有得到任何响应。我尝试将 eventListener 放在 GameButton 中。as 并且还在 GameWorld.as 中尝试过,但都没有奏效。此外,我在实例化各种类时传递了对舞台的引用,因为当我尝试在 GameWorld.as 中添加Child 时,什么都不会出现。我搜索了该站点并发现了类似的内容,但似乎没有帮助。预先感谢您对我的任何建议。这是代码:

游戏世界.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);
        }

    }

}

游戏按钮.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;
        }

    }

}

字符.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;
        }

    }

}

背景.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;
        }

    }

}
4

1 回答 1

0

所有艺术作品都加载到 as 文件中。

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

因此,让我们退后一步,假设您有一个包含 6 个符号的符号,这些符号是您创建的只是 Flash 按钮(当您选择按钮作为符号类型时)。这些将是 SimpleButtons,但在下面的类中,我们只是将它们键入为 DisplayObject。该类并不关心它们是什么,但使用 Simplebutton 可以让它们放弃不需要代码的 up、over、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()
  • 您的 Class 名称中已经包含字符,所以实际上这些应该只是pos()and move()(尽管现在不需要缩短position())。
  • 您的子类对父类的引用所做的唯一一件事就是添加自己。为此,他们不需要也不应该参考父母。添加孩子是父母的责任(如果您使用舞台,则由 Flash Player 负责)。
  • 也就是说,您可以为您的 Character 提供对类型为 IEventDispatcher 的父类的引用,并允许 Character 收听此频道。这个概念称为事件总线

请注意,这么多人做您正在做的事情的原因是 Adob​​e 未能记录如何在时间轴上正确使用 OOP。不幸的是,当我们中的一些人在 2009 年末/2010 年初开始记录时,损害已经造成,每个人都认为,如果你想编写好的代码,你必须假装时间线和阶段不存在。

我知道我已经涵盖了很多内容,并且可能我所说的大部分内容与您认为自己知道的内容直接矛盾,所以请不要犹豫,提出您可能有的任何问题。

于 2013-02-12T02:11:08.097 回答