11. ミニゲーム(フリーモード)

1.0.3 から、ノベルゲームの選択肢からミニゲームへ進み、結果(クリア・失敗)で会話を分けられるようになりました。 制作者が自分のミニゲームを作れます。

ADV・ノベルの会話の途中で、 2D のミニゲーム (神経衰弱・3 つ並べ・反射と連打のような短い遊び)を遊ばせる方法です。 ミニゲームは システムスクリプト で作り、 シナリオ から呼び出して、結果(クリア・失敗)で会話を分けます。

まず見本を遊んでみましょう。
lumina.exe を起動し、タイトルの「はじめから」で始まる紹介デモ( data0\scenario\feature_demo.txt )の選択肢で 「② 応用サンプル」→(次のページへ)→ 5 ページ目の「21. ミニゲーム(神経衰弱・3 つ並べ・反射)」を選ぶと、 ミニゲームの見本 data0\scenario\mg_sample.txt の会話が始まります。楓の「どれから遊ぶ?」の選択肢で、神経衰弱・3 つ並べ・反射と連打のどれかを選んで遊びます。 遊び終わると紹介デモへ戻ります。
Windows / ブラウザ / Android で同じように動きます。マウス・指・キー(パッド)で遊べます。

11.1 しくみ

役 書く場所 すること
シナリオ data0\scenario\*.txt g2d_run でミニゲームを動かし、 g2d_event_is で返ってきたイベント( clear など)を見て分ける
ミニゲームのスクリプト data0\system\*.txt Game2D.begin(…, "free") で始め、絵・文字を置き、 Game2D.run で実行してイベントに応える。終わりに Game2D.setResult で結果を返す
絵・効果音・表 data4\game2d ・ data0\game2d ・ data5\se ・ data0\table スプライトシート(1 枚の絵に並べた絵と、その切り出しの定義)、効果音、難しさなどの表

11.2 いちばん小さな例

マスを 3 つとも押すとクリアになるミニゲームです。 data0\system\MyFree.txt として保存します。

// @lumina
function MyBuild() {
    if (Game2D.begin(1280, 720, 60, "free") == 0) { return 0; }
    Game2D.loadAtlas("cards", "data4/game2d/mg_cards");      // スプライトシート(定義は data0/game2d/mg_cards.txt)
    for (var i = 0; i < 3; i = i + 1) {
        Game2D.addSprite("c" + i, "cards:back_f", 400 + i * 240, 360, 1);   // (名前, "シート:絵", x, y, 層)
        Game2D.setSprite("c" + i, "hit", 1);                   // 押せるようにする → イベント "tap:c0" など
    }
    Game2D.addText("title", "3 枚とも押す", 40, 24, 30, "#FFFFFF", 5);
    Game2D.on("tap:*", "score 10; return");                     // このイベントが来たらスクリプトへ戻る
    Game2D.attach(5);                                           // レイヤ 5 にゲームの画面を出す
    return 1;
}
if (MyBuild() == 1) {
    GameState.set("my_lit", 0);
    while (1) {
        var ev = Game2D.run(0);                                 // イベントが来るまで遊ばせる
        if (ev.indexOf("tap:") == 0) {
            var id = ev.substring(4);
            Game2D.setSprite(id, "hit", 0);
            Game2D.tween(id, "rgb=#60E090; scale=1.12", 0.2, "out_back");
            GameState.add("my_lit", 1);                          // 数は GameState に持つ(11.7)
            if (GameState.get("my_lit") >= 3) { Game2D.setResult("clear"); break; }
        } else { Game2D.setResult(ev); break; }                  // pause・cancel など
    }
}

シナリオでは、会話の選択肢で選んだ後に呼びます(見本の mg_sample.txt も、楓の「どれから遊ぶ?」の選択肢から 3 本のどれかへ進みます)。

name 楓
	「ミニゲームで遊んでいく?」
select "遊ぶ" *play "やめておく" *next
*play
g2d_run MyFree ev
g2d_event_is "clear" *won
	だめだったね。
g2d_end
jump *next
*won
	クリア!
g2d_end
*next

ふつうのシナリオと同じく、タイトルの「はじめから」→ 会話 → 選択肢 → ミニゲーム → 会話に戻る、という流れで遊ばれます。特別な起動のしかたは要りません。

11.3 シナリオの命令(13 個)

命令 内容
g2d_run スクリプト [変数] ミニゲームを動かす。結果の番号を変数へ
g2d_resume [変数] [最大ミリ秒] 途中の会話のあと、遊んでいたミニゲームを続きから動かす( g2d_run の後・ g2d_end の前)
g2d_end ミニゲームを終え、画面を外す
g2d_event_is "イベント" *ラベル 最後に返ったイベントの名前が同じならラベルへ。末尾の * は前方一致( "mg:*" )
gs_set 名前 値 ・ gs_add 名前 [数] ・ gs_get 名前 変数 GameState(ミニゲームとシナリオで共有する値。セーブに入る)を書く・足す・読む
gs_if "式" *ラベル GameState の式( "a == 1" ・ "a > 0 && b < 3" )が真ならラベルへ
table_get 表 行 列 変数 data0\table の表のセルの値を変数へ。変数を gs:名前 と書くと GameState へ
g2d_grid_get グリッド x y 変数 ・ g2d_grid_set グリッド x y 値 グリッド( Grid )のマスを読む・書く
g2d_list_get リスト 位置 変数 ・ g2d_list_size リスト 変数 リスト( List )の要素・数を読む

シナリオの変数は整数だけなので、文字の値は gs:名前 で GameState に受けて gs_if で比べます。

11.4 システムスクリプトの関数

開始・実行・結果

