記事一覧
第1回 設定とタイトル
第2回 メイン画面
第3回 ターゲットと敵と
第4回 スコア・時間など
第5回 ゲームを公開する
第6回 Twitterにスコアを投稿
第7回 サウンド関係
第8回 物理エンジンなど
はじめに
@_ahoge_さんが,本連載のツイートをRTしてくださったので,気合をいれて第4回を書きました.
前回までで,なんとなくゲームの骨格ができた(ことにします)ので,スコアや時間など,ゲームに必要なパラメータを管理する部分を作っていきます.
パラメータの設定と表示
まず,Mainの冒頭部分では,スコアと時間に関連する変数を作成する処理が追加されています.いずれも$
で始まるグローバル変数を用いています.これは,ほかのオブジェクトからもこれらの値を参照する可能性があるからです1
$score=0;
$time=0;
$frames=0;
new Label{template="スコア $score 時間 $time", x=200,y=50, size=20}; //★A
$state="play";
new Player{x=100,y=100};
経過時間については,$time
と$frames
という2つの変数を用意しました.経過時間をフレーム数$frames
で計測した上で,秒に変換したものを$time
に格納しています(変換処理は後述).なぜそうしているかというと,★AのLabel
オブジェクトのテンプレート機能を利用するためです.template
フィールドに文字列を設定すると,文字列内の$XXXX
の部分を該当するグローバル変数の値に置換して表示します.この値は常時更新されるので,繰り返しの途中でラベルのテキストの書き換え処理を書く必要がありません.
最後の$state
は,ゲームの状態をあらわすものです.プレイ中は"play"
,クリアしたら"clear"
,ゲームオーバーになったら"gameover"
にそれぞれ設定するようにします(設定する処理はPlayer
クラスにて後述).
メインループ(経過時間の更新)
次に,メインループの前回からの変更点をしまします.
while($state=="play") {//★B
if (rnd(50)==0) {
new Target{x=rnd($screenWidth),y=0,vx=0,vy=1};
}
if (rnd(50)==0) {
new Enemy{x=rnd($screenWidth),y=$screenHeight,vx=0,vy=-1};
}
$frames++;//★C
$time=floor($frames/$Boot.getFrameRate());//★C
update();
}
- ★Bでは,メインループの繰り返し条件を
true
(無限ループ)から$state
が"play"
の間,つまりプレイが続いている間繰り返す,というように変更しています. - ★Cでは,経過時間の計測を次のように行っています.
-
$frames
をフレームごとに増やす -
$time
は$frames
をフレームレート$Boot.getFrameRate()
で割る2 -
floor
関数で小数点以下を切り捨てる
-
プレイヤー(スコアと状態の更新)
Main
のプログラムはまだ続いているのですが,ここでいったんPlayer
クラスのほうに目を向けてみましょう.★Dと★Eが追加した部分です.
pad=new APad;
p=$pat_ahoge26+0;
while(true) {
x+=pad.vx*5;
y+=pad.vy*5;
t=crashTo(Target);
if (t) {
//----- ★D
$score+=1;
if ($score>=10) {
$state="clear";
break;
}
//------
t.die();
}
e=crashTo(Enemy);
if (e) {
$state="gameover";//★E
die();
}
update();
}
- ★Dでは,ターゲットに触れたときにスコアを増やす処理を追加しています.また,スコアが10になったらクリアということにして,
$state
に"clear"
を設定しています.また,break;
によってメインループを抜け出し,プレイヤーが停止するようにします.3 - ★Eでは,敵にあたったときに
$state
に"gameover"
を設定しています.
いずれも処理でも$state
が"play"
以外の値になった場合は,先ほどのMain
の★Bの条件が不成立になり,メインループが終了します.
ゲーム終了の処理
ここで再びMain
に戻り,メインループ後の処理をみていきます.
switch($state) {
case "gameover":
new Label{text="ゲームオーバー",x=230,y=200,size=50};
break;
case "clear":
new Label{text="クリア",x=230,y=200,size=50};
break;
}
new Button{
text="Title",
top=300,
onClick=goTitle,
};
\goTitle() {
new FadeEffect{type="out",page=Title};
}
Tonyu2 でもswitch文が使えます4.$state
の値に応じてラベルを表示しています.
そして,タイトルに戻るボタンを表示しています.このへんの処理は第2回を参照してください.
バリエーション
今回は「ターゲット規定個数取ったらクリア」というものでしたが,他にもクリア条件はあると思います.各自変更してみてください.
- 一定時間耐えたらクリア(時間内に取った個数を競う)
- 青天井(敵に当たるまでずっと.敵がだんだん速くなるとか.あとターゲットを逃したらだめ,とか)
今回はここまで.この後ももう少し続きます.
第26回あほげーまであと約1か月です.次回は7周年だったり,スポンサーイベントだったりするらしいので楽しみにしています.
-
スコアや経過時間に応じて敵が強くなったりする場合,Enemyクラスから
$score
や$time
を参照することがあるでしょう. ↩ -
本プロジェクトではフレームレートは30になっていますが,Tonyu System2の開発環境から「新規作成」で作成したプロジェクトでは,デフォルトのフレームレートは60になります(Ver 2018-0427以降).変更したい場合は最初に
$Boot.setFrameRate(30);
のように書いてください. ↩ -
クリア後も動けたっていいんですが,敵にあたると消えてしまうので「クリアしたのにやられた!」みたいなことにならないようにするためです(それはそれでいい味という説も).敵が動き続けるのが気になる方は,
Enemy
のメインループにおいて「$state
が"play"
の間だけ繰り返す」ようにしておくとよいでしょう. ↩ -
前バージョンのTonyu System(Tonyu1)ではswitch使えなかったのです... ↩