Inside KAG3/右クリックサブルーチン作成のヒント

Last-modified: 2016-03-29 (火) 12:03:38

基本的なことは「KAG Systemリファレンス」の「Tips/その他‐右クリックサブルーチンについて」、または「吉里吉里2/KAG3によるノベルゲーム開発」の「右クリックサブルーチンを作ろう」を参照のこと。

セーブ/ロード画面

ロード画面

ハイパーリンクを使ったシンプルなロード画面の例。
ブックマーク名が"(未設定)"だった場合(ブックマークの日付が空文字だった場合でも良い)、ハイパーリンクを作らないようにしている点、linkタグのexp属性でエンティティを使っている点に注目。

; ループカウンタを0にする
[eval exp="tf.i = 0"]
*loop
  ; ブックマーク名を得る
  [eval exp="tf.bookmark = kag.getBookMarkPageName(tf.i)"]
  ; ハイパーリンクを作り、クリックしたらkag.restoreBookMark()を呼び出す
  [link exp="&'kag.restoreBookMark('+tf.i+')'" cond="tf.bookmark != '(未設定)'"]
    ; リンク文字列にブックマーク更新日時&ブックマーク名を使う
    [emb exp="kag.getBookMarkDate(tf.i)"][emb exp="tf.bookmark"]
  ; ハイパーリンクここまで
  [endlink cond="tf.bookmark != '(未設定)'"][r]
  ; 利用可能な栞の数ぶん繰り返す
  [jump target=*loop cond="++tf.i < kag.numBookMarks"]
[s]
  • Config.tjsのrestoreMenu.visibleをfalseにしておく方が良い
  • kag.restoreBookMark()メソッドを呼び出す代わりに、別のラベルにジャンプしてloadタグを実行…でも構わない
  • disablestoreタグ、storeタグでロードが抑制されているかどうかは、kag.canRestore()の戻り値で判断できる
  • kag.getBookMarkDate()は該当する栞がない場合、空文字を返す。空文字だったら"----/--/-- --:--"を表示させるなどして書式を揃えると良い

セーブ画面

ハイパーリンクを使ったシンプルなセーブ画面の例。
基本的にはロード画面の作り方と同じだが、ハイパーリンクを再描画して、最新のセーブデータ一覧が表示されるようにしている点が異なる。

; リンクがクリックされたら、リンク文字列の変更が反映されるよう*redrawに戻って再描画する
*redraw
; メッセージレイヤのクリア
[er]
; ループカウンタを0にする
[eval exp="tf.i = 0"]
*loop
  ; ハイパーリンクを作る(クリックしたらkag.storeBookMark()を呼び出し、*redrawへジャンプ)
  [link target=*redraw exp="&'kag.storeBookMark('+tf.i+')'"]
    ; リンク文字列にブックマーク更新日時&ブックマーク名を使う
    [emb exp="kag.getBookMarkDate(tf.i)"][emb exp="kag.getBookMarkPageName(tf.i)"]
  ; ハイパーリンクここまで
  [endlink][r]
  ; 利用可能な栞の数ぶん繰り返す
  [jump target=*loop cond="++tf.i < kag.numBookMarks"]
[s]
  • Config.tjsのstoreMenu.visibleをfalseにしておく方が良い
  • kag.storeBookMark()メソッドを呼び出す代わりに、別のラベルにジャンプしてsaveタグを実行…でも構わない
  • disablestoreタグ、storeタグでセーブが抑制されているかどうかは、kag.canStore()の戻り値で判断できる
  • kag.getBookMarkDate()は該当する栞がない場合、空文字を返す。空文字だったら"----/--/-- --:--"を表示させるなどして書式を揃えると良い

サムネイル画像の読み込みと表示

準備

