キャラクターチャット - Flash(ActionScript)とPHPの連携入門
目次
実行画面
キャラクターが話すチャットプログラムです。自動リロード時間は10秒となっています。チャット画面へ
ソースダウンロード
今回のポイント
-キャラクターのドラッグ-eval
画面作成
ファイル名「chat2.fla」で新規 Flash ドキュメントを作成してください。そこにステージ・ステージに乗せるシンボルなどを作ってゆきます。ステージのプロパティ
最初にステージのプロパティを設定します。この解説で使っているムービーでは、サイズを「550×400」、背景色を「#FFFFFF」、フレームレートを「15fps」としています。背景の作成
1フレーム目に以下のような感じで適当に背景を描きます。キャラクタの作成
次に、キャラクタのムービークリップを作成します。キャラクタの上下にはダイナミックテキストを作り、上のダイナミックテキストの変数名を「name」、下のダイナミックテキストの変数名を「msg」としてください。上に名前、下に喋った言葉が入ります。注意点として、必ずステージ上ではなくムービークリップの編集画面でダイナミックテキストを作成してください。同じようにしてムービークリップを4つ作り、ステージ上に配置します。ムービークリップのインスタンス名は「chr1」「chr2」「chr3」「chr4」と付けます。
名前入力フィールドの作成
次に中央あたりにテキスト入力フィールドを作成し、変数名に「name」と付けます。入力フィールドの上に「名前を入力して好きなキャラクタを選んでください」といったテキストを書いておくと良いでしょう。メッセージ入力フィールドの作成
次に2フレーム目にキーフレームを打ち、2フレーム目の名前入力フィールドを削除し、画面下あたりにテキスト入力フィールドを作成し、インスタンス名に「msg_txt」と付けます。変数名ではないので注意してください。1フレーム目のアクションの作成
1フレーム目をクリックして、以下の ActionScript を記述します。
System.useCodepage = true;
var sl = new LoadVars(); // 送受信データ
var myno; // 自分のキャラクタNo.
var msg = ""; // 入力メッセージ
sl.load("chat2.php");
sl.onLoad = function() {
var user = this.user.split("\t");
for (var i = 0; i < 4; i++) {
var mc = eval("chr" + (i + 1));
if (user[i] != "") mc._visible = false;
mc.no = i + 1;
mc.vy = 0;
mc.ay = 0.2;
mc.onEnterFrame = function() {
this._y += this.vy;
this.vy += this.ay;
if (this.vy < -2 || this.vy > 2) this.ay = -this.ay;
}
mc.onPress = function() {
if (name != "") {
myno = this.no;
gotoAndStop(2);
}
}
}
}
stop();
2フレーム目のアクションの作成
次に2フレーム目をクリックして、以下の ActionScript を記述します。
var timer = 0; // リロードタイマ
sl = new LoadVars();
Key.addListener(msg_txt);
call_php();
for (var i = 0; i < 4; i++) {
var mc = eval("chr" + (i + 1));
mc._visible = true;
mc.onPress = function() {this.startDrag();}
mc.onRelease = function() {this.stopDrag();}
mc.onReleaseOutside = function() {this.stopDrag();}
}
// Enterキーの処理
msg_txt.onKeyDown = function() {
if (Key.getCode() == Key.ENTER) {
msg = msg_txt.text;
msg_txt.text = "";
call_php();
}
}
// PHPからデータを受信したときの処理
sl.onLoad = function() {
var user = this.user.split("\t");
var log = this.log.split("\t");
for (var i = 0; i < 4; i++) {
var mc = eval("chr" + (i + 1));
mc.name = user[i];
mc.msg = "「" + log[i] + "」";
}
timer = 0;
}
// 毎フレーム処理
onEnterFrame = function() {
// 10秒でリロード
if (++timer > 15 * 10) call_php();
}
// PHPコール
function call_php() {
sl.name = name;
sl.msg = msg;
sl.no = myno;
sl.sendAndLoad("chat2.php?rn=" + Math.random(), sl);
}
完成したらパブリッシュして chat2.swf と chat2.html をサーバにアップロードしてください。サーバプログラム(PHP)の作成
次にチャットデータを送受信するPHPプログラムを作成します。以下のソースを入力してください。
<?php
$lines = array();
$user = "";
$log = "";
$fp = fopen('chat2.txt', 'r+');
flock($fp, LOCK_EX);
for (;;) {
$line = fgets($fp);
if (!$line) break;
array_push($lines, $line);
}
if (count($lines) < 4) {
for ($i = 0; $i < 4; $i++) $lines[$i] = "\t\t0";
}
$time = time();
if ($_POST['no']) $lines[$_POST['no'] - 1] = "{$_POST['name']}\t{$_POST['msg']}\t$time\n";
rewind($fp);
ftruncate($fp, 0);
foreach ($lines as $l) {
list($n, $m, $t) = explode("\t", $l);
$t = rtrim($t);
// 30秒以上リロードのないユーザーはオフライン
if ($time - $t > 30) {$n = ""; $m = "";}
fputs($fp, "$n\t$m\t$t\n");
$user .= "$n\t";
$log .= "$m\t";
}
fclose($fp);
print "user=" . urlencode($user);
print "&log=" . urlencode($log);
?>
完成したら「chat2.php」という名前でサーバにアップロードしてください。ログファイルの作成
次にチャットのログを保存するファイルを作成します。空のテキストファイル「chat2.txt」を作成してサーバにアップし、属性変更から「その他」に書込許可属性を与えてください。実行
以上が完成したらサーバ上の chat2.html を実行します。chat2.swf を直接実行しても構いません。ActionScript 解説
1フレーム目のアクション解説
var sl = new LoadVars();
サーバとデータをやり取りするための LoadVars オブジェクトを生成しています。
var myno;
自分のキャラクタ番号が入ります(chr1 なら 1, chr2 なら 2, chr3 なら 3, chr4 なら 4)。
var msg = "";
確定した入力メッセージを保存しておく変数です。
sl.load("chat2.php");
まず最初に、既に使われているキャラクタを調べるためにサーバからチャットデータを取得しています。
var user = this.user.split("\t");
現在のユーザ名がタブ区切りで返ってくるので、split 関数で分割して user 配列に代入しています。
var mc = eval("chr" + (i + 1));
eval は引数の文字列を ActionScript の変数名や関数名として使うことができる命令です。ここでは mc に chr1 ~ chr4 までのムービークリップの参照が順番に入ってきます。
if (user[i] != "") mc._visible = false;
ユーザー文字列が空でなければそのユーザーはオンラインなので、ムービークリップを見えなくして選択不可能にします。
mc.no = i + 1;
選んだムービークリップのキャラクタ番号が分からなくなると困るので、ここで保存しておきます。
mc.vy = 0;
mc.ay = 0.2;
ムービークリップが縦方向に揺れる効果を行うために速度と加速度の変数を作ります。
mc.onEnterFrame = function() {
this._y += this.vy;
this.vy += this.ay;
if (this.vy < -2 || this.vy > 2) this.ay = -this.ay;
}
毎フレーム処理では、ムービークリップが揺れる処理を行っています。
mc.onPress = function() {
if (name != "") {
myno = this.no;
gotoAndStop(2);
}
}
ムービークリップ上でマウスがクリックされたときは、まず名前が入力されているか調べ、入力されていたら自分のキャラクタ番号を取り出し、2フレーム目へ移動します。2フレーム目のアクション解説
var timer = 0;
リロード用のタイマです。
Key.addListener(msg_txt);
Enter キーをメッセージ入力フィールドで受け付けるようにします。
call_php();
最初にサーバに接続して他のオンラインユーザーの名前とメッセージを取得します。関数の内容については後述します。
var mc = eval("chr" + (i + 1));
4つのキャラクタのムービークリップを mc で参照します。
mc._visible = true;
全てのキャラクタを表示状態にします。
mc.onPress = function() {this.startDrag();}
ムービークリップ上でマウスが押されたとき、ドラッグを開始します。startDrag メソッドによってムービークリップをドラッグすることができます。
mc.onRelease = function() {this.stopDrag();}
マウスが離されたとき、stopDrag メソッドによってムービークリップのドラッグを終了します。
mc.onReleaseOutside = function() {this.stopDrag();}
onReleaseOutside は、マウスが押された後、ムービークリップ上でない場所でマウスが離されたときに発生するイベントです。この場合も同じようにドラッグを終了します。
msg_txt.onKeyDown = function() {
if (Key.getCode() == Key.ENTER) {
msg = msg_txt.text;
msg_txt.text = "";
call_php();
}
}
メッセージ入力フィールド上で Enter キーを押したときの処理です。変数 msg に入力されたテキストを格納し、入力フィールドを空にし、サーバに入力内容を送信するために call_php 関数を呼び出しています。
sl.onLoad = function() {
サーバからチャットデータが返信されたときに呼ばれます。
var user = this.user.split("\t");
var log = this.log.split("\t");
まずユーザとそれぞれのユーザのメッセージがタブ区切りで送られるのでそれぞれ配列 user, log に格納します。
for (var i = 0; i < 4; i++) {
var mc = eval("chr" + (i + 1));
mc.name = user[i];
mc.msg = "「" + log[i] + "」";
}
画面上のムービークリップのダイナミックテキストにユーザ名とメッセージをセットします。
onEnterFrame = function() {
// 10秒でリロード
if (++timer > 15 * 10) call_php();
}
毎フレーム処理です。10秒毎にリロードします。
function call_php() {
サーバ上の PHP 呼び出し関数です。
sl.name = name;
sl.msg = msg;
sl.no = myno;
sl.sendAndLoad("chat2.php?rn=" + Math.random(), sl);
LoadVars オブジェクト sl に自分の名前、メッセージ、キャラクタ番号をセットし送信します。PHPプログラムの解説
ログファイル chat2.txt の内容は名前\tメッセージ\t送信時間\n
という形式で上から順番にキャラ1~キャラ4の4行分あります。
$lines = array();
$user = "";
$log = "";
$lines にはログファイルの各行が配列で入ります。$user は Flash に送信するユーザ一覧、$log は Flash に送信するメッセージ一覧が入ります。
for (;;) {
$line = fgets($fp);
if (!$line) break;
array_push($lines, $line);
}
ログファイルの各行を $lines 配列に格納します。
if (count($lines) < 4) {
for ($i = 0; $i < 4; $i++) $lines[$i] = "\t\t0";
}
ログファイルが4行無いときは最初に呼ばれたときなので初期値として名前とメッセージは空、時間は0をセットします。
if ($_POST['no']) $lines[$_POST['no'] - 1] = "{$_POST['name']}\t{$_POST['msg']}\t$time\n";
キャラクタ番号があるときは、該当する行に Flash から送信された名前・メッセージと送信時間を格納します。
foreach ($lines as $l) {
list($n, $m, $t) = explode("\t", $l);
$t = rtrim($t);
// 30秒以上リロードのないユーザーはオフライン
if ($time - $t > 30) {$n = ""; $m = "";}
fputs($fp, "$n\t$m\t$t\n");
$user .= "$n\t";
$log .= "$m\t";
}
各行をタブで分割し、ファイルに格納し直し、さらに Flash 側にユーザ一覧とメッセージ一覧をタブ区切りで送信しています。現在時間と送信時間の差を調べて30秒以上送信の無いユーザーはオフラインとします。