忍者ブログ

Home > Flash・Flex・AS

Flash・Flex・AS Archive

[PR]

  • 2024-11-21 (Thu)
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

  • Comments (Close):
  • TrackBack (Close):

ActionScript再挑戦!Flexで人工無脳作ってみた

2009/06/20 20:10
 誤字脱字修正。

2009/03/06 22:45
 htmlのソースとプロジェクトファイル一式を追加しました。

たぶん、今までで一番長文です。

1年以上前に書いた、
 ・ Hello, Flash!:ActionScriptを初めて使ってみたらお絵かきが簡単にできてびっくりした - Born Neet
は今だに僕のブログで一番の人気記事です。
HolyGrailさんのおかげでしょうが…)

にもかかわらず、それから一年以上ASの話題を扱わないという体たらく。
(地味に勉強してたりはしたんですが、記事にするまでにはいたりませんでした。)

というわけで改めて学びなおすべく、新しい言語の学習にはもってこい(?)の人工無脳を作ってみました。

以下に手順をメモしますので興味があればどうぞ。
ソースのライセンスも(使用ライブラリに合わせて)修正BSDにしとくのでご自由に。

前やった時は、FlexのFの字もわかってなかったのでたいした説明はできませんでしたが、
今回は本読んだり、(だいぶ前ですが)セミナーに行ったりもしてたのでいくらかはマシだと思います。

Flexとは

Flexは、Flashの技術を利用したリッチインターネットアプリケーション(RIA)です。
Flexならデザインセンスのカケラもない僕でも、プログラミングするだけでFlash Player上で動くアプリケーションを作ることができるのです。

と、僕は理解してます。

まぁ細かい定義なんかはどうでもよくて、FlashPlayerがあればどこでも同じように動く、
つまり、「Firefoxで開発→IEで確認→動かない→直す→Firefoxで変に」みたいなことをしなくて済むのです。

ということで僕は勝手にFlexはRIAの本命なんじゃないかと思ってます。

準備

まずは環境を整えます。
やったのは半年以上前なので抜けてるかもしれません。

開発には、FlashDevelopを使います。
補完がないときついので。(テキストエディタでJavaを開発するぐらいのしんどさです)

というわけで、以下のサイトあたりを参考にFlex SDKとFlashDevelopを(ないならJavaも)インストール。
(自分が参考にしたサイトは忘れちゃったので適当に検索しました。)

 ・ Adobe Flex SDK超入門 (treasuring misc.)
 ・ フリーのFlash統合開発環境 FlashDevelop (+flex 3 SDK)を入れてみました:■ 音楽方丈記 ■

他にも情報は山ほどあるのでここは省略。

Flexプログラミング入門

Flashはどうやって作ってるのかさっぱりわかりませんが、
FlexはWebプログラマにとって非常にわかりやすい構造です。
(カッコ内参照)

作成するファイルは以下の3つ。

 ・ mxml(htmlの役目)
 ・ ActionScript(JavaScriptの役目)
 ・ CSS(そのまま)

HTMLベースのアプリと同様に、
mxmlで構造、ASでイベント等を設定、CSSで装飾します。

さらにASとJSは型とclassがあること意外ほとんど同じなので、
mxmlだけ覚えればもう何でも作れちゃうのです!
(実際は以前の僕の記事のようにmxmlなしでも作れますが…)

FlashDevelopのプロジェクトの作り方

さて、そろそろ飽きてきましたが。。。

FlashDevelopは高機能なので初めて使う時若干とまどいます。
特に新規プロジェクト作成の選択肢が多すぎる!

ってことで僕の作成手順を書いときます。

 1. AS3のEmptyProject(なんか2個あるけど上の方)を選択
   ・ Nameは適当(一応ラクダ文字が規則みたい)
   ・ packageは空で
   これで余計なものが何もない空のプロジェクトが作られます。

 2. Projectの箱を右クリックしてmxmlを追加
   さらに
   ・ 追加したmxmlを右クリックしてAlwaysCompileにチェック
   ・ プロジェクトのプロパティ(右クリック or メニューから)で
    「No output~」のチェックを外し、ファイル名を適当に入力

FlashDevelopがちゃんとインストールされていれば、
これでコンパイルでき、Flashでおなじみのswfファイルが作成されるはずです。
(参考サイトにもありますが、External Playerの設定大事)

あとはASなりCSSなりサブのmxmlなりをガシガシ追加していくだけです。

SWFObject