ロード/セーブでサムネイル画像を扱うには、予め以下のような作業が必要。

  • Config.tjsのfreeSaveDataModeをfalseに設定する(デフォルト)
  • Config.tjsのsaveThumbnailをtrueに設定する
  • 右クリックサブルーチン内で栞をはさむ場合、事前にlocksnapshotタグを実行しておく。なお、locksnapshotを実行した場合、栞をはさみ終えたらunlocksnapshotタグを実行しておく必要がある

サムネイル画像の読み込み~表示

例えば、背景レイヤ表画面に全てのサムネイル画像を追加読み込みするには、以下のようなKAGシナリオファイルになる。

; ※予め以下の配列を用意しておくこと(いずれも要素数はnumBookMarks個必要)
;   tf.x…サムネイル画像の表示X座標
;   tf.y…サムネイル画像の表示Y座標
; 栞の数が10個、画面サイズ640×480時の例(いい加減):
; [eval exp="tf.x = [ 21, 175, 329, 483,  21, 175, 329, 483,  21, 175]"]
; [eval exp="tf.y = [ 45,  45,  45,  45, 189, 189, 189, 189, 333, 333]"]
; ループカウンタを0にする
[eval exp="tf.i = 0"]
*loop
  ; ブックマーク名が"(未設定)"以外なら…
  [if exp="kag.getBookMarkPageName(tf.i) != '(未設定)'"]
    ; ローカルストレージ名を得る
    [eval exp="tf.st = kag.getBookMarkFileNameAtNum(tf.i)"]
    ; サムネイル画像を背景レイヤ表画面に追加読み込み
    [pimage storage="&tf.st" layer=base page=fore dx="&tf.x[tf.i]" dy="&tf.y[tf.i]"]
  [endif]
  ; 利用可能な栞の数ぶん繰り返す
  [jump target=*loop cond="++tf.i < kag.numBookMarks"]
[s]

栞が存在するかどうか、事前にkag.getBookMarkPageName()の戻り値が"(未設定)"以外であることをチェックしておく必要がある(kag.getBookMarkDate()の戻り値でチェックしても良い)。

後は、以下のような処理を追加すれば、基本的な形が整う。

  • サムネイル画像上に「透明な」グラフィカルボタンを置き、クリックしたらロード/セーブさせる(事前に「透明な」メッセージレイヤを置くことを忘れずに)
  • クリッカブルマップ(上記サンプルでは背景レイヤ表画面に)を用意し、サムネイル画像部分をクリックしたらロード/セーブさせる

補足

小技にグラフィカルボタンでサムネイル画像を描画する方法を説明しているので、参照されたい。

書き込み保護

num が書き込み保護されているか否かは、メンバ変数kag.bookMarkProtectedStates[num]で調べることができる。

num に書き込み保護フラグを設定するには、メソッドkag.setBookMarkProtectedState()を呼び出す。

ダウンロード

  • filesimple_rclick.lzh…ハイパーリンクを使ったシンプルな右クリックサブルーチン(セーブ/ロードのみ)
  • filesimple_rclick2.lzh…↑の改造版。ハイパーリンク上にマウスを置いたらサムネイル画像を表示
  • filesimple_rclick3.zip…↑の更に改造版。ページ切り替え対応

各種設定

ウィンドウ/フルスクリーン切り替え

ハイパーリンクを使ったシンプルなウィンドウ/フルスクリーン切り替えの例を示す(現実的にはクリッカブルマップや自作オプションボタンを使った方が良い)。
ウィンドウ画面の場合は「フルスクリーン」の、フルスクリーンの場合は「ウィンドウ」のハイパーリンクを有効にしている点に注目。

[link exp="kag.onWindowedMenuItemClick(kag)" cond="kag.fullScreen"]
  ウィンドウ
[endlink cond="kag.fullScreen"][r]
[link exp="kag.onFullScreenMenuItemClick(kag)" cond="!kag.fullScreen"]
  フルスクリーン
[endlink cond="!kag.fullScreen"][s]

