2012-11-05

ActionScript3.0でキーボード入力を検知する(初歩)

[話者] キーボードイベントだが、stageに対してaddEventListener(KeyboardEvent)すれば取得できる。

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObjectContainer.html#addChild() によると、「stageに直接addChild()するな。セキュリティ的に考えて」と書いてあるが、keyboardはいいのかな‥‥。

実際のFlash。このFlashを一度クリックしたらキーボード取得できる。Flashの外を一度クリックすると、取得できなくなるのだな。

https://sites.google.com/site/itouhiro/2012/20121104keyboardEvent.swf

FlashDevelopのOutputペイン(ウィンドウの下部)みると、trace(e)で、キーボードイベントにいろいろプロパティがあることがわかる。 Flash画面には、そのうちの3プロパティを表示している。

ソースコードは2つに分かれている。

Main.as

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.text.TextField;
    
    /**
     * ...
     * @author itouhiro
     */
    [SWF(backgroundColor="0xf8f8f8", width="320",height="240", frameRate="15")]
    public class Main extends Sprite 
    {
        private var logger:Logger;
        
        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
            var tfd:TextField = new TextField();
            tfd.text = "Type Any Key";
            addChild(tfd);
            
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            
            logger = new Logger();
            logger.x = 10; logger.y = 0;
            addChild(logger);
        }
        
        private function keyDownHandler(e:KeyboardEvent):void 
        {
            trace(e);
            logger.log('keyCode='+e.keyCode.toString() + ' shiftKey='+e.shiftKey.toString() + ' ctrlKey='+e.ctrlKey.toString()  );
        }
    }
}

[合いの手] 確かに stage.addEventListenerってやってるね。

ShiftキーやCtrlキーとの同時押ししたかどうか、プロパティみればわかるのか。

[話者] Loggerクラスは前回と同じ。

Logger.as

package  
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    
    /**
     * ...
     * @author itouhiro
     */
    public class Logger extends Sprite 
    {
        private var lines:Array;
        private var tfd:TextField;
        
        public function Logger(str:String = '') 
        {
            var format:TextFormat = new TextFormat();
            format.font = "Courier New";
            format.size = 12;
            format.color = 0x999999;
            
            tfd = new TextField();
            tfd.defaultTextFormat = format;
            tfd.text = str;
            tfd.autoSize = TextFieldAutoSize.LEFT;
            addChild(tfd);
            
            lines = new Array();            
        }
        public function log(str:String):void
        {
            lines.push(new Date().time.toString().substr(-5) + ' ' + str);
            if (lines.length >= 15)
            {
                lines.shift();
            }
            tfd.text = lines.join('\n');
        }
    }
}

[合いの手] ふむふむ。

これで何ができるんだろ?

[話者] かな入力フラッシュを作ってみよう。

キーコードと、入力される文字の対応を、作ったばかりのFlashを使って調べるぞ。

[合いの手] 実際にキーを一個ずつ押してメモってるのか。

[話者] Flashはこちら。

このFlashを一度クリックしたらキーボード取得できる。NTTと入力すると、「みかか」と表示されるだろう。systemと入力すると「とんとかいも」になるよね

https://sites.google.com/site/itouhiro/2012/20121104keyboardEvent2.swf

ソースは2つなのだが、Loggerクラスは上記のとまったく同じなので省略して、Mainクラスのみ掲載するよ。

Main.as

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.text.TextField;
    
    /**
     * ...
     * @author itouhiro
     */
    [SWF(backgroundColor="0xf8f8f8", width="320",height="240", frameRate="15")]
    public class Main extends Sprite 
    {
        private var logger:Logger;
        private var kanaMap:Object = new Object();
        
        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
            var keys:String;

            keys  = '49 50 51 52 53 54 55 56 57 48 189 222 220 ';
            keys += '81 87 69 82 84 89 85 73 79 80 192 219 ';
            keys += '65 83 68 70 71 72 74 75 76 187 186 221 ';
            keys += '90 88 67 86 66 78 77 188 190 191 226';
            var keyCodes:Array = keys.split(' ');

            keys  = 'ぬ ふ あ う え お や ゆ よ わ ほ へ ー ';
            keys += 'た て い す か ん な に ら せ ゛ ゜ ';
            keys += 'ち と し は き く ま の り れ け む ';
            keys += 'つ さ そ ひ こ み も ね る め ろ';
            var kanaList:Array = keys.split(' ');

            keys  = 'ぬ ふ ぁ ぅ ぇ ぉ ゃ ゅ ょ を ほ ゑ ー ';
            keys += 'た て ぃ す ヵ ん な に ら せ ゛ 「 ';
            keys += 'ち と し ゎ き く ま の り れ ヶ 」 ';
            keys += 'っ さ そ ゐ こ み も 、 。 ・ ろ';
            var kanaList_shift:Array = keys.split(' ');

            for (var i:int = 0; i < keyCodes.length; i++)
            {
                kanaMap[int(keyCodes[i])] = new Array(kanaList[i], kanaList_shift[i]);
            }
            
            var tfd:TextField = new TextField();
            tfd.text = "かな入力Flash";
            addChild(tfd);
            
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            
            logger = new Logger();
            logger.x = 10; logger.y = 0;
            addChild(logger);
        }
            
        private function keyDownHandler(e:KeyboardEvent):void 
        {
            var kana:String;
            if (e.shiftKey)
            {
                kana = kanaMap[e.keyCode][1];
            } else {
                kana = kanaMap[e.keyCode][0];
            }
            logger.log('keyCode='+e.keyCode.toString() + ' かな='+kana);
        }
    }
}

