ジャンピングゲーム(スコアランキング) - Flash(ActionScript)とPHPの連携入門
目次
- Flash(ActionScript)とPHPの連携入門
- ジャンピングゲーム(スコアランキング)
- レースゲーム(スコアランキング)
- チャット
- キャラクターチャット
実行画面
床の穴に落ちないようにだるまをジャンプさせて行くゲームです。マウスを押しつづけるとパワーが溜まって行き、離すとパワーに応じた距離をジャンプします。ゲームオーバーになったときに、名前を入れて send ボタンを押すとスコアランキングに登録することができます。ゲーム画面へ
ソースダウンロード
今回のポイント
- getURL 関数による PHP との連携
- 床のスクロール
画面作成
ファイル名「jump.fla」で新規 Flash ドキュメントを作成してください。そこにステージ・ステージに乗せるシンボルなどを作ってゆきます。ステージのプロパティ
最初にステージのプロパティを適当に設定します。この解説で使っているムービーでは、サイズを「640×160」、背景色を「#FFAA42」、フレームレートを「30fps」としています。自機の作成
1フレーム目に自機のキャラクタを描いてムービークリップに変換し、インスタンス名を「jiki_mc」とします。中心点は自機の中央にしてください。インスタンスを配置する場所はどこでもOKです。
床の作成
次に床のキャラクタを描いてムービークリップに変換します。その後ライブラリウインドウの床のシンボルを右クリックし「リンケージ」を選び、「リンケージプロパティ」のウインドウで「ActionScriptに書き出し」にチェックを入れ、「識別子」の欄に「yuka」と書きます。画面上のインスタンスは削除しておいてください。
テキスト(パワー・メートル)の作成
1フレーム目に下図のようにテキストを配置してください。「power」と「m」は静止テキストにします。「power」の右の0はダイナミックテキストにして変数の欄に「pow」と書きます。「m」の左の0もダイナミックテキストとし、変数の欄に「meter」と書きます。
2フレーム目の作成
2フレーム目にキーフレームを挿入し、下図のようにゲームオーバー画面を作成します。文字「GAME OVER」「name」は静止テキストにします。真ん中の白い部分は四角形を描き、その上にテキスト入力エリア(テキストツールで作った文字エリアのプロパティを「テキスト入力」にする)を追加し、変数の欄に「name」と書きます。右の「send」はボタンシンボルにします。
ランキング無しのプログラムの記述
まずスコアランキング無しのプログラムを作成します。1フレーム目のアクション
1フレーム目をクリックして、以下の ActionScript を記述します。
var yuka = new Array(); // 床配列
var yn, yw; // 床の数・幅
var over = false; // ゲームオーバーならtrue
var ssp = 4; // スクロールスピード
var level = 0.1; // 難易度
pow = 0; // ジャンプ力(ダイナミックテキスト)
meter = 0; // 進行距離(ダイナミックテキスト)
for (yn = 0;; yn++) {
yuka[yn] = attachMovie("yuka", "yuka" + yn, yn);
if (yn == 0) yw = yuka[yn]._width - 4;
yuka[yn]._x = yn * yw;
yuka[yn]._y = Stage.height - yuka[yn]._height;
if (yuka[yn]._x > Stage.width + yuka[yn]._width) break;
}
onEnterFrame = function() {
if (over) {
gotoAndStop(2);
return;
}
// 床スクロール
for (var i = 0; i < yn; i++) {
yuka[i]._x -= ssp;
}
if (yuka[yn - 1]._x < Stage.width) {
var yt = yuka[0];
yt._x = yuka[yn - 1]._x + yw;
if (Math.random() < level) yt._visible = false;
else yt._visible = true;
level += 0.001;
if (level > 0.9) level = 0.9;
for (var i = 0; i < yn - 1; i++) {
yuka[i] = yuka[i + 1];
}
yuka[yn - 1] = yt;
}
meter++;
// 落ち判定
var rf = true;
for (var i = 0; i < yn; i++) {
if (!jiki_mc.jf) {
if (yuka[i]._visible &&
yuka[i]._x + yuka[i]._width / 2 > jiki_mc._x &&
yuka[i]._x - yuka[i]._width / 2 < jiki_mc._x) {
rf = false;
}
} else rf = false;
}
if (rf) {
jiki_mc._y += 40;
over = true;
}
if (jiki_mc._x < 0 || jiki_mc._x > Stage.width) over = true;
}
stop();
自機のアクション
自機シンボルのインスタンスをクリックして以下の ActionScript を記述します。
onClipEvent(load) {
_x = Stage.width / 2;
_y = Stage.height - _root.yuka[0]._height * 2 - 2;
var mf = false; // マウスボタンを押していればtrue
var jf = false; // ジャンプ中ならtrue
var sy = _y; // 初期Y座標
var vy = 0; // ジャンプ中の速度
}
onClipEvent(enterFrame) {
if (_root.over) return;
if (jf) {
_y += vy;
vy++;
_x += _root.ssp;
if (_y > sy) {
jf = false;
_y = sy;
_root.pow = 0;
}
} else if (mf) {
_x -= _root.ssp;
_root.pow += 1;
if (_root.pow > 40) _root.pow = 0;
} else {
_rotation += 8;
}
}
onClipEvent(mouseDown) {
mf = true;
}
onClipEvent(mouseUp) {
mf = false;
if (!jf) {
jf = true;
vy = -_root.pow / 2;
}
}
実行
以上が完成したら保存してゲームを実行し、スコアランキング以外の部分が動くことを確認してください。ランキング部分のプログラムの記述
次にスコアランキング部分のプログラムを作成します。sendボタンのアクション
2フレーム目の「send」ボタンをクリックし、以下の ActionScript を記述します。
on(release) {
System.useCodepage = true;
getURL("jump.php?name=" + escape(name) + "&meter=" + meter);
}
ランキングプログラム(PHP)の作成
次にスコアランキングの登録・表示を行うPHPプログラムを作成します。以下のソースを入力してください。Flash からパブリッシュしたHTMLファイルを使うと良いでしょう。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>だるま転がし</title>
</head>
<body>
<div align="center">
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="640" height="160" id="jump" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="jump.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffaa42" />
<embed src="jump.swf" quality="high" bgcolor="#ffaa42" width="640" height="160" name="jump" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
<br><br>
<table border="1">
<tr><th>順位</th><th>お名前</th><th>距離</th></tr>
<?php
$name = htmlspecialchars($_GET['name']);
$meter = htmlspecialchars($_GET['meter']);
$rank = file("rank.txt");
if ($meter) {
if (!$name) $name = "名無しさん";
for ($i = 0; $i < count($rank) + 1; $i++) {
if ($i < count($rank)) {
list($n, $m) = split("\t", $rank[$i]);
$m = rtrim($m);
} else $m = 0;
if ($meter > $m) {
array_splice($rank, $i, 0, "$name\t$meter\n");
break;
}
}
if (count($rank) > 20) array_pop($rank);
$fp = fopen('rank.txt', 'r+');
flock($fp, LOCK_EX);
ftruncate($fp, 0);
for ($i = 0; $i < count($rank); $i++) fputs($fp, $rank[$i]);
fclose($fp);
}
for ($i = 0; $i < count($rank); $i++) {
list($n, $m) = split("\t", $rank[$i]);
$m = rtrim($m);
print "<tr><td>" . ($i + 1) . "</td><td>$n</td><td>{$m}m</td></tr>\n";
}
?>
</table>
</div>
</body>
</html>
完成したら「jump.php」という名前でサーバにアップロードしてください。ランキングファイルの作成
空のテキストファイル「rank.txt」を作成してサーバにアップし、属性変更から「その他」に書込許可属性を与えてください。実行
以上が完成したらサーバ上の「jump.php」を実行し、スコアが登録できることを確認してみてください。ActionScript 解説
1フレーム目のフレームアクション解説
var yuka = new Array();
床の配列です。左から順に要素 0, 1, 2… となります。
var yn, yw;
床の数と一個の床の幅です。
var over = false;
ゲームオーバーならこのフラグが true になります。
var ssp = 4;
一回に床が動くピクセル数です。
var level = 0.1;
難易度です。これが1に近づくほど穴の数が多くなり難しくなります。
pow = 0;
meter = 0;
ジャンプ力と走行距離を表すダイナミックテキスト変数です。画面に直接反映されます。
for (yn = 0;; yn++) {
yuka[yn] = attachMovie("yuka", "yuka" + yn, yn);
if (yn == 0) yw = yuka[yn]._width - 4;
yuka[yn]._x = yn * yw;
yuka[yn]._y = Stage.height - yuka[yn]._height;
if (yuka[yn]._x > Stage.width + yuka[yn]._width) break;
}
床の初期配置を作成している部分です。まず attachMovie によって床のインスタンスを作成し、床の幅-4ピクセルの幅で床を敷き詰めて行きます。スクロールすることを考えて画面一杯+床一個分敷き詰まったら、break でループを抜けます。
onEnterFrame = function() {
以下は毎フレーム時の処理です。
if (over) {
gotoAndStop(2);
return;
}
ゲームオーバーならば2フレーム目に移行します。
for (var i = 0; i < yn; i++) {
yuka[i]._x -= ssp;
}
各床をスクロールスピードの分だけ左に移動します。
if (yuka[yn - 1]._x < Stage.width) {
一番右の床の中心点がステージ内に入ったら、床のローテーション処理を以下で行います。具体的には、床配列の要素を1つずつ左へずらし、一番左の要素を一番右の要素として再利用し、座標を付け直します。
var yt = yuka[0];
まずテンポラリ変数 yt に一番左の床の MovieClip を保存しておきます。
yt._x = yuka[yn - 1]._x + yw;
一番左の床の MovieClip は一番右の床の MovieClip として再利用するので、X座標を変更しています。
if (Math.random() < level) yt._visible = false;
else yt._visible = true;
level += 0.001;
if (level > 0.9) level = 0.9;
Math.random 関数は 0以上1未満の任意の実数を返す関数です。それが level の値より小さければ _visible プロパティを false、つまり穴とします。もし現在の level が 0.2 ならば2割の確率で穴が現れるわけです。さらに level を少しずつ上げて徐々に難しくなるようにしています。
for (var i = 0; i < yn - 1; i++) {
yuka[i] = yuka[i + 1];
}
yuka[yn - 1] = yt;
床のローテーション処理を行っています。
meter++;
進行距離を進ませます。
var rf = true;
ここから以下は自機の落下判定です。rf は自機が落下したときに true になるフラグです。
for (var i = 0; i < yn; i++) {
if (!jiki_mc.jf) {
if (yuka[i]._visible &&
yuka[i]._x + yuka[i]._width / 2 > jiki_mc._x &&
yuka[i]._x - yuka[i]._width / 2 < jiki_mc._x) {
rf = false;
}
} else rf = false;
}
自機がジャンプしてなく、なおかつ床があり、なおかつ床の上に自機がいるとき、落下フラグを false にします。これを床の数分だけ繰り返します。
if (rf) {
jiki_mc._y += 40;
over = true;
}
落下したならば自機のY座標を少し下げで落ちた感じを出し、ゲームオーバーフラグを立てます。
if (jiki_mc._x < 0 || jiki_mc._x > Stage.width) over = true;
画面の左端・右端に到達してもゲームオーバーにします。自機のムービークリップアクション解説
onClipEvent(load) {
_x = Stage.width / 2;
_y = Stage.height - _root.yuka[0]._height * 2 - 2;
var mf = false;
var jf = false;
var sy = _y;
var vy = 0;
}
初期設定部分です。自機のX座標は画面の中央にし、自機のY座標は床に乗るようにします。乗っているように見えない場合はここの -2 を調整してみてください。mf はマウスを押している間 true になるフラグ変数です。jf はジャンプしている間 true になるフラグ変数です。sy には自機のジャンプしていないときのY座標を保存しておきます。vy はY方向の速度です。
onClipEvent(enterFrame) {
毎フレーム処理です。
if (_root.over) return;
ゲームオーバーなら何もせずに戻ります。
if (jf) {
ジャンプ中の処理です。
_y += vy;
まずY座標にY方向の速度を加えます。
vy++;
重力加速度を加えています。
_x += _root.ssp;
ジャンプ中は右へ移動します。
if (_y > sy) {
jf = false;
_y = sy;
_root.pow = 0;
}
現在のY座標が初期Y座標より大きいというのは着地したということなので、ジャンプフラグをクリアし、ジャンプ力を0に戻します。
} else if (mf) {
_x -= _root.ssp;
_root.pow += 1;
if (_root.pow > 40) _root.pow = 0;
ジャンプ中でなく、マウスボタンが押されてれば、自機の回転を止めて後ろに下がるようにし、ジャンプ力を増やして行きます。
} else {
_rotation += 8;
}
地上でマウスボタンが押されていなければ回転します。
onClipEvent(mouseDown) {
mf = true;
}
マウスボタンが押されたときに発生するイベントです。フラグを立てているだけです。
onClipEvent(mouseUp) {
mf = false;
if (!jf) {
jf = true;
vy = -_root.pow / 2;
}
}
マウスボタンが離されたときに発生するイベントです。フラグをクリアし、ジャンプ中でなければジャンプ処理(ジャンプフラグを立て、ジャンプ力を速度に設定する)を行います。sendボタンのアクション解説
System.useCodepage = true;
名前を日本語で書くと、Flash の内部文字コードは Unicode、今回の PHP の文字コードは ShiftJIS なので文字化けが起こります。この命令によって Flash の内部文字コードをシステムの文字コード、つまり ShiftJIS にすることができます。
getURL("jump.php?name=" + escape(name) + "&meter=" + meter);
getURL は指定した URL にジャンプする関数です。ここでは GET 変数として PHP に名前と進行距離を送信しています。名前は日本語やスペースが入る可能性があるのでURLエンコードしています。不正な送信を防ぐために暗号化などの措置を取る必要があるのですが、今回は簡略化のためこのままにしています。PHPプログラムの解説
$name = htmlspecialchars($_GET['name']);
$meter = htmlspecialchars($_GET['meter']);
ActionScript から GET メソッドで送られた名前と進行距離をタグをエスケープして取り出しています。
$rank = file("rank.txt");
rank.txt には進行距離の長い順に上から「名前<tab>進行距離」の形式で一行ずつ最大20件記録されます。それを一行ずつ配列 $rank に格納します。
if ($meter) {
GET 変数の meter があるときはスコアを登録したときと見なし、以下のスコア登録処理を行います。
for ($i = 0; $i < count($rank) + 1; $i++) {
スコアを配列 $rank の適切な位置に挿入するために、配列を全てループします。+1 しているのは、配列を全部走査しても挿入すべき場所が見つからなかった場合に配列の一番下に挿入するための措置です。
if ($i < count($rank)) {
list($n, $m) = split("\t", $rank[$i]);
$m = rtrim($m);
} else $m = 0;
配列の要素から split 関数によって進行距離を $m に代入します。配列の一番後ろの場合は進行距離を 0 にして確実に挿入できるようにしています。
if ($meter > $m) {
array_splice($rank, $i, 0, "$name\t$meter\n");
break;
}
現在の進行距離が配列要素の進行距離よりも大きい場合、その要素の上に名前と進行距離を新しい要素として追加します。
if (count($rank) > 20) array_pop($rank);
追加した結果、20件よりも多くなった場合、最後の要素を削除して20件にします。
$fp = fopen('rank.txt', 'r+');
flock($fp, LOCK_EX);
ftruncate($fp, 0);
for ($i = 0; $i < count($rank); $i++) fputs($fp, $rank[$i]);
fclose($fp);
配列 $rank の内容をファイルに書き戻しています。まずロックをかけ、サイズを0にし、一行ずつ書き込みします。
for ($i = 0; $i < count($rank); $i++) {
list($n, $m) = split("\t", $rank[$i]);
$m = rtrim($m);
print "<tr><td>" . ($i + 1) . "</td><td>$n</td><td>{$m}m</td></tr>\n";
}
配列 $rank の内容をテーブルとして書き出しています。