もう駄目だ…長文すぎる…。
というわけで、ソース以外はこれで最後です。

Flashを公開する時はHTMLに埋め込むことになります。
しかしこれが、objectタグやらembedタグやら実にややこしい。

そこで、swfobjectです。
このライブラリを使えばid指定とjs1行で済みます。

詳しくは、

 ・ 八角研究所 : FlashをHTMLに貼るライブラリ swfobject 2 を使う
 ・ SWFObject v2.0 ドキュメント日本語訳 : Media Technology Labs (MTL) : メディアテクノロジーラボ ブログ
 ・ nondelion.com - 続・swfobject で flash を Window 内に全画面表示

等をどうぞ。

Flexな人工無脳

ようやく本題です。
もう説明する気力は残ってないのでコメントを参照してください。

僕の試行錯誤の結果です…。

動くサンプルはここに置いときます→Flexで人工無能 - tnantoka.net
(はじめは空っぽですが、会話を覚えていきます。
またstudyタブからテキストをaddすれば賢くなるかもしれません。)

プロジェクトファイル一式も置いとくのでどうぞ。

Main.mxml

画面構造

<?xml version="1.0" encoding="utf-8"?>
<!-- 
	Applicationにwidth,heightを設定すれば、-config.xmlをいじらなくても大きさ指定できる 
	creationCompleteはwindow.onload的存在(as内からは設定できないので属性で)
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
	
	<!-- as,css外部ファイル化 -->
	<mx:Script source="init.as"/>
	<mx:Style source="style.css"/>
	
	<!-- 大枠 -->
	<mx:Panel width="100%" height="100%" title="Flexで人工無脳" horizontalAlign="center">
		
		<!-- 
			タブ切り替え
			creationPolicy="all"にしないと初期化時にイベント設定できない 
		-->
		<mx:ViewStack id="viewStack" width="100%" height="100%" creationPolicy="all">
			
			<!-- 会話画面 -->
			<mx:VBox label="talk" horizontalAlign="center">
				<mx:HBox width="70%">
					<mx:TextInput width="90%" id="msgInput" />
					<mx:Button label="send" id="sendButton" />
				</mx:HBox>
				<mx:TextArea width="70%" height="85%" id="historyArea"></mx:TextArea>
			</mx:VBox>
			
			<!-- 学習画面 -->
			<mx:VBox label="study" horizontalAlign="center" styleName="study">
				<mx:TextArea width="70%" height="87%" id="sourceArea"></mx:TextArea>
				<mx:HBox width="70%">
					<mx:Button label="init" id="initButton" />
					<mx:Spacer width="100%"/>
					<mx:Button label="add" id="addButton" />
				</mx:HBox>
			</mx:VBox>
			
		</mx:ViewStack>
		
		<!-- タブメニュー(各要素のlabelがタブに) -->
		<mx:LinkBar dataProvider="{viewStack}"/>
		
	</mx:Panel>
	
</mx:Application>

init.as

イベントを設定したり、Munouクラスを使ったり。

import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import mx.events.FlexEvent;
import mx.rpc.http.HTTPService;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;

// グローバル使わないために関数内で処理
private function init():void {
	
	var munou:Munou;
	
	// テキストを読み込んで学習
	// XMLHttpRequest同様に使える
	var http:HTTPService = new HTTPService();
	http.url = 'test.txt';
	http.resultFormat = 'text'; // デフォルトはXML

	// 成功
	http.addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void {
//		munou = new Munou(event.result as String);
		munou = new Munou(''); // 今回は白紙で
	});

	// 失敗
	http.addEventListener(FaultEvent.FAULT, function(event:FaultEvent):void {
		Alert.show(event.fault.faultString);
	});

	http.send();
	
	// sendクリックで話しかける
	sendButton.addEventListener(MouseEvent.CLICK, send);
	// エンター押下にも同じイベント設定
	msgInput.addEventListener(FlexEvent.ENTER, send);
	
	// 初期化
	initButton.addEventListener(MouseEvent.CLICK, function(event:Event):void {
		// 
		munou.init(sourceArea.text);
		sourceArea.text = '';
	});
	
	// 覚えさせる
	addButton.addEventListener(MouseEvent.CLICK, function(event:Event):void {
		if (sourceArea.text) {
			munou.learn(sourceArea.text);
			sourceArea.text = '';
		}
	});
	
	// 話しかける
	function send(event:Event):void {

		var msg:String = msgInput.text;
		
		// ちょっとだけhtmlが使える
		historyArea.htmlText += '<p>あなたの発言:<br/>\t' + msg + '</p>';
		historyArea.htmlText += '<p><font color="#0000ff">munouの発言:<br/>\t' + munou.response(msg) + '</font></p>';
		msgInput.text = '';
		
		// スクロールバーを最終行に設定
		// (遅延実行?しないと更新前の位置になる)
		callLater(function():void {
			historyArea.verticalScrollPosition = historyArea.maxVerticalScrollPosition; 
		});

	}

	// かぎカッコ内のテキストを抽出(不使用)
	function getTalk(text:String):String {

		var talk:Array = text.match(/「[^」]+?」/g);
	
		for(var i:int = 0; i < talk.length; i++) {
			talk[i] = talk[i].replace(/[「\s 」]+/g, '');
		}
		
		return talk.join('\n');
	}
	
} // init