ウィンドウの状態(kag.fullScreen)はシステム変数に記録されているため、ウィンドウの状態を変更するだけで、次回起動時でも最新の状態に復元される。

  • Config.tjsのdisplayMenu.visibleをfalseにしておく方が良い

未読部分

  • Config.tjsのcharacterMenu.visibleをfalseにしておく方が良い

文字表示速度

[文字表示‐表示速度]メニューのイベントハンドラを呼び出す場合は、例えば以下のようになる。

; 文字表示速度を「ノーウェイト」に変更
[link exp="kag.onChSpeedMenuItemClick(kag.chNoWaitMenuItem)"]ノーウェイト[endlink][r]
; 文字表示速度を「高速」に変更
[link exp="kag.onChSpeedMenuItemClick(kag.chFastMenuItem)"]高速[endlink][r]
; 文字表示速度を「普通」に変更
[link exp="kag.onChSpeedMenuItemClick(kag.chNormalMenuItem)"]普通[endlink][r]
; 文字表示速度を「遅い」に変更
[link exp="kag.onChSpeedMenuItemClick(kag.chSlowMenuItem)"]遅い[endlink][s]

直接kag.userChSpeedを変更する場合は、例えば以下のようになる。
任意の値が設定できる反面、[文字表示‐表示速度]メニューのチェックと同期しないため、[文字表示‐表示速度]メニューを外すなどの対処が必要になる。

; 文字表示速度を「ノーウェイト」に変更
[eval exp="kag.userChSpeed = 0"]
 (中略)
; 文字表示速度を「高速」と「普通」の中間に変更(任意の整数値を直接代入しても良い)
[eval exp="kag.userChSpeed = (kag.chSpeeds.fast+kag.chSpeeds.normal)\2"]

どちらの方法を採ったとしても、右クリックサブルーチンを抜ける直前、具体的にはtemploadタグとreturnタグの間に、以下のタグを置く必要がある。

; デフォルトの文字表示速度で文字表示しているなら、直ちに設定を反映する
[delay speed=user cond="kag.chUserMode"]

ページ末まで一気に

未読部分をページ待つまで一気に読むか否かを保持しているメンバ変数はkag.chNonStopToPageBreakなので、この値を参照する(ページ末まで読み進むなら真、そうでなければ偽)。

なお、この値を変更する場合は、メソッドkag.onChNonStopToPageBreakItemClick()を呼び出した方が無難。

既読部分

  • Config.tjsのcharacterMenu.visibleをfalseにしておく方が良い

文字表示速度

[文字表示‐一度読んだところは]メニューのイベントハンドラを呼び出す場合は、例えば以下のようになる。

; 既読文字表示速度を「ノーウェイト」に変更
[link exp="kag.onCh2ndSpeedMenuItemClick(kag.ch2ndNoWaitMenuItem)"]ノーウェイト[endlink][r]
; 既読文字表示速度を「高速」に変更
[link exp="kag.onCh2ndSpeedMenuItemClick(kag.ch2ndFastMenuItem)"]高速[endlink][r]
; 既読文字表示速度を「普通」に変更
[link exp="kag.onCh2ndSpeedMenuItemClick(kag.ch2ndNormalMenuItem)"]普通[endlink][r]
; 既読文字表示速度を「変えない」に変更
[link exp="kag.onCh2ndSpeedMenuItemClick(kag.ch2ndNoChangeMenuItem)"]変えない[endlink][s]

直接kag.userCh2ndSpeedを変更する場合は、例えば以下のようになる。
任意の値が設定できる反面、[文字表示‐一度読んだところは]メニューのチェックと同期しないため、[文字表示‐一度読んだところは]メニューを外すなどの対処が必要になる。

; 既読文字表示速度を「ノーウェイト」に変更
[eval exp="kag.userCh2ndSpeed = 0"]
 (中略)
