2013-06-03

Actionscript3.0で状態遷移

状態遷移についてGoogle検索で調べたところ、 http://flash-scope.com/scene_change_with_function_call.html のソースコードが単純でわかりやすかった。

少し変更したのが以下。SceneではなくてPageと呼んでいるが、2つのページをクリックするたびに切り替える。(シーンというのは映画用語だと思うが、私は本派なのでページで)

package
{
    import flash.display.Sprite;
    import flash.events.Event;

    /**
     * ...
     * @author itouhiro
     */
    [SWF (backgroundColor="0xEEEEEE",frameRate="30",width="465",height="465")]
    public class Main extends Sprite {

        public function Main():void {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            sceneTop();
        }
        private function sceneTop():void {
            addChild(new Page(sceneRound1, 0x808080 + 0x808080 * Math.random() * 0.5));
        }
        private function sceneRound1():void {
            addChild(new Page2(sceneTop, 0x808080 * Math.random() * 0.5));
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;

    class Page extends Sprite {
        private var nextPage:Function;

        public function Page(f:Function, c:uint):void {
            nextPage = f;
            graphics.beginFill(c);
            //365 .. stage.stageWidth - 100。 stage.stageWidth だとerror
            graphics.drawRect(365 * Math.random(), 365 * Math.random(), 100, 100);
            graphics.endFill();
            addEventListener(MouseEvent.CLICK, onClick);
        }
        private function onClick(e:MouseEvent):void {
            removeEventListener(MouseEvent.CLICK, onClick);
            parent.removeChild(this);
            nextPage();
            nextPage = null;
        }
    }

    class Page2 extends Sprite {
        private var nextPage:Function;

        public function Page2(f:Function, c:uint):void {
            nextPage = f;
            graphics.beginFill(c);
            graphics.drawCircle(365 * Math.random(), 365 * Math.random(), 50);
            graphics.endFill();
            addEventListener(MouseEvent.CLICK, onClick);
        }

        private function onClick(e:MouseEvent):void {
            removeEventListener(MouseEvent.CLICK, onClick);
            parent.removeChild(this);
            nextPage();
            nextPage = null;
        }
    }

https://sites.google.com/site/itouhiro/2013/20130602funccall.swf

この原始的て単純なコードを、以下で磨いていく。

http://www.project-nya.jp/modules/weblog/details.php?blog_id=1333 ではSceneは interface IScene で共通methodを持たせている。

同じようにやってみたけど、上のソースにinterfaceつけても特に意味はなかった。

package
{
    import flash.display.Sprite;
    import flash.events.Event;

    /**
     * ...
     * @author itouhiro
     */
    [SWF (backgroundColor="0xEEEEEE",frameRate="30",width="465",height="465")]
    public class Main extends Sprite {
        public function Main():void {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            sceneTop();
        }
        private function sceneTop():void {
            addChild(new Page1(sceneRound1, 0x808080 + 0x808080 * Math.random() * 0.5));
        }
        private function sceneRound1():void {
            addChild(new Page2(sceneTop, 0x808080 * Math.random() * 0.5));
        }
    }
}

import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;

    interface IPage {
        function open():void;
        function close(e:MouseEvent):void;
    }
    class Page1 extends Sprite implements IPage {
        private var nextPage:Function;
        public function Page1(f:Function, c:uint):void {
            nextPage = f;
            graphics.beginFill(c);
            //365 .. stage.stageWidth - 100。 stage.stageWidth だとerror
            graphics.drawRect(365 * Math.random(), 365 * Math.random(), 100, 100);
            graphics.endFill();
            addEventListener(MouseEvent.CLICK, close);
        }
        public function open():void {
        }
        public function close(e:MouseEvent):void {
            removeEventListener(MouseEvent.CLICK, close);
            parent.removeChild(this);
            nextPage();
            nextPage = null;
        }
    }

    class Page2 extends Sprite implements IPage {
        private var nextPage:Function;
        public function Page2(f:Function, c:uint):void {
            nextPage = f;
            graphics.beginFill(c);
            graphics.drawCircle(365 * Math.random(), 365 * Math.random(), 50);
            graphics.endFill();
            addEventListener(MouseEvent.CLICK, close);
        }
        public function open():void {
        }
        public function close(e:MouseEvent):void {
            removeEventListener(MouseEvent.CLICK, close);
            parent.removeChild(this);
            nextPage();
            nextPage = null;
        }
    }

サンプル2

http://www.kuma-de.com/blog/2010-02-03/1561 のソースを読んでみた。上の流れを参考にすると読むことができた。

Main見るとScene.getNextScene()で次に向かっているんだな。 あと、個々のシーンからMainに戻るために、個々のシーンでFunction.call()するのではなく、個々のシーンでDispatchEventでEvent.COMPLETEを投げてMainに制御を戻している。

https://sites.google.com/site/itouhiro/2013/20130603scene.swf

ソース Main.as

package {
    import flash.display.Scene;
    import flash.display.Sprite;
    import flash.events.Event;

    /**
     * ...
     * @author itouhiro
     */
    [SWF (backgroundColor="0xEEEEEE",frameRate="30",width="465",height="465")]
    public class Main extends Sprite {
        private var scene:SceneBase;

        public function Main():void {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point

            scene = new SceneTop();
            addChild(scene);
            scene.start();
            scene.addEventListener(Event.COMPLETE, onComplete);
        }

        private function onComplete(e:Event):void {
            scene.removeEventListener(Event.COMPLETE, onComplete);
            var newScene:SceneBase  = scene.getNext();

            scene.stop();
            removeChild(scene);
            scene = null;

            scene = newScene;
            scene.init();
            addChild(scene);
            scene.start();
            scene.addEventListener(Event.COMPLETE, onComplete);
        }
    }
}

SceneBase.as (Sceneというクラス名は使えなかった)

package  {
    import flash.display.Sprite;
    import flash.events.Event;

    /**
     * ...
     * @author itouhiro
     */
    public class SceneBase extends Sprite {
        protected var nextScene:SceneBase;

        public function SceneBase() {
            super();
        }

        public function getNext():SceneBase {
            return nextScene;
        }
        public function init():void {
        }
        public function start():void {
        }
        public function stop():void {
        }
        public function close():void {
            dispatchEvent(new Event(Event.COMPLETE));
        }
    }
}

SceneTop.as

package  {
    import flash.display.CapsStyle;
    import flash.display.Graphics;
    import flash.display.JointStyle;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.text.StyleSheet;
    import flash.text.TextField;
    /**
     * ...
     * @author itouhiro
     */
    public class SceneTop extends SceneBase {

        public function SceneTop() {
            init();
        }
        override public function init():void {
            graphics.beginFill(0xCCCCCC);
            graphics.lineStyle(3, 0x666666);
            graphics.drawRoundRect(50, 50, 365, 365, 10, 10);
            graphics.endFill();

            var tf:TextField = new TextField();
            var css:StyleSheet = new StyleSheet();
            css.setStyle('p', { fontSize:'48px', fontFamily:'Verdana', fontWeight:'bold', color:'#FFFFFF' } );
            tf.styleSheet = css;
            tf.htmlText = '<p>Flash Quest</p>';
            tf.width = 465;
            tf.x = 70;
            tf.y = 180;
            addChild(tf);
        }
        override public function start():void {
            var btnStart:Sprite = new Sprite;
            var g:Graphics = btnStart.graphics;
            g.beginFill(16731648, 1);
            g.lineStyle(3, 0x000000, 0.8, true, "normal", CapsStyle.ROUND, JointStyle.ROUND, 1);
            g.drawRoundRect(0, 0, 83, 37, 30, 30);
            g.endFill();
            btnStart.x = 100;
            btnStart.y = 350;
            addChild(btnStart);
            btnStart.addEventListener(MouseEvent.CLICK, onClickStart);
        }
        private function onClickStart(e:MouseEvent):void {
            nextScene = new SceneGame();
            close();
        }
        override public function stop():void {
        }
    }
}

SceneGame.as

package  {
    import flash.display.CapsStyle;
    import flash.display.Graphics;
    import flash.display.JointStyle;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.text.StyleSheet;
    import flash.text.TextField;
    /**
     * ...
     * @author itouhiro
     */
    public class SceneGame extends SceneBase {

        public function SceneGame() {
            init();
        }
        override public function init():void {
            graphics.beginFill(0x996666);
            graphics.lineStyle(3, 0xCC3333);
            graphics.drawRoundRect(40, 80, 385, 305, 10, 10);
            graphics.endFill();

            var tf:TextField = new TextField();
            var css:StyleSheet = new StyleSheet();
            css.setStyle('p', { fontSize:'48px', fontFamily:'Verdana', fontWeight:'bold', color:'#FFFFFF' } );
            tf.styleSheet = css;
            tf.htmlText = '<p>PlayGame</p>';
            tf.width = 465;
            tf.x = 70;
            tf.y = 180;
            addChild(tf);
        }
        override public function start():void {
            var btnStart:Sprite = new Sprite;
            var g:Graphics = btnStart.graphics;
            g.beginFill(0x00CC00, 1);
            g.lineStyle(3, 0x000000, 0.8, true, "normal", CapsStyle.ROUND, JointStyle.ROUND, 1);
            g.drawRoundRect(0, 0, 83, 37, 30, 30);
            g.endFill();
            btnStart.x = 280;
            btnStart.y = 300;
            addChild(btnStart);
            btnStart.addEventListener(MouseEvent.CLICK, onClickStart);
        }
        private function onClickStart(e:MouseEvent):void {
            nextScene = new SceneGameOver();
            close();
        }
        override public function stop():void {
        }
    }
}

SceneGameOver.as

package  {
    import flash.display.CapsStyle;
    import flash.display.Graphics;
    import flash.display.JointStyle;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.text.StyleSheet;
    import flash.text.TextField;
    /**
     * ...
     * @author itouhiro
     */
    public class SceneGameOver extends SceneBase {

        public function SceneGameOver() {
            init();
        }
        override public function init():void {
            graphics.beginFill(0x000000);
            graphics.drawRect(0, 120, 465, 225);
            graphics.endFill();

            var tf:TextField = new TextField();
            var css:StyleSheet = new StyleSheet();
            css.setStyle('p', { fontSize:'48px', fontFamily:'Verdana', fontWeight:'bold', color:'#FFFFFF' } );
            tf.styleSheet = css;
            tf.htmlText = '<p>GameOver</p>';
            tf.width = 465;
            tf.x = 70;
            tf.y = 180;
            addChild(tf);
        }
        override public function start():void {
            var btnStart:Sprite = new Sprite;
            var g:Graphics = btnStart.graphics;
            g.beginFill(0xEEEE00, 1);
            g.lineStyle(3, 0x999900, 0.8, true, "normal", CapsStyle.ROUND, JointStyle.ROUND, 1);
            g.drawRoundRect(0, 0, 83, 37, 30, 30);
            g.endFill();
            btnStart.x = 200;
            btnStart.y = 270;
            addChild(btnStart);
            btnStart.addEventListener(MouseEvent.CLICK, onClickStart);
        }
        private function onClickStart(e:MouseEvent):void {
            nextScene = new SceneTop();
            close();
        }
        override public function stop():void {
        }
    }
}

0 件のコメント:

コメントを投稿

人気記事