0

as3の学習を支援しようとしている小さなプロジェクトがあります。これは、本 Foundation Game Design with Actionscript 3.0 からのバリエーションです。ドキュメントクラスを持つためだけにflaを使用しています。すべてのアートは as ファイル内にロードされます。この本では、彼はすべてのコードをドキュメント クラスに配置しただけで、私もそれに沿って進めたところ、期待どおりに機能しました。OOP を処理するために、コードを個別のクラスに分割しようとしています。1 つのクラスは背景 (Background.as) を作成し、1 つのクラスはキャラクター (Character.as) を作成し、もう 1 つのクラスはボタン (GameButton.as) を 6 つの異なるボタンに対して 6 回インスタンス化します。そしてもちろん、ドキュメント クラスである GameWorld.as があります。すべてがロードされ、期待どおりに表示されます。しかし、ボタンに eventListener を追加しようとすると、応答がありません。eventListener を GameButton に入れてみました。どちらも機能していません。また、さまざまなクラスをインスタンス化するときに、ステージへの参照を渡します。サイトを検索したところ、似たようなものが見つかりましたが、役に立たなかったようです。アドバイスをいただきありがとうございます。コードは次のとおりです。

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;
        }

    }

}
4

1 に答える 1

0

すべてのアートはファイルとしてロードされます。

これは私がお勧めするアプローチではありません。神が私たちにFlashIDEを与えてくれたのには理由があります-そしてそれはコードを書くことではありません!実行時にビジュアルを変更する実際の要件がない限り、コードのレイアウトとビデオに費やしているときはいつでも無駄になります。パスがすべてハードコーディングされているという事実は、その要件がないことを示しています。

それでは、一歩下がって、フラッシュボタンとして作成した6つのシンボルを含むシンボルがあると想像してみましょう(シンボルタイプとしてボタンを選択した場合)。これらはSimpleButtonsになりますが、以下のクラスでは、DisplayObjectとして入力するだけです。クラスはそれらが何であるかを気にしませんが、Simplebuttonを使用すると、コードを必要としないアップ、オーバー、ダウン、およびヒット状態が得られます。

以下は、「ステージインスタンスを自動的に宣言する」ことを前提としていることに注意してください。これは、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()
  • クラスにはすでに名前に文字が含まれているので、実際にはこれらはandである必要がありますpos()move()ただし、短縮する必要はありませんposition())。
  • 子クラスが親への参照を使用して実行しているのは、自分自身を追加することだけです。彼らはこの目的のために親への参照を必要とせず、また持つべきではありません。子を追加するのは親の責任です(または、ステージを使用する場合はFlash Playerの責任です)。
  • そうは言っても、IEventDispatcherとして入力された親クラスへの参照をキャラクターに与えて、キャラクターがこのチャネルをリッスンできるようにすることができます。この概念はイベントバスと呼ばれます。

非常に多くの人があなたがしていることをしている理由は、アドビがタイムラインでOOPを適切に使用する方法を文書化できなかったためです。残念ながら、私たちの何人か2009年の終わりから2010年の初めにかけて、被害が発生し、優れたコードを書きたい場合はタイムラインとステージが存在しないふりをしなければならないと誰もが思っていました。

私は多くのことをカバーしたことを知っています、そしておそらく私が言ったことのほとんどはあなたが知っていると思っていたものと直接矛盾しているので、あなたが持っているかもしれない質問をすることを躊躇しないでください。

于 2013-02-12T02:11:08.097 に答える