Munou.as

人工無脳(簡易形態素解析+マルコフ連鎖)で会話するclassです。

/**
 * 人工無脳(簡易形態素解析+マルコフ連鎖)で会話するClass
 */
package {

//	import org.coderepos.text.TinySegmenter; // CodeRepos
	import uwi.tinysegmenter.TinySegmenter; // SparkProject
	
	// mxml名と被るとダメ
	public class Munou {

		// 文頭・文末識別子
		private const START:String = '__START__';
		private const END:String = '__END__';
		
		// 初期化テキストを一応保存
		private var text:String;

		// 形態素解析マシン
		private var segmenter:TinySegmenter;
		
		// 学習した結果
		private var dic:Object;
		
		// コンストラクタ
		public function Munou(text:String) {
			this.text = text;			
			segmenter = new TinySegmenter();
			init(text);
		}

		// 初期化
		public function init(text:String):void {
			dic = {};
			learn(text);
		}
		
		// 学習
		public function learn(text:String):void {

			if (text) {
			
				// スペース・タブは1字に圧縮
				// 改行で区切る(スペース・タブは残したいので\sは使わず)
				// そのほかの記号は無視
				var a:Array = 
					text.replace(/([  \t])+/g, '$1')
						.split(/[\r\n]+/);
				
				// Vistaならtraceログは以下に
				// C:\Users\<user>\AppData\Roaming\Macromedia\Flash Player\Logs
				// trace(a.join(','));
				
				for (var i:int = 0; i < a.length; i++) {

					var b:Array = morph(a[i]);
					trace(b.join('|'));
					
					b.unshift(START);
					b.push(END);
					
					for (var j:int = 0; j < b.length - 1; j++) {

						var s:String = b[j];
						if (dic[s]) dic[s].push(b[j + 1])
						else dic[s] = [b[j + 1]];
						
					}	
				}
			}
		}

		// 形態素解析
		private function morph(text:String):Array {
			return segmenter.segment(text);	
		}
		
		// マルコフ連鎖で文章作成
		private function markov(text:String):String {
		
			if (!dic[START]) return '';
			
			var s:String = dic[START][Math.floor(Math.random() * dic[START].length)];
			var r:String = '';
			
			while (s != END) {
				r += s;
				
				// 文末っぽい記号が出ても終了
				if (s.match(/[。!!??]/)) break;
				s = dic[s][Math.floor(Math.random() * dic[s].length)];
			}
			
			return r;
		}
		
		// 応答
		public function response(msg:String):String {
			
			var func:Function;

			learn(msg);

// 今回はマルコフのみで
//			switch(Math.floor(Math.random() * 10)) {
			
				// 1/10の確立でオウム返し
//				case 0:
//					func = echo;
//					break;
				// 1/10の確立で定型応答
//				case 1:
//					func = random;
//					break;
				// その他はマルコフで
//				default:
					func = markov;	
//			}
			
			return func(msg);
		}
		
		// オウム返し(不使用)
		private function echo(msg:String):String {
			return msg;
		}

		// ランダム応答(不使用)
		private function random(msg:String):String {
			
			var a:Array = [
				'',
			];

			return a[Math.floor(Math.random() * a.length)];
		}

		// 初期化テキスト表示(不使用)
		public function getText():String {
			return text;
		}
		
	} // class
	
} // package

style.css

見た目を調整。
htmlほど自由には設定できません。

@charset "UTF-8";

Application {
	background-color: #fff;
/*	width: 300px; 効かない */
}

