forked from: GYAOS_sample

by cloud10design.fl forked from GYAOS_sample (diff: 1170)
Copyright hacker_9vjnvtdz ( http://wonderfl.net/user/hacker_9vjnvtdz )
MIT License ( http://www.opensource.org/licenses/mit-license.php )
Downloaded from: http://wonderfl.net/c/f6f2

最初の入力フォームにTwitterのアカウントを入力してください。
♥1 | Line 839 | Modified 2011-01-31 22:21:24 | MIT License | (replaced)
play

ActionScript3 source code

/**
 * Copyright cloud10design.fl ( http://wonderfl.net/user/cloud10design.fl )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/hKoD
 */

// forked from hacker_9vjnvtdz's GYAOS_sample
/**
 * Copyright hacker_9vjnvtdz ( http://wonderfl.net/user/hacker_9vjnvtdz )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/f6f2
 *
 * 最初の入力フォームにTwitterのアカウントを入力してください。
 * 
 * 
 * 
 * 
 *
 */
 
package{
    import flash.text.TextField;
    import flash.display.Sprite;
    import flash.system.IME;
    import flash.system.IMEConversionMode;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;
    import fl.transitions.Tween;
    import fl.transitions.easing.*;
    import flash.text.TextFieldType;
    import flash.text.TextFormat;
    
    [SWF(width="465", height="465", frameRate="30", backgroundColor="#FFFFFF")]
    
    public class DocumentClass extends Sprite {
        
        //----------------------------------------------------------------------
        //
        // プロパティ
        //
        //----------------------------------------------------------------------
        
        /**
         * プレイヤー
         */
        public var player:Character;
        
        /**
         * モンスター
         */
        public var monster:Enemy;
        
        /**
         * 原文ツイートリスト
         */
        public var tweets:Array = [];
        
        /**
         * アルファベット化ツイートリスト
         */
        public var convertedTweet:String;

        /**
         * 呪文に使用できる文字情報
         */
        public var spellableChars:SpellableChars;

        /**
         * ツイッターアカウント
         */
        public var twitterUser:String;

        /**
         * 画像ローディング用カウンター
         */
        public var imagesCounter:uint = 0;

        //----------------------------------------------------------------------
        //
        // プロパティ(表示オブジェクト)
        //
        //----------------------------------------------------------------------

        /**
         * 呪文入力フィールド
         */
        public var spellField:SpellField = new SpellField();
        public var spellFieldImage:Image = new Image('http://cloud10.jp/wonderfl/gyaos/spellfield.png');
        
        /**
         * HP表示フィールド
         */
        public var viewHp:TextField = new TextField();
        
        /**
         * ダメージ表示フィールド
         */
        public var viewDamage:TextField = new TextField();
        
        /**
         * 使用中のツイート表示フィールド
         */
        public var viewTweet:TextField   = new TextField();
        
        /**
         * タイプライター
         */
        public var typewriter:Typewriter = new Typewriter();
        
        public var accountField:TextField = new TextField();
        
        
        //----------------------------------------------------------------------
        //
        // コンストラクタ
        //
        //----------------------------------------------------------------------

        public function DocumentClass():void{
            
            // IMEモードを半角英数に強制
            IME.conversionMode = IMEConversionMode.ALPHANUMERIC_HALF;
            
            // プレイヤーの設定
            player = new Character('url', 'こっち', 100);
            player.magic = 2;
            
            // モンスターの設定
            monster = new Enemy('http://assets.wonderfl.net/images/related_images/9/9a/9a67/9a674310835d956620db269594b14241d8c079ba', 'あっち', 200 );
            monster.magicDef = 1;
            monster.agility  = 50;
            
            accountField.border = true;
            accountField.width = 200;
            accountField.height = 40;
            accountField.x = 132;
            accountField.y = 200;
            accountField.type = TextFieldType.INPUT;
            accountField.addEventListener( KeyboardEvent.KEY_DOWN, setAccount );
            
            stage.addChild( accountField );
        
        }
        
        //----------------------------------------------------------------------
        //
        // メソッド
        //
        //----------------------------------------------------------------------

        public function setAccount( e:KeyboardEvent ):void{
            if( e.keyCode == Keyboard.ENTER ){
                twitterUser = accountField.text;
                stage.removeChild( accountField );
                
                // 画像の読み込み完了するとloadedImagesを呼び出す
                typewriter.complete =
                monster.complete =
                spellFieldImage.complete = loadedImages;
    
                // 画像をロード
                typewriter.load();
                monster.load();
                spellFieldImage.load();
            }
        }

        /**
         * 画像の読み込みが完了すると呼び出されるメソッド
         */
        public function loadedImages():void{
            imagesCounter++;
            if( imagesCounter == 3 ){
                // ステージに追加
                //stage.addChild( viewHp );
                //stage.addChild( viewTweet );
                stage.addChild( typewriter );
                stage.addChild( monster );
                stage.addChild( spellFieldImage );
                stage.addChild( spellField );
                stage.addChild( viewDamage );
                
                // スタイリング ※いずれはクラス内でスタイリング予定
                viewTweet.width = 464;
                viewTweet.wordWrap = true;
                viewDamage.defaultTextFormat = new TextFormat( null, 50, 0xFF0000, true, true, null, null, null, "right" );
                
                // 配置
                viewHp.y = 200;
                viewDamage.x = 100;
                viewDamage.y = 200;
                viewTweet.y = 260;
                
                spellField.width = 281;
                spellField.height = 39;
                spellField.x = 91;
                spellField.y = 275;
                spellFieldImage.x = 81;
                spellFieldImage.y = 260;
                typewriter.y = 323;
                
                monster.y = -20;
                monster.x = ( stage.stageWidth - monster.width ) / 2;
                
                // 初期表示設定
                viewHp.text = monster.hp + '/' + monster.maxHp;
                
                // TwitterユーザタイムラインAPI XML形式のURL
                var url:String = 'http://search.twitter.com/search.atom?q=';
                
                // TwitterAPIのXMLのロード
                // 読み込み完了するとloadedTwitterをコール
                var xmlLoader:GetXML = new GetXML( url + twitterUser );
                xmlLoader.complete = loadedTwitter;
                xmlLoader.load();
            }
        }
        
        /**
         * TwitterのXMLの読み込みが完了すると呼び出されるメソッド
         */
        public function loadedTwitter( xml:XML ):void{
            default xml namespace = new Namespace("http://www.w3.org/2005/Atom");
            // 配列tweetsにTwitterタイムラインのツイートを格納
            var entries:XMLList = xml.entry;
            for( var i:uint = 0; i < entries.length(); i++ ){
                if( entries[i].author.name.toString().match( new RegExp( '^' + twitterUser + ' ' ) ) ){
                    tweets.push( entries[i].title );
                }
            }
            
            // ゲーム開始
            // スタンバイ状態にする
            onStandby();
        }
        
        /**
         * スタンバイ状態で呼び出されるメソッド
         */
        public function onStandby():void{
            
            
            
            /* !---! 加筆中 !---! */
            player.startBattle();
            monster.startBattle();
            
            
            // 呪文動作を選択した際の処理
            onSpellAction();
            bindTypeListener();
        }
        
        /**
         * タイプライターのキーボードイベントを結びつける
         */
        public function bindTypeListener():void{
            stage.addEventListener( KeyboardEvent.KEY_DOWN, spellTypeDown );
            stage.addEventListener( KeyboardEvent.KEY_UP,   spellTypeUp );
        }
        
        /**
         * タイプライターのキーボードイベントを切り離す
         */
        public function unbindTypeListener():void{
            stage.removeEventListener( KeyboardEvent.KEY_DOWN, spellTypeDown );
            stage.removeEventListener( KeyboardEvent.KEY_UP,   spellTypeUp );
        }

        /**
         * 呪文動作を選択した際の処理
         */
        public function onSpellAction():void{
            
            // アルファベット化したツイートリストからツイートをひとつ抜き出す
            var tweet:String = convertTweet( tweets.shift() );
            
            // 抜き出したツイートを表示
            viewTweet.text = tweet;

            // 呪文に使用できる文字をツイートから取得し管理するインスタンス
            spellableChars = new SpellableChars( tweet );
            
            // タイプライターに使用できる文字を表示
            typewriter.display( spellableChars );
            
            // 呪文入力フィールドに入力できる文字を制限
            spellField.restrict = spellableChars.getRestrictChars();
        }
        
        /**
         * 呪文入力フィールドにキー入力をした祭に呼び出される
         */
        public function spellTypeDown( e:KeyboardEvent ):void{
            if( e.keyCode == Keyboard.BACKSPACE ){
                if( spellField.text !== '' ){
                    var lastChar:String = spellField.text.split('').reverse()[0];
                    spellableChars[ lastChar ]++;
                    spellField.text = spellField.text.replace( /.$/, '');
                }
            }else if( ExMath.inRange( e.keyCode, Keyboard.A, Keyboard.Z ) ){
                
                var typedChar:String = typewriter.codeToChar( e.keyCode );
            
                // 文字の残りを管理するインスタンス(spellableCharsのコピー)
                //var remainder:SpellableChars = spellableChars.clone();
                if(spellableChars[ typedChar ]>0){
                    spellableChars[ typedChar ]--;
                    
                    spellField.appendText( typedChar );
                    
                    // 残文字をタイプライタに表示
                    
                }
            }else if( e.keyCode == Keyboard.SPACE ){
                if( !onSpace ){
                    if( !slideToTypewriter || !slideToTypewriter.isPlaying ){
                        slideToSpellList = new Tween( typewriter, 'x', None.easeIn, 0, -465, .5, true );
                    }
                }
                onSpace = true;
            }
            typewriter.display( spellableChars );
        }
        
        public var slideToSpellList:Tween;
        public var slideToTypewriter:Tween;
        public var onSpace:Boolean = false;
        
        
        /**
         * 呪文入力フィールドにキー入力をした祭に呼び出される
         */
        public function spellTypeUp( e:KeyboardEvent ):void{
            if( e.keyCode == Keyboard.ENTER ){
                var damage:int = player.spell( spellField.text, monster );
                if( damage > 0 ){
                    viewDamage.text = damage.toString();
                    monster.hp -= damage;
                    viewHp.text = monster.hp + '/' + monster.maxHp;
                }else{
                    viewDamage.text = 'ミス';
                }
                spellField.text = '';
                
                if( !monster.hp ){
                    stage.removeChild( monster );
                    unbindTypeListener();
                    trace('GAME OVER');
                }else{
                    onSpellAction();
                }
            }else if( e.keyCode == Keyboard.SPACE ){
                if( onSpace ){
                    if( !slideToSpellList.isPlaying ){
                        slideToTypewriter = new Tween( typewriter, 'x', None.easeIn, -465, 0, .5, true );
                    }else{
                        slideToSpellList.continueTo( 0, slideToSpellList.duration - slideToSpellList.time );
                    }
                    
                }
                onSpace = false;
            }
        }
        
        public function convertTweet( tweet:String ):String{
            var format:Object = {
                     'ア|ァ' : 'a'
                    ,'イ|ィ' : 'i'
                    ,'ウ|ゥ' : 'u'
                    ,'エ|ェ' : 'e'
                    ,'オ|ォ' : 'o'
                    
                    ,'カ|ヵ' : 'ka'
                    ,'キ' : 'ki'
                    ,'ク' : 'ku'
                    ,'ケ|ヶ' : 'ke'
                    ,'コ' : 'ko'
                    
                    ,'サ' : 'sa'
                    ,'シ' : 'shi'
                    ,'ス' : 'su'
                    ,'セ' : 'se'
                    ,'ソ' : 'so'
                    
                    ,'タ' : 'ta'
                    ,'チ' : 'chi'
                    ,'ツ' : 'tu'
                    ,'テ' : 'te'
                    ,'ト' : 'to'
                    
                    ,'ナ' : 'na'
                    ,'ニ' : 'ni'
                    ,'ヌ' : 'nu'
                    ,'ネ' : 'ne'
                    ,'ノ' : 'no'

                    ,'ハ' : 'ha'
                    ,'ヒ' : 'hi'
                    ,'フ' : 'fu'
                    ,'ヘ' : 'he'
                    ,'ホ' : 'ho'

                    ,'マ' : 'ma'
                    ,'ミ' : 'mi'
                    ,'ム' : 'mu'
                    ,'メ' : 'me'
                    ,'モ' : 'mo'

                    ,'ヤ|ャ' : 'ya'
                    ,'ユ|ュ' : 'yu'
                    ,'ヨ|ョ' : 'yo'
                    
                    ,'ラ' : 'ra'
                    ,'リ' : 'ri'
                    ,'ル' : 'ru'
                    ,'レ' : 're'
                    ,'ロ' : 'ro'

                    ,'ワ' : 'wa'
                    ,'ヰ' : 'wi'
                    ,'ヱ' : 'we'
                    ,'ヲ' : 'wo'
                    
                    ,'ン' : 'n'
                    
                    ,'ガ' : 'ga'
                    ,'ギ' : 'gi'
                    ,'グ' : 'gu'
                    ,'ゲ' : 'ge'
                    ,'ゴ' : 'go'
                    
                    ,'ザ' : 'za'
                    ,'ジ' : 'zi'
                    ,'ズ' : 'zu'
                    ,'ゼ' : 'ze'
                    ,'ゾ' : 'zo'
                    
                    ,'ダ' : 'da'
                    ,'ヂ' : 'zi'
                    ,'ヅ' : 'zu'
                    ,'デ' : 'de'
                    ,'ド' : 'do'
                    
                    ,'バ' : 'ba'
                    ,'ビ' : 'bi'
                    ,'ブ' : 'bu'
                    ,'ベ' : 'be'
                    ,'ボ' : 'bo'

                    ,'パ' : 'pa'
                    ,'ピ' : 'pi'
                    ,'プ' : 'pu'
                    ,'ペ' : 'pe'
                    ,'ポ' : 'po'

                    ,'ヷ' : 'va'
                    ,'ヸ' : 'vi'
                    ,'ヴ' : 'vu'
                    ,'ヹ' : 've'
                    ,'ヺ' : 'vo'
                };
            tweet = ExString.convert( tweet, ExStringConvert.HIRAGANA_TO_KATAKANA )
            for( var pattern:String in format ){
                var ereg:RegExp = new RegExp( pattern, 'g' );
                tweet = tweet.replace( ereg, format[ pattern ] );
            }
            tweet = tweet.toLowerCase();
            tweet = tweet.replace(/[^a-z!]/g, '');
            return tweet;
        }
    }
}

import flash.display.Sprite;
import flash.display.MovieClip;
import flash.text.*;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
import flash.system.IME;
import flash.system.IMEConversionMode;
import flash.display.Loader;
import flash.system.LoaderContext;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.geom.ColorTransform;

class Image extends MovieClip{
    public var complete:Function;
    public var image:Loader = new Loader;
    public var url:URLRequest;
    
    public function Image( url:String ):void{
        this.url = new URLRequest( url );
    }
    
    public function load():void{
        var context:LoaderContext = new LoaderContext( true );
        image.load( url, context );
        image.contentLoaderInfo.addEventListener( Event.COMPLETE, _complete );
    }
    
    protected function _complete( e:Event ):void{
        addChild( image );
        if( Boolean(complete) ) complete();
    }
}

/* Character Class *
 * ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== */
class Character extends Image{
    
    // ID Number
    public var id:uint = 0;
    
    // MAX HP
    private var _maxHp:uint = 1;
    public function get maxHp():uint{
        return _maxHp;
    }
    public function set maxHp( value:uint ):void{
        var max:uint = 9999;
        _maxHp = value > max ? max : value;
    }

    // HP
    private var _hp:uint = 1;
    public function get hp():int{
        return _hp;
    }
    public function set hp( value:int ):void{
        var max:int = _maxHp;
        var hp:int   = value > max ? max : value;
        _hp = hp > 0 ? hp : 0;
    }

    // 魔力
    private var _magic:int = 1;
    public function get magic():int{
        return _magic;
    }
    public function set magic( value:int ):void{
        var max:int = 255;
        var magic:int = value > max ? max : value;
        _magic = magic > 0 ? magic : 0;
    }

    // 魔法防御力
    private var _magicDef:int = 1;
    public function get magicDef():int{
        return _magicDef;
    }
    public function set magicDef( value:int ):void{
        var max:int = 255;
        var magicDef:int = value > max ? max : value;
        _magicDef = magicDef > 0 ? magicDef : 0;
    }
    
    // すばやさ
    private var _agility:int = 1;
    public function get agility():int{
        return _agility;
    }
    public function set agility( value:int ):void{
        var max:uint = 255;
        var agility:int = value > max ? max : value;
        _agility = agility > 0 ? agility : 0;
    }
    
    // 魔法
    public var spells:Array = [];
    
    // コンストラクタ
    public function Character( imageURL:String, name:String, hp:uint = 1 ):void{
        super( imageURL );
        this.name = name;
        _maxHp   = hp;
        fullCare();
        spells['ice']       = new Spell( this, 2, '氷' );
        spells['fire']      = new Spell( this, 4, '炎' );
        spells['thunder']   = new Spell( this, 6, '雷' );
        spells['explosion'] = new Spell( this, 8, '爆発' );
    }
    
    // スペルを唱える
    public function spell( spell:String, target:Character ):int{
        if( spells[ spell ] ){
            return spells[ spell ].spell( target, spell, 1 );
        }
        return -1;
    }
    
    // 全回復させる
    public function fullCare():void{
        _hp = _maxHp;
    }
    
    // 戦闘開始
    public function startBattle():void{
        nextTurn();
    }
    
    public var turnWaitTimer:Timer;
    
    // 次のターンまでの延滞
    public function nextTurn():void{
        var turnWait:Number = ( 256 - agility ) / 25.6 * 1000;
        turnWaitTimer = new Timer( turnWait );
        turnWaitTimer.addEventListener( TimerEvent.TIMER, _onStandby );
        turnWaitTimer.start();        
    }
    
    // スタンバイ状態
    protected function _onStandby( e:TimerEvent ):void{
        turnWaitTimer.stop();
    }
}

class Enemy extends Character{
    public var damageFilter:Sprite = new Sprite();
    public var actionTimer:Timer;
    public function Enemy( imageURL:String, name:String, hp:uint = 1 ):void{
        super( imageURL, name, hp );
        addEventListener( Event.ADDED_TO_STAGE, _addedToStage );
        addEventListener( Event.REMOVED_FROM_STAGE, _removedFromStage );
    }
    protected override function _onStandby( e:TimerEvent ):void{
        super._onStandby( e );
        doAction();
    }
    public function doAction():void{
        actionTimer = new Timer( 1000 / 30 , 12 );
        _attack();
    }
    
    private function _attack():void{
        actionTimer.addEventListener( TimerEvent.TIMER, _attackMotion );
        actionTimer.start();
    }
    
    private function _attackMotion( e:TimerEvent ):void{
        var f:uint = e.target.currentCount;
        var redFilter:ColorTransform = new ColorTransform( 2, 0, 0, 1, 255, -100, -100, 0 );
        var defaultColor:ColorTransform = new ColorTransform( 0, 0, 0, 1, 0, 0, 0, 0 );
        var span:Number = 20;
        switch( f ){
            case 1:
            case 2:
            case 3:
                width  += span;
                height += span;
                x      -= span/2;
                y      -= span/2;
            break;
            case 4:
            case 6:
                damageFilter.visible = true;
            break;
            case 5:
            case 7:
                damageFilter.visible = false;
            break;
            case 8:
            case 9:
            case 10:
                width  -= span;
                height -= span;
                x      += span/2;
                y      += span/2;
            break;
            case 11:
                actionTimer.removeEventListener( TimerEvent.TIMER, _attackMotion );
                nextTurn();
        }
    }
    
    private function _addedToStage( e:Event ):void{
        stage.addChild( damageFilter );
        damageFilter.visible = false;
        damageFilter.graphics.beginFill( 0xFF0000, .8 );
        damageFilter.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
    }
    
    private function _removedFromStage( e:Event ):void{
        turnWaitTimer.stop();
        if( actionTimer ) actionTimer.stop();
        stage.removeChild( damageFilter );
    }
}

class Typewriter extends Image{
    public var keyA:SpellableCharCounter = new SpellableCharCounter();
    public var keyB:SpellableCharCounter = new SpellableCharCounter();
    public var keyC:SpellableCharCounter = new SpellableCharCounter();
    public var keyD:SpellableCharCounter = new SpellableCharCounter();
    public var keyE:SpellableCharCounter = new SpellableCharCounter();
    public var keyF:SpellableCharCounter = new SpellableCharCounter();
    public var keyG:SpellableCharCounter = new SpellableCharCounter();
    public var keyH:SpellableCharCounter = new SpellableCharCounter();
    public var keyI:SpellableCharCounter = new SpellableCharCounter();
    public var keyJ:SpellableCharCounter = new SpellableCharCounter();
    public var keyK:SpellableCharCounter = new SpellableCharCounter();
    public var keyL:SpellableCharCounter = new SpellableCharCounter();
    public var keyM:SpellableCharCounter = new SpellableCharCounter();
    public var keyN:SpellableCharCounter = new SpellableCharCounter();
    public var keyO:SpellableCharCounter = new SpellableCharCounter();
    public var keyP:SpellableCharCounter = new SpellableCharCounter();
    public var keyQ:SpellableCharCounter = new SpellableCharCounter();
    public var keyR:SpellableCharCounter = new SpellableCharCounter();
    public var keyS:SpellableCharCounter = new SpellableCharCounter();
    public var keyT:SpellableCharCounter = new SpellableCharCounter();
    public var keyU:SpellableCharCounter = new SpellableCharCounter();
    public var keyV:SpellableCharCounter = new SpellableCharCounter();
    public var keyW:SpellableCharCounter = new SpellableCharCounter();
    public var keyX:SpellableCharCounter = new SpellableCharCounter();
    public var keyY:SpellableCharCounter = new SpellableCharCounter();
    public var keyZ:SpellableCharCounter = new SpellableCharCounter();
    public var key$:SpellableCharCounter = new SpellableCharCounter();
    
    public function Typewriter():void{
        super( 'http://cloud10.jp/wonderfl/gyaos/typewriter.png' );
        //super( 'keyboard.png' );
    }
    
    public function codeToChar( keyCode:uint ):String{
        return String.fromCharCode( keyCode ).toLowerCase();
    }
    
    protected override function _complete( e:Event ):void{
        super._complete( e );
        
        // Graphical Position constants
        const MARGIN:uint = 46;
        const ROW1_X:uint = 25;
        const ROW2_X:uint = 38;
        const ROW3_X:uint = 53;
        const ROW1_Y:uint = 20;
        const ROW2_Y:uint = 67;
        const ROW3_Y:uint = 114;
        
        // Q ~ P keys
        addChild( keyQ );
        keyQ.x = ROW1_X;
        keyQ.y = ROW1_Y;
        
        addChild( keyW );
        keyW.x = ROW1_X + MARGIN;
        keyW.y = ROW1_Y;
        
        addChild( keyE );
        keyE.x = ROW1_X + MARGIN * 2;
        keyE.y = ROW1_Y;
        
        addChild( keyR );
        keyR.x = ROW1_X + MARGIN * 3;
        keyR.y = ROW1_Y;
        
        addChild( keyT );
        keyT.x = ROW1_X + MARGIN * 4;
        keyT.y = ROW1_Y;
        
        addChild( keyY );
        keyY.x = ROW1_X + MARGIN * 5;
        keyY.y = ROW1_Y;
        
        addChild( keyU );
        keyU.x = ROW1_X + MARGIN * 6;
        keyU.y = ROW1_Y;
        
        addChild( keyI );
        keyI.x = ROW1_X + MARGIN * 7;
        keyI.y = ROW1_Y;
        
        addChild( keyO );
        keyO.x = ROW1_X + MARGIN * 8;
        keyO.y = ROW1_Y;
        
        addChild( keyP );
        keyP.x = ROW1_X + MARGIN * 9;
        keyP.y = ROW1_Y;
        
        // A ~ L keys
        addChild( keyA );
        keyA.x = ROW2_X;
        keyA.y = ROW2_Y;
        
        addChild( keyS );
        keyS.x = ROW2_X + MARGIN;
        keyS.y = ROW2_Y;
        
        addChild( keyD );
        keyD.x = ROW2_X + MARGIN * 2;
        keyD.y = ROW2_Y;
        
        addChild( keyF );
        keyF.x = ROW2_X + MARGIN * 3;
        keyF.y = ROW2_Y;
        
        addChild( keyG );
        keyG.x = ROW2_X + MARGIN * 4;
        keyG.y = ROW2_Y;
        
        addChild( keyH );
        keyH.x = ROW2_X + MARGIN * 5;
        keyH.y = ROW2_Y;
        
        addChild( keyJ );
        keyJ.x = ROW2_X + MARGIN * 6;
        keyJ.y = ROW2_Y;
        
        addChild( keyK );
        keyK.x = ROW2_X + MARGIN * 7;
        keyK.y = ROW2_Y;
        
        addChild( keyL );
        keyL.x = ROW2_X + MARGIN * 8;
        keyL.y = ROW2_Y;
        
        // Z ~ M keys
        addChild( keyZ );
        keyZ.x = ROW3_X;
        keyZ.y = ROW3_Y;
        
        addChild( keyX );
        keyX.x = ROW3_X + MARGIN;
        keyX.y = ROW3_Y;
        
        addChild( keyC );
        keyC.x = ROW3_X + MARGIN * 2;
        keyC.y = ROW3_Y;
        
        addChild( keyV );
        keyV.x = ROW3_X + MARGIN * 3;
        keyV.y = ROW3_Y;
        
        addChild( keyB );
        keyB.x = ROW3_X + MARGIN * 4;
        keyB.y = ROW3_Y;
        
        addChild( keyN );
        keyN.x = ROW3_X + MARGIN * 5;
        keyN.y = ROW3_Y;
        
        addChild( keyM );
        keyM.x = ROW3_X + MARGIN * 6;
        keyM.y = ROW3_Y;        
    }
    
    public function display( remainder:SpellableChars ):void{
        keyA.num = remainder.a;
        keyB.num = remainder.b;
        keyC.num = remainder.c;
        keyD.num = remainder.d;
        keyE.num = remainder.e;
        keyF.num = remainder.f;
        keyG.num = remainder.g;
        keyH.num = remainder.h;
        keyI.num = remainder.i;
        keyJ.num = remainder.j;
        keyK.num = remainder.k;
        keyL.num = remainder.l;
        keyM.num = remainder.m;
        keyN.num = remainder.n;
        keyO.num = remainder.o;
        keyP.num = remainder.p;
        keyQ.num = remainder.q;
        keyR.num = remainder.r;
        keyS.num = remainder.s;
        keyT.num = remainder.t;
        keyU.num = remainder.u;
        keyV.num = remainder.v;
        keyW.num = remainder.w;
        keyX.num = remainder.x;
        keyY.num = remainder.y;
        keyZ.num = remainder.z;
    }
}

class SpellableCharCounter extends Sprite{
    private var _num:int = 0;
    public function set num( value:int ):void{
        _num = value < 0 ? 0 : value;
        if( _num ){
            visible = true;
        }else{
            visible = false;
        }
        textField.text = _num.toString();
    }
    public function get num():int{
        return _num;
    }
    
    private var textField:TextField = new TextField();
    
    public function SpellableCharCounter( num:uint = 0 ):void{
        visible = false;
        
        this.num = num;
        
        graphics.beginFill( 0xFF0000 );
        graphics.drawCircle( 10, 10, 10 );
        
        var format:TextFormat = new TextFormat();
        format.color = 0xFFFFFF;
        format.align = TextFormatAlign.CENTER;
        
        textField.defaultTextFormat = format;
        
        textField.width = 20;
        
        addChild( textField );
        
        textField.x = 0;
        textField.y = 0;
    }
}

class SpellField extends TextField{
    
    public var textBeforeKeyUp:String = '';
    public var onKeyDown:Function;
    public var onKeyUp:Function;
    
    public function SpellField():void{
        
        var format:TextFormat = new TextFormat();
        
        format.align = TextFormatAlign.CENTER;
        format.size = 30; 
        
        defaultTextFormat = format;
    }
}

class SpellableChars extends Object{
    public var a:int = 0;
    public var b:int = 0;
    public var c:int = 0;
    public var d:int = 0;
    public var e:int = 0;
    public var f:int = 0;
    public var g:int = 0;
    public var h:int = 0;
    public var i:int = 0;
    public var j:int = 0;
    public var k:int = 0;
    public var l:int = 0;
    public var m:int = 0;
    public var n:int = 0;
    public var o:int = 0;
    public var p:int = 0;
    public var q:int = 0;
    public var r:int = 0;
    public var s:int = 0;
    public var t:int = 0;
    public var u:int = 0;
    public var v:int = 0;
    public var w:int = 0;
    public var x:int = 0;
    public var y:int = 0;
    public var z:int = 0;
    public var $:int = 0;
    private var _text:String;
    
    public function SpellableChars( text:String ):void{
        _text = text;
        var chars:Array = text.split('');
        var i:uint = chars.length;
        while( i-- > 0 ){
            this[ chars[ i ] ]++;
        }
    }
    
    public function clone():SpellableChars{
        return new SpellableChars( _text );
    }
    
    public function getRestrictChars():String{
        var result:String = '';
        for( var i:uint = 97; i < 123; i++){
            var char:String = String.fromCharCode( i );
            if( this[ char ] ){
                result += char;
            }
        }
        return result;
    }
}

/* Spell Class *
 * ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== */
class Spell{
    public var master:Character;
    public var power:uint;
    public var summary:String;
    
    public function Spell( master:Character, power:uint, summary:String ){
        this.master  = master;
        this.power   = power;
        this.summary = summary;
    }
    
    public function spell( target:Character, spell:String, critical:uint = 1 ):uint{
        var mainPower:uint = power * spell.length * critical;
        var random:Number = ExMath.random( 0.955, 1.144 );
        var damage:uint = Math.ceil( (master.magic - target.magicDef) * mainPower * random );
        return damage;
    }
}

class ExMath{
    /**
    *  @startから@toまでの乱数を返す静的メソッド(浮動小数点数対応※正確さは保証できない)
    */
    public static function random( start:Number, to:Number ):Number{
        var place:uint        = Math.max( ExMath.placeFigure( start ), ExMath.placeFigure( to ) );
        var quantitizer:uint  = Math.pow( 10, place );
        var base:Number       = Math.min( start, to );
        var difference:Number = Math.abs( ExMath.round( start - to, place ) ) * quantitizer;
        var result:Number     = ( base * quantitizer + Math.random() * difference ) / quantitizer;
        return ExMath.round( result, place );
    }
    /**
    *  @numberを小数点第(@place)位で四捨五入した結果を返す静的メソッド
    */
    public static function round( number:Number, place:uint ):Number{
        var quantitizer:uint = place > 0 ? Math.pow( 10, place ) : 1;
        return Math.round( number * quantitizer ) / quantitizer;
    }
    /**
    *  @numberを有効桁数を返す静的メソッド
    */
    public static function placeFigure( number:Number ):uint{
        var place:Array = number.toString().split( '.' );
        return place[1] ? place[1].length : 0;
    }
    /**
    *  @numberが@range1から(@range2:省略の場合0)の範囲にあるかどうか論理値で返す静的メソッド
    */
    public static function inRange( number:Number, range1:Number, range2:Number = 0 ):Boolean{
        if( number == range1 || number == range2 ) return true;
        var top:Number = Math.max( number, range1, range2 );
        if( top == number ) return false;
        var bottom:Number = Math.min( number, range1, range2 );
        if( bottom == number ) return false;
        return true;
    }
}

class ExString{
    public static function convert( string:String, option:uint ):String{
        var chars:Array = string.split('');
        var i:uint      = chars.length;
        var code:uint;
        switch( option ){
            // ExStringConvert.HIRAGANA_TO_KATAKANA
            case 0:
                while( i-- > 0 ){
                    code = chars[ i ].charCodeAt();
                    if( ExMath.inRange( code, 12353, 12438 ) || ExMath.inRange( code, 12445, 12446 ) ){
                        chars[ i ] = String.fromCharCode( code + 96 );
                    }
                }
            break;
            // ExStringConvert.KATAKANA_TO_HIRAGANA
            case 1:
                while( i-- > 0 ){
                    code = chars[ i ].charCodeAt();
                    if( ExMath.inRange( code, 12449, 12534 ) || ExMath.inRange( code, 12541, 12542 ) ){
                        chars[ i ] = String.fromCharCode( code - 96 );
                    }else if( ExMath.inRange( code, 12535, 12538 ) ){
                        chars[ i ] = String.fromCharCode( code - 104 ) + '゛';
                    }
                }
            break;
        }
        return chars.join('');
    }
}

class ExStringConvert{
    public static const HIRAGANA_TO_KATAKANA:uint = 0;
    public static const KATAKANA_TO_HIRAGANA:uint = 1;
}


    class GetData {
        /* Properties *
         * ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== */
            // public
            public var url:String = null;
            public var param:Object = null;
            public var open:Function = null;
            public var progress:Function = null;
            public var complete:Function = null;
            public var error:Function = null;
            public var method:String = URLRequestMethod.GET;
            public var event:Event = null;
            // private
            private var _urlReq:URLRequest = new URLRequest();
            private var _urlLoad:URLLoader = new URLLoader();
        
        /* Constractor *
         * ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== */
            public function GetData ( url:String, param:Object = null, method:String = null ):void {
                this.url = url;
                _urlReq.url = this.url;
                this.param = param;
                if( method == URLRequestMethod.POST ) this.method = URLRequestMethod.POST;
            }
        /* Private Methods *
         * ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== */
            private function _open(e:Event):void{
                event = e;
                this.open();
            }
            private function _progress(e:ProgressEvent):void{
                event = e;
                var bytesLoaded:int = e.target.bytesLoaded;
                var bytesTotal:int = e.target.bytesTotal;
                progress( bytesLoaded, bytesTotal );
            }
            protected function _complete(e:Event):void{
                event = e;
                complete( e.target.data );
            }
            private function _ioError(e:IOErrorEvent):void{
                event = e;
                var errorMessage:String = e.text;
                error( errorMessage );
            }
            private function _securityError(e:SecurityErrorEvent):void{
                event = e;
                var errorMessage:String = e.text;
                error( errorMessage );
            }
        /* Methods *
         * ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== */
            public function load ():void {
                if (Boolean(open)) {
                    _urlLoad.addEventListener (Event.OPEN, _open);
                }
                if (Boolean(progress)) {
                    _urlLoad.addEventListener (ProgressEvent.PROGRESS, _progress);
                }
                
                    _urlLoad.addEventListener (Event.COMPLETE, _complete);
                
                if (Boolean(error)) {
                    _urlLoad.addEventListener (IOErrorEvent.IO_ERROR, _ioError);
                    _urlLoad.addEventListener (SecurityErrorEvent.SECURITY_ERROR, _securityError);
                }
                if (param) {
                    var _urlVar:URLVariables = new URLVariables();
                    _urlReq.method = method;
                    for (var p:String in param) {
                        _urlVar[p] = param[p];
                    }
                    _urlReq.data = _urlVar;
                }
                _urlLoad.load ( _urlReq );
            }
    }

    
    class GetXML extends GetData {
        
        /* Constractor *
         * ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== */
            public function GetXML ( url:String, param:Object = null, method:String = null ):void {
                super( url, param, method );
            }
        
        /* Private or Protected Methods *
         * ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== */
            protected override function _complete(e:Event):void{
                event = e;
                var xml:XML = new XML( e.target.data );
                complete( xml );
            }
    }