関数 内容
Game2D.begin(幅, 高さ, 60, "free") ・ end() ・ isActive() フリーモードを始める(1 / 0)・終える・始まっているか
Game2D.attach(レイヤ) ・ detach() ・ setClearColor(色) ゲームの画面を ADV のレイヤに出す・外す・背景色
Game2D.on(イベント, 動作) イベントに動作を付ける。動作は return (スクリプトへ戻る)・ score 数 ・ add 名前 数 ・ flag 名前 値 ・ sound 名前 ・ hitstop ミリ秒 ・ slow 率 ミリ秒 を ; でつなぐ。 "tap:*" のように * も使える
Game2D.run(最大ミリ秒) 戻るイベントが来るまで遊ばせ、その名前を返す(0 は上限なし)
Game2D.setResult(イベント) ・ lastResult() ・ resultCode() シナリオへ返す結果( "clear" ・ "defeat" ・ "cancel" など)
Game2D.addTimer(名前, 秒, くり返し) ・ pushEvent(名前) ・ elapsed() タイマー(鳴るとイベント 名前 )・自分でイベントを出す・ゲームの経過時間(秒)
Game2D.score() ・ setSeed(シード) ・ canSave() ・ worldKind() スコア・乱数のシード・いまセーブしてよいか・2D のモードの種類( "free" )

スプライト(置く・動かす)

関数 内容
Game2D.loadAtlas(名前, "data4/game2d/…") スプライトシートを読む(定義は data0\game2d の同じ名前の .txt)
addSprite(名前, "シート:絵", x, y [, 層]) ・ addText(名前, 文, x, y [, 大きさ [, 色 [, 層]]]) ・ addRect(名前, x, y, w, h [, 色 [, 不透明度 [, 層]]]) 絵・文字・四角を置く(4,096 個まで。層 0〜99、大きいほど手前。文字は "\n" で改行)
setSprite(名前, 値の名前, 値) ・ sprite(名前, 値の名前) 値を変える・読む。値の名前は x y scale scalex scaley rot alpha rgb w h visible anim flipx flipy layer hit text size pivotx pivoty
removeSprite(名前) ・ clearSprites() ・ spriteCount() ・ spriteAt(x, y) 消す・全部消す・数・その場所の押せる物の名前
tween(名前, "x=640; alpha=0", 秒 [, イージング [, イベント]]) ・ stopTween(名前) ・ isTweening(名前) 時間をかけて値を変える(終わると "tween:名前" )。イージングは linear in_quad out_quad in_out_quad in_cubic out_cubic in_out_cubic in_back out_back out_bounce out_elastic step
flash(名前, 秒 [, 1 回の秒]) 点滅(終わると "flash:名前" )

指・マウス・キー

画面の部品・音・時間

関数 内容
addGauge(名前, x, y, w, h, 値の名前, 最大 [, 色 [, 背景色]]) ・ setGauge ・ removeGauge ゲージ。値は GameState の名前
message(文) メッセージウィンドウ(閉じると "message:done" 。 "\n" で改行)
choose("a,b,c", GameState の名前) 選択肢の一覧(選んだ番号 1〜・やめると 0 を入れて "choose:名前" )
notice(文 [, 秒]) ・ fade(1 / 0, ミリ秒 [, 色]) ・ wipe(形, 1 / 0, ミリ秒 [, 色]) 通知・フェード・ワイプ
preloadSe(名前, パス) ・ setSeGate(…) ・ playSe(名前 [, 音量 [, 左右]]) ・ setSeDistance(近い, 遠い) 効果音
playBgm(パス [, フェードのミリ秒]) ・ stopBgm([ミリ秒]) ・ currentBgm() ・ bgmPosition() BGM(シナリオの bgm と同じ曲のパス。同じ曲なら何もしない)
setTimeScale(率) ・ timeScale() ・ hitStop(ミリ秒) ・ shake(ミリ秒, ピクセル) ゲームの速さ(0.1〜4)・一瞬止める・画面を揺らす

イベント( message:done ・ choose:名前 ・ tween:名前 ・ key:* ・タイマー)も、 on を付けた物だけが戻ります。

11.5 グリッド・リスト・表・GameState

11.6 途中の会話とセーブ

11.7 つまずきやすい所

11.8 見本のファイル

ファイル 内容
data0\scenario\mg_sample.txt 楓が案内するシナリオ。メニュー → 3 本 → 結果で会話が分かれる → 結末(英語は data0\lang\en\scenario\mg_sample.txt と data0\lang\en.txt の mg.* )
data0\system\MgMemory.txt 神経衰弱(リストを混ぜる・押す・めくる tween・点滅・ゲージ・選択肢の一覧)。矢印と Enter・Space・Z でも遊べる
data0\system\MgMatch3.txt 3 つ並べ(グリッド・ドラッグ・スワイプ・消える・落ちる・連鎖)。枠を動かし決定でつかんで矢印で入れ替えも
data0\system\MgReflex.txt 反射と連打(タイマー・ヒットストップ・スロー・揺れ・ゲージ・連打)
data0\system\MgSave.txt シナリオからセーブ画面を出すためのスクリプト
data0\table\mg_*.txt ・ data0\game2d\mg_*.txt ・ data4\game2d\mg_* ・ data5\se\mg_* 難しさの表・スプライトシートの定義・絵・効果音(曲は data5\sound\rpg_village ・ rpg_cave ・ rpg_battle )
この版で使えない物
シューティング・横スクロールのアクション・RPG・マス目の戦略の 2D のモード( begin の "shmup" ・ "platform" ・ "rpg" ・ "tactics" )、 Rpg.* ・ Tactics.* 、 rpg_ ・ tac_ の命令は入っていません。 begin で "free" 以外を選ぶと 0 が返り、何も始まりません。