実録!クソゲーの作り方!
お盆にクソゲーを作ったので制作中に考えたこととかを記事にまとめました。
きっかけ
環境とかについて
制作ツールはRPGツクールMZを使いました。ちなみにつくるのはRPGではありませんメッフィーとミッフィーを振り分けるだけのクソゲーです。
ミッフィーは世界的に有名なうさぎさんです。メッフィーはわたくしの愛読するWeb漫画『胎界主』(http://www.taikaisyu.com/)の名物キャラクターの愛称であります。胎界主を読め。
この紳士がメフィストフェレス陛下です
最初にざっくりと仕様とか要件を決めた
最初に決めた方針は以下のようなものでした
1.ランダムに表示されるメッフィーとミッフィーを左右に振り分けるゲームにする
2.気軽に遊んで貰いやすいようブラウザ上で動作することを前提にする(ダウンロードやインストールが不要)
3.画像が表示される時間をだんだん短くして一応のゲーム性をだす
4.稀に無関係な画像を出して笑いを誘う
5.イベント作成の勉強も兼ねてなるべくイベントコマンドで完結するように作る
作ってみた
イベントはメインのイベントとリアルタイムに入力を拾うための並列処理コモンイベントを組み合わせて作成しました。
◆文章:なし, People3(0), ウィンドウ, 下
: :これから貴様には『メ』と『ミ』を仕分けしてもらう
: :『メ』は右『ミ』は左だ
: :わかったか?
◆選択肢の表示:わかった, すンごくよくわかった, 今はまだわからない (ウィンドウ, 右, #1, #2)
:わかったのとき
◆文章:なし, People3(0), ウィンドウ, 下
: :よかろう
: :ちなみによくわからないモノが見えたときは
: :スルーするのが正解じゃ
: :お前は何も見なかった、そういう事じゃ。
◆文章:なし, People3(0), ウィンドウ, 下
: :ではゆくぞ
◆ピクチャの表示:#11, _Right, 中央 (736,496), (100%,100%), 255, 通常
◆ピクチャの表示:#12, _Left, 中央 (80,496), (100%,100%), 255, 通常
◆プラグインコマンド:PictureCrossKey, ピクチャーにキーを割り当てる
: :キーの名称 = right
: :ピクチャーの番号 = 11
: :アニメーションID = 125
◆プラグインコマンド:PictureCrossKey, ピクチャーにキーを割り当てる
: :キーの名称 = left
: :ピクチャーの番号 = 12
: :アニメーションID = 125
◆変数の操作:#0001 スコア記録用 = 0
◆変数の操作:#0003 回答 = -1
◆変数の操作:#0004 回答猶予時間設定 = 300
◆変数の操作:#0005 回答猶予減少量 = 1
◆変数の操作:#0006 最短回答猶予 = 30
◆変数の操作:#0011 スコアX座標 = 704
◆変数の操作:#0012 スコアY座標 = 544
◆変数の操作:#0013 スコアX座標補正値 = 0
◆変数の操作:#0015 残り時間描画用控え = 0
◆変数の操作:#0016 スコア基本値 = 15000
◆ウェイト:120フレーム
◆ループ
◆注釈:出題処理
◆ピクチャの消去:#1
◆ウェイト:60フレーム
◆注釈:回答用変数は-1を未回答、0をメ、Ⅰをミとします
◆変数の操作:#0008 レア出現判定 = 乱数 1..1000
◆条件分岐:レア出現判定 ≤ 15
◆変数の操作:#0002 メとミ出題 = -1
◆変数の操作:#0010 はずれ枠抽選 = 乱数 1..13
◆条件分岐:はずれ枠抽選 = 1
◆ピクチャの表示:#1, _body, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 2
◆ピクチャの表示:#1, _fireman, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 3
◆ピクチャの表示:#1, _gasya, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 4
◆ピクチャの表示:#1, _houseman, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 5
◆ピクチャの表示:#1, _manoftower, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 6
◆ピクチャの表示:#1, _marchocias, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 7
◆ピクチャの表示:#1, _mareo, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 8
◆ピクチャの表示:#1, _monky, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 9
◆ピクチャの表示:#1, _niki, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 10
◆ピクチャの表示:#1, _rex, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 11
◆ピクチャの表示:#1, _solomon, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 12
◆ピクチャの表示:#1, _tatiana, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆条件分岐:はずれ枠抽選 = 13
◆ピクチャの表示:#1, _zbb, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆
:それ以外のとき
◆変数の操作:#0002 メとミ出題 = 乱数 0..1
◆条件分岐:メとミ出題 = 0
◆ピクチャの表示:#1, mephi, 中央 (408,312), (100%,100%), 255, 通常
◆
:それ以外のとき
◆ピクチャの表示:#1, miffy, 中央 (408,312), (100%,100%), 255, 通常
◆
:分岐終了
◆
:分岐終了
◆SEの演奏:Bow1 (90, 100, 0)
◆注釈:この辺になんか良い感じでユーザーの入力を受け付けるスクリプト
◆変数の操作:#0007 回答時間カウンター = 回答猶予時間設定
◆変数の操作:#0015 残り時間描画用控え = 回答時間カウンター
◆スイッチの操作:#0001 回答受付中 = ON
◆ループ
◆変数の操作:#0007 回答時間カウンター -= 1
◆条件分岐:回答時間カウンター < 0
◆スイッチの操作:#0001 回答受付中 = OFF
◆ループの中断
◆
:分岐終了
◆条件分岐:残り時間描画用控え ≥ 180
◆プラグインコマンド:TextPicture, テキストピクチャの設定
: :テキスト = 回答時間残り \v[15] fr
◆
:それ以外のとき
◆条件分岐:残り時間描画用控え ≥ 120
◆プラグインコマンド:TextPicture, テキストピクチャの設定
: :テキスト = 回答時間残り \C[17]\v[15] fr
◆
:それ以外のとき
◆条件分岐:残り時間描画用控え ≥ 60
◆プラグインコマンド:TextPicture, テキストピクチャの設定
: :テキスト = 回答時間残り \C[2]\v[15] fr
◆
:それ以外のとき
◆プラグインコマンド:TextPicture, テキストピクチャの設定
: :テキスト = 回答時間残り \C[18]\v[15] fr
◆
:分岐終了
◆
:分岐終了
◆
:分岐終了
◆ピクチャの表示:#3, なし, 左上 (0,592), (100%,100%), 255, 通常
◆変数の操作:#0015 残り時間描画用控え = 回答時間カウンター
◆ウェイト:1フレーム
◆
:以上繰り返し
◆注釈:回答結果を受けての処理
◆条件分岐:回答 = メとミ出題
◆変数の操作:#0009 スコア加算値 = スコア基本値
◆変数の操作:#0009 スコア加算値 /= 回答猶予時間設定
◆条件分岐:スコア加算値 ≤ 1
◆変数の操作:#0009 スコア加算値 = 1
◆
:分岐終了
◆変数の操作:#0001 スコア記録用 += スコア加算値
◆SEの演奏:Flash2 (90, 100, 0)
◆変数の操作:#0013 スコアX座標補正値 = スコア記録用
◆変数の操作:#0014 スコア桁数 = 1
◆ループ
◆変数の操作:#0013 スコアX座標補正値 /= 10
◆条件分岐:スコアX座標補正値 = 0
◆ループの中断
◆
:分岐終了
◆変数の操作:#0014 スコア桁数 += 1
◆
:以上繰り返し
◆変数の操作:#0013 スコアX座標補正値 = スコア桁数
◆変数の操作:#0013 スコアX座標補正値 *= 32
◆変数の操作:#0013 スコアX座標補正値 *= -1
◆変数の操作:#0013 スコアX座標補正値 += スコアX座標
◆プラグインコマンド:TextPicture, テキストピクチャの設定
: :テキスト = スコア:\{\{\{\v[1]
◆ピクチャの表示:#2, なし, 左上 ({スコアX座標補正値},{スコアY座標}), (100%,100%), 255, 通常
◆変数の操作:#0003 回答 = -1
◆変数の操作:#0004 回答猶予時間設定 -= 回答猶予減少量
◆条件分岐:回答猶予時間設定 < 最短回答猶予
◆変数の操作:#0004 回答猶予時間設定 = 最短回答猶予
◆
:分岐終了
◆
:それ以外のとき
◆注釈:不正解の場合
◆SEの演奏:Buzzer1 (90, 100, 0)
◆ループの中断
◆
:分岐終了
◆
:以上繰り返し
◆ピクチャの消去:#11
◆ピクチャの消去:#12
◆画面の色調変更:(34,-34,-68,170), 1フレーム (ウェイト)
◆文章:なし, People3(0), ウィンドウ, 下
: :ご苦労
: :貴様のスコアは\{\v[1]\}じゃ
◆文章:なし, People3(0), ウィンドウ, 下
: :この結果をツイートすることも出来るがどうする?
◆選択肢の表示:ツイートする, やめておく (ウィンドウ, 右, #1, #2)
:ツイートするのとき
◆プラグインコマンド:Tweet, Tweet
: :TweetText = 私はXッフィーを仕分け続けて \v[1] pts.を獲得し…
◆
:やめておくのとき
◆
:分岐終了
◆画面の色調変更:(0,0,0,0), 60フレーム (ウェイト)
◆ピクチャの消去:#1
◆ピクチャの消去:#2
◆ピクチャの消去:#3
◆
:すンごくよくわかったのとき
◆SEの演奏:Blow5 (90, 100, 0)
◆画面のフラッシュ:(255,0,0,170), 15フレーム (ウェイト)
◆文章:なし, People3(0), ウィンドウ, 下
: :なんとなく分かっても
: :すンごくよく分かるわけねーだろが
◆
:今はまだわからないのとき
◆文章:なし, People3(0), ウィンドウ, 下
: :チッ
: :小利口な野郎だ
◆
:分岐終了
これがメインの処理をするイベント(完成品)
◆注釈:キーが押された判定
◆ループ
◆条件分岐:ボタン[右]が押されている
◆スイッチの操作:#0002 右ジャンプ = ON
◆変数の操作:#0003 回答 = 0
◆変数の操作:#0007 回答時間カウンター = 0
◆スイッチの操作:#0001 回答受付中 = OFF
◆ループの中断
◆
:分岐終了
◆条件分岐:ボタン[左]が押されている
◆スイッチの操作:#0003 左ジャンプ = ON
◆変数の操作:#0003 回答 = 1
◆変数の操作:#0007 回答時間カウンター = 0
◆スイッチの操作:#0001 回答受付中 = OFF
◆ループの中断
◆
:分岐終了
◆ウェイト:1フレーム
◆
:以上繰り返し
これが入力を拾ってくるコモンイベント(完成品)
コモンイベントはユーザーが右または左のボタンを押した事を検知してメインのイベントに知らせる役割です。
メインのイベントでは回答の答え合わせを行い正解ならスコアを計算して加算、次の問題の出題へ進みます。不正解ならそこでゲームオーバーです。
問題その一、スマホで操作出来ない問題
ツクールMZの前バージョンにあたるツクールMVがスマホでプレイすると画面上にボタンが勝手に出てくる仕様だったような記憶があったのでMZでも同様と思い込んでいたがそんなことは無かった!
MZはマップをタッチすればそこに向かって勝手にキャラクターが移動するし選択肢のUIを直接タッチすればコマンドが実行されるようになったから画面上にボタンを出す必要が無くなっていたのだ。盲点!
解禁!プラグイン!
なるべくイベントコマンドだけで完結したかったのですがこうなっては仕方ありません。だって、気軽にご笑覧頂きたいのにスマホブラウザでプレイ出来ないというのは致命的です。由々しさMAXですよこいつぁ!
で、ツクールMZには最初から付属しているプラグインが幾つかありましてその中にButtonPictureというおあつらえ向きっぽいのがあったんですな。
これで万事解決か…?
ところがこれはピクチャーをクリックしたときに特定のコモンイベントを起動させるというもので方向キーとかの代替をしてくれる訳じゃ無かったんですよね。
で、試してみてわかったのですが通常のコモンイベントは呼び出されても一旦処理待ちの待機列に追加されて今実行中のイベントが終了するまで待たされる仕組みになってたんです。これではメインのイベント実行中にリアルタイムでユーザーの操作に反応することは出来ません。マイッタネ!
※多分駄目だと思ったので実際には試しませんでしたがコモンイベントの種類を自動か並列処理にしたらひょっとすると動いたのかもしれません
無ければ作るしかねーじゃん!
ちょーメンドクサイですが最早他に手段はありません。書くっきゃ無いのですスクリプトを!
先述のButtonPictureを参考にシステムの中核を成すスクリプト群を読み解いて行きます。Sprite_PictureがどうのGame_Pictureがフンダララだのひたすら地道な作業です。
で、なんやかんやあって実労多分12時間くらいでボタンを追加出来ました。
スクリプトのエディタはVSCodeがオススメ
問題その二、なんか遅い
コングラッチュレーション。君はやり遂げた。ピクチャーで表示させたボタンが期待どおりに反応します。なんて、素晴らしいのかしら…
調子にのって延々テストプレイをする私。どんどんスコアが伸びます。伸び続けます。
…??
伸びすぎでは?
想定を超えて異様に伸びたスコア
なんか異様に簡単です。回答の猶予時間が長すぎる気がしてきました。
仕様上の回答猶予時間は最初は5秒=300フレームで正解する毎に1フレームずつ短くなっていく設計です。でも実際計ってみると一問目の回答猶予時間が15秒近くあります。ナンデダロー???
こういう時は分析ツールです。テストプレイ中にF8押すと分析ツールが起動して色々見れるんですよ知ってました?(私は真面目にヘルプを読んでなかったのでこの時まで知らなかった)
プレイ中のパフォーマンスを計測した結果がこちら
上のほうの緑のグラフがfpsで標準が60のところ回答受付中は毎回fpsが一桁近くまで落ちていました。とりあえず何かの処理がメチャメチャ重いということがわかります。
当初はカウントダウンの文字列を描画する処理が重いのかと考えたりしましたが結果的に原因は別のところにありました。
ユーザーの入力を待ち受けるコモンイベントの方にウェイトをいれ忘れていたんですよね。
ツクールの仕様として、どのボタンが押されているかという状態の更新は原則1フレームに1回だけ行われます。なので、それより高い頻度で状態を問い合わせても状態が変わっているわけは無いので無意味なのですがループの中にウェイトを入れ忘れたため1フレームに何万回でもCPUパワーの許す限り問い合わせを行ってしまい無茶苦茶重かったわけです。つまるところしょーもない凡ミスですわ。
完成!これがクソゲーだ!
とゆーような曲折を経て一応の完成を見たのがこちらです。ご笑覧あれ!
副産物
副産物としてピクチャーにキーを割り当てるスクリプトが出来てしまいました。
※汎用性の低い部分を削ったので実際にゲームに使ったものとは少しだけ違います。
※右クリックから保存してください。直接開くと文字化けして表示されるみたいです。
この記事が気に入ったらサポートをしてみませんか?