Panel {
/*	width: 100%; %指定はエラー */
/*	padding: 10px; 効かない */
	padding-top: 20px;
	padding-bottom: 20px;
}

HBox {
/*	text-align: center; TextInputの中身がセンタリングされちゃう */
	padding-top: 10px;
	padding-bottom: 10px;
}

.study {
	padding-top: 10px;
}

index.html

swfを全画面表示

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Flexで人工無脳 - tnantoka.net</title>
	<meta http-equiv="Content-Style-Type" content="text/css" />
	<meta http-equiv="Content-Script-Type" content="text/javascript" />
	<link rel="stylesheet" type="text/css" href="style.css" media="all" />
	<script type="text/javascript" src="swfobject.js"></script>
	<script type="text/javascript">
swfobject.embedSWF('Munou.swf', 'swfArea', '100%', '100%', '9.0.0');
	</script>
	<style type="text/css">
/* for Firefox */
html, body {
	height: 100%;
}
html {
	overflow: hidden;
}
/* common */
body {
	margin: 0;
}	
	
	</style>
</head>
<body>
<div id="swfArea" style="width: 100%; height: 100%;">
</div>
</body>
</html>

読んだ本

photo
Flex3プログラミング入門
宮田 亮
秀和システム 2008-08
おすすめ平均 star
star思わず続編を探してしまいました。
starこれからFlexを触る方へ

by G-Tools , 2009/03/04

だいぶ前に読んだ時はイマイチと思ったんだけど、
AIRプログラミング入門と内容を使い回しすぎだし)
今回作るにあたってリファレンスとして結構役に立った。
初Flexのお供に是非。

photo
ActionScript3.0のドリル (Workbook in Programming)
佐藤 信正
ソシム 2009-02

by G-Tools , 2009/03/04

ホントはFlex3.0SDKで学ぶActionScript3.0入門が欲しかったんだけど、
どこにもないので(発売後1年足らずなのに…)しかたなく、同じくFlex SDK(Builderではなく)で作るこの本を購入。
(安さにつられたわけじゃ…)

プログラミング初心者用の本のため、他言語の経験者にはあまり向かない。
僕はE4Xを触ったことがなかったので多少はためになりました。
(本は対象読者を見てから買いましょう、ですね!)

あと、ところどころに、ん?と思う説明が。。。

関数名だけで利用される関数をクロージャともいいます(p.168)

…いいません!(笑)

とかね。

その他参考

 ・ TextArea自動スクロール
   FirefoxのTextAreaと同じくtextを追加するとスクロールバーが先頭に戻っちゃう対策。

 ・ [Air/Flex]ViewStackの落とし穴 - 秘密結社ぎゅう☆ぎゅう倶楽部
   スムーズな画面遷移と引き換えにイベント設定ができなくなるとか…。

 ・ たまご日記(別館) [flex] テキストの改行が余分に付く
   改行の扱いにわりと苦労させられました。

 ・ /air/TLife/src/uwi/tinysegmenter/TinySegmenter.as - Spark project
 ・ /lang/actionscript/as3tinysegmenter/src/org/coderepos/text/TinySegmenter.as -- CodeRepos::Share -- Trac
   TinySegmenterのAS移植版。
   僕はなんとなくSparkProjectの方を使ってます。

PR

Hello, Flash!:ActionScriptを初めて使ってみたらお絵かきが簡単にできてびっくりした

Flashの勉強しなきゃなぁと思ってたら、ちょうど良いタイミングで、
Flashの要となるスクリプト言語「ActionScript」とは?(1/3) ─ @IT
なんて記事が出てたのでやってみた。

Hello, world!そのままは面白くないので、単純なお絵かきFlashを作ってみることにした。

ActionScript(っていうかFlash自体)初めてで、かなり手探りだったけどなんとか完成。
(ソースとswfは続きに。トップにFlashが表示されると重くなるので)

[感想]

JavaのSwingみたいだなぁというのが第一印象。
構文もそうだけど、コンパイルのもっさり感とか(笑)

っていうかお絵かき機能があまりにも簡単に実現できて軽くショック!
(x)html2presenの時(canvasでやった)の苦労はなんだったんだ~!

とまぁ一応できたけど、やっぱ1回入門書読みたいな。
どっかに本ぐらい体系的にまとまってるAS3のサイトないかなぁ…。

[参考]

Continue reading

Home > Flash・Flex・AS

Search
Loading
Feeds
Links
スポンサードリンク

Page Top