[合いの手] private var kanaMap:Object = new Object() は何だろう?

[話者] 連想配列なのだが‥‥これはキーが数字だからArrayでもよかったのか‥‥

[合いの手] ん?

[話者] 「配列」の添え字が数字と決まっているんだが、「連想配列」の場合、添え字(キー)は文字列も使っていいんだ。 まあ、ここらへんはJavaScriptと同じだね。参考: http://d.hatena.ne.jp/amachang/20070202/1170386546

            //配列を生成、値を格納
            var arr:Array = new Array('foo', 'bar');

            var b:Array = ['buz', 'qux'];
            
            var c:Array = [];
            c[2] = 'quux';
            
            //配列を取り出す
            for (var i:int = 0; i < arr.length; i++)
            {
                trace('index=' + i + ', value=' + arr[i]);
            }

            //連想配列を生成、値を格納
            var hash:Object = new Object();
            hash['apple'] = 'pie';
            hash['orange'] = 'juice';
            
            var hh:Object = { 'grape':'juice', 'strawberry':'cake' }; 
            
            for (var key:String in hash)
            {
                trace('key='+ key + ', value=' + hash[key]);
            }

[合いの手] キー入力でなにか操作できるFlashもほしいな

[話者] ソースコード1つで。

実際のFlashはこちら。一度Flashをマウスクリックすると操作可能になる。カーソルキー上下左右で動くぞ。Shiftキーも押すと速度が3倍になる。

https://sites.google.com/site/itouhiro/2012/20121105keyboardEvent3.swf

ソースはこれ。

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;
    
    /**
     * ...
     * @author itouhiro
     */
    [SWF(backgroundColor="0xf8f8f8", width="320",height="240", frameRate="30")]
    public class Main extends Sprite 
    {
        private var circle: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
            circle = new Sprite();
            circle.graphics.beginFill(0xFFCC00);
            circle.graphics.drawCircle(0, 0, 40);
            addChild(circle);
            
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
        }
        
        private function keyDownHandler(e:KeyboardEvent):void 
        {
            var key:uint = e.keyCode;
            var delta:int = 5;
            if (e.shiftKey)
            {
                delta *= 3;
            }
            
            if (key == Keyboard.UP)
            {
                circle.y -= delta;
            } else if (key == Keyboard.DOWN)
            {
                circle.y += delta;
            } else if (key == Keyboard.RIGHT)
            {
                circle.x += delta;
            } else if (key == Keyboard.LEFT)
            {
                circle.x -= delta;
            }
        }
    }
}

[合いの手] ナナメに動けない‥‥ Shiftキーの同時押しは対応してるけど、↑と→の同時押しは対応してないようだね。どうにかならない?

[話者] それは KEY_DOWNだけじゃなくて、KEY_UPも監視することで解決する。KEY_DOWNを一度検出したら、KEY_UPが検出されるまではDOWNのままだと解釈すればいいんだ。

実際のFlashはこちら。一度Flashをマウスクリックすると操作可能になる。カーソルキーで上下左右ナナメに動くぞ。Shiftキー押しても速度アップしなくなった。

https://sites.google.com/site/itouhiro/2012/20121105keyboardEvent4.swf

ソースはこれ。

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;
    
    /**
     * ...
     * @author itouhiro
     */
    [SWF(backgroundColor="0xf8f8f8", width="320",height="240", frameRate="30")]
    public class Main extends Sprite 
    {
        private var circle:Sprite;
        private var cursor:Array;
        
        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
            circle = new Sprite();
            circle.graphics.beginFill(0xCCFF00);
            circle.graphics.drawCircle(0, 0, 40);
            addChild(circle);
            
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
            
            cursor = [];
            cursor[Keyboard.UP] = 0;
            cursor[Keyboard.DOWN] = 0;
            cursor[Keyboard.RIGHT] = 0;
            cursor[Keyboard.LEFT] = 0;
        }
        
        private function keyUpHandler(e:KeyboardEvent):void 
        {
            cursor[e.keyCode] = 0;
        }
        
        private function keyDownHandler(e:KeyboardEvent):void 
        {
            switch (e.keyCode) {
                case Keyboard.UP :
                case Keyboard.DOWN :
                case Keyboard.RIGHT :
                case Keyboard.LEFT :
                    cursor[e.keyCode] = 5;
                    break;
                default :
                    break;
            }
            circle.y -= cursor[Keyboard.UP];
            circle.y += cursor[Keyboard.DOWN];
            circle.x += cursor[Keyboard.RIGHT];
            circle.x -= cursor[Keyboard.LEFT];
        }
    }
}

[合いの手] ナナメに動けたよ。ウェーイ

0 件のコメント:

コメントを投稿

人気記事