; 既読文字表示速度を「高速」と「普通」の中間に変更(任意の整数値を直接代入しても良い)
[eval exp="kag.userCh2ndSpeed = (kag.chSpeeds.fast+kag.chSpeeds.normal)\2"]
 (中略)
; 既読文字表示速度を「変えない」に変更
[eval exp="kag.userCh2ndSpeed = -1"]

ページ末まで一気に

既読部分をページ待つまで一気に読むか否かを保持しているメンバ変数はkag.ch2ndNonStopToPageBreakなので、この値を参照する(ページ末まで読み進むなら真、そうでなければ偽)。

なお、この値を変更する場合は、メソッドkag.onCh2ndNonStopToPageBreakItemClick()を呼び出した方が無難。

自動的に読み進むウェイト

自動的に読み進むウェイトを変更する方法は、例えば以下のようになる。

; 自動的に読み進むウェイトを「短い」に変更する
[link exp="kag.onAutoModeWaitMenuClick(kag.autoModeFastMenuItem)"]短い[endlink][r]
; 自動的に読み進むウェイトを「やや短い」に変更する
[link exp="kag.onAutoModeWaitMenuClick(kag.autoModeFasterMenuItem)"]やや短い[endlink][r]
; 自動的に読み進むウェイトを「普通」に変更する
[link exp="kag.onAutoModeWaitMenuClick(kag.autoModeMediumMenuItem)"]普通[endlink][r]
; 自動的に読み進むウェイトを「やや長い」に変更する
[link exp="kag.onAutoModeWaitMenuClick(kag.autoModeSlowerMenuItem)"]やや長い[endlink][r]
; 自動的に読み進むウェイトを「長い」に変更する
[link exp="kag.onAutoModeWaitMenuClick(kag.autoModeSlowMenuItem)"]長い[endlink][s]

直接kag.autoModeLineWait、kag.autoModePageWaitを変更する場合は、例えば以下のようになる。
任意の値が設定できる反面、[自動的に読み進む]のメニュー項目と同期しなくなるため、[自動的に読み進む]メニューごと外すなどの対処が必要になる。

; 自動的に読み進むウェイトを「短い」と「やや短い」の中間に変更(任意の整数値を直接代入しても良い)
[eval exp="kag.autoModeLineWait = (kag.autoModeLineWaits.fast+kag.autoModeLineWaits.faster)\2"]
[eval exp="kag.autoModePageWait = (kag.autoModePageWaits.fast+kag.autoModePageWaits.faster)\2"]

BGM・SE・ムービー

BGM

  • 大域音量の参照…kag.bgm.currentBuffer.volume2\1000で求められる
  • 大域音量の設定…bgmoptタグかkag.bgm.setOptions()メソッドを介した方が無難

SE

  • 大域音量の参照…kag.se[n].volume2\1000で求められる(nは効果音バッファ番号)
  • 大域音量の設定…seoptタグかkag.se[n].setOptions()メソッドを介した方が無難

ムービー

ムービーは音量のみで、大域音量がないことに注意。また、音量が変更できるのは、レイヤ描画モードで、かつオーディオストリーム数が1以上のMPEGファイルに限られている。

  • 音量の参照…kag.movies[n].audioVolume\1000で求められる(nはムービーオブジェクト番号)
  • 音量の設定…videoタグかkag.movies[n].setOptions()メソッドを介した方が無難

ムービーの音量はtempsaveタグの記録対象となっており、右クリックサブルーチン内で音量を変更しても、temploadタグを呼び出せば元に戻される。
代替案としては、

  1. システム変数(仮にsf.movie_volumeとしておく;ムービーオブジェクトが複数ある場合は配列を使う)を音量に見立て、初期値として100を代入しておく
  2. 右クリックサブルーチン内ではsf.movie_volumeの値を変更させる
  3. videoタグのvolume属性値では常に"&sf.movie_volume"を指定する。videoタグのラッパーマクロを作っておき、それのみ使うようにする

といった対処が考えられる。