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 枚の絵に並べた絵と、その切り出しの定義)、効果音、難しさなどの表 |
-
ミニゲームは「
フリーモード
」(
Game2D.beginの 4 つ目の引数"free")で作ります。決まった遊び方の無いモードで、スクリプトが置いた物(絵・文字・四角)を、イベント(押した・タイマーが鳴った・動きが終わった など)に応えて動かします。 - 毎フレームの動き(動かす・点滅・アニメ・押した所の判定・タイマー)はエンジンがします。スクリプトは「画面を作る」と「イベントに応える」だけです。
- この版で使える 2D のモードはフリーモードだけです。環境変数などの設定は要りません。作品のリリース(ReleaseBuilder で作る配布物)でもそのまま動きます。
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
ふつうのシナリオと同じく、タイトルの「はじめから」→ 会話 → 選択肢 → ミニゲーム → 会話に戻る、という流れで遊ばれます。特別な起動のしかたは要りません。
-
g2d_run スクリプト 変数はsystem/スクリプトを動かし、結果の番号(0 やめた・1 クリア・2 失敗・3 ほか)を変数へ入れます。返したイベントの名前はg2d_event_isで見ます。 -
終わったら
g2d_endでゲームの画面を外します。 -
イベントは
Game2D.onを付けた物だけがスクリプトへ戻ります (on("tap:*", "return")のように。付けなければ戻りません)。
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:名前"
)
|
指・マウス・キー
-
setSprite(名前, "hit", 1)の物を押すとイベント"tap:名前"、長押しすると"longpress:名前"、ドラッグすると"drag:名前"、離すと"drop:名前"、スワイプすると"swipe:left"・right・up・downが出ます。スワイプを始めた物はGame2D.swipeFrom()。 -
関数:
pointerX()・pointerY()・pointerDown()・pointerPressed()・pointerReleased()・pointerHeld()・pointerCount()・setPointerParam(名前, 値)(判定の値tap_move long_press swipe_min swipe_time drag_start)。 -
キー・パッド: イベント
"key:up"・down・left・right・confirm・jumpなど(押した時に 1 回。上下左右は押し続けると繰り返す)。押しているかはGame2D.keyHeld("confirm")。割り当てはgetKey・setKey・keyName・resetKeys、タッチ操作用のパッドの表示はsetTouchPad(0 / 1)。 -
Z キー・パッドの A は 1 回で
key:confirmとkey:jumpの両方が出ます。 両方を受けるときは、同じ時間(Game2D.elapsed())の 2 つ目を捨てます(見本MgReflex.txtの書き方)。
画面の部品・音・時間
| 関数 | 内容 |
|---|---|
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
-
グリッド
Grid.*(マスごとに整数を持つ表。1〜256 四方・64 個まで):createremovehaswidthheightgetsetfillrandomFillcountfindLines(縦・横に同じ値が並んだマス)removeLineslastCellscollapse(落とす)rotatefloodswaptoTextfromTextsetSeed。 -
リスト
List.*(文字列のリスト。4,096 個まで):createremovehassizeatsetpushpopinsertremoveAtindexOfshufflemovecleartoTextfromTextsetSeed。 -
グリッド・リストは
ミニゲームの外(ADV の上)でも
使えます。ミニゲームが結果をグリッドやリストに残し、シナリオが
g2d_grid_get・g2d_list_sizeで読む形にできます。中身と乱数はセーブに入ります。 -
表
Table.*:loadrowCountcolumnCountfindRowgetIntgetFloatgetStr(data0\tableの表)。 -
GameState
GameState.*:setgetgetStraddhasremoveclear(セーブに入る値)、setPersistgetPersistaddPersistmaxPersist(作品全体に残る整数。ハイスコアなど)。
11.6 途中の会話とセーブ
-
ミニゲームの途中で会話をはさむときは、スクリプトが
Game2D.setResult("mg:half")のようなイベントを返してシナリオへ戻り、会話の後にシナリオがg2d_resume evで続きを動かします。 -
会話の間(
g2d_runの後・g2d_endの前でゲームを実行していない間)はセーブできます。ロードすると、ミニゲームのスクリプトが最初から実行し直され(グリッド・リスト・GameState はロードした中身のまま)、続きから遊べます。画面を作る所では GameState を書き換えない(「はじめ」の値は GameState が無いときだけ入れる)のがこつです。 -
メッセージウィンドウ・選択肢の一覧が開いている間はセーブしません(
Game2D.canSave()が 0)。
11.7 つまずきやすい所
-
関数の中から外の
varに代入しても、外の値は変わりません。 回数や段階は GameState に持つか、関数が値を返す形にします。 -
配列
a[i] = xは使えません。 リスト・グリッドはList.*・Grid.*で持ちます。 -
イベントは
onを付けないと戻りません。 -
同じ瞬間に戻るイベントが 2 つ以上あると、2 つ目からは次の
Game2D.runの頭で順に返ります。
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 が返り、何も始まりません。