トップページへ戻る


デバッグ(CDP/DMS)
 
「きょーわ何やんのかなー?」

「その質問に答える前に、ゲームを制作する側が一番注意しなくちゃいけないことは何だと思う?」

「んー、わかんない」

「いわゆる『バグ』を最小限に抑えることだ」

「ばぐって何かな−?」

「簡単に言えばプログラム上のミスだ。バグがあるとゲームが誤動作したり、途中で進まなくなったりする」

「ふーん」

「一説には、バグはどんなプログラムでも内包していると言われる。バグが発見され、それがどっちとも取れる場合は、『それは製品の仕様です』と言って押し通す業界関係者もいるが、少ないに越したことはない」

「そーだねー」

「そこで、ここでは、吉里吉里/KAGを利用して開発をしていたおいらの体験から、割と起こりやすいバグをいくつか説明して、参考にしてもらおうと思う」

「んでも、あんたのふちゅーいからおきたんじゃないの?」

「そ……それはそうだけど……一例としては参考になるだろう?」

「んまーいーやー」

「まず一番多かったのは、読み込まれるファイルが見つからなかったり、ジャンプ先のラベルが見つからなかったことだな。制作途中だから準備していないことが多かったけど、それを直すのを忘れてそのままリリースしちゃった場合、大変なことになる」

「そりゃそーでしょもー」

(前略)
[s]
;--------------------------------------------
*return_menu
[layopt layer=message0 page=back visible=false]\
[image storage="title.bmp" layer=base page=back]\
[trans rule="trans1" time=2000 vague=100]\
[wt]\
[ct]\
[jump target=*menu]
[s]

「あ、えらいえらい。名前入力画面の所で処理用のラベルを作ってから戻る手法を使ったわけか。そういう応用は大事だよ」

「んでもって、画面はこんなふーになるんだよー」

「なるほどね。通常、セーブデータは画面上部のプルダウンメニュー『栞をたどる』から呼び出せるが、ここでその作業をプレイヤーにさせるのはカッコ悪いし、せっかくだからダミー文字が書かれている画面の中央部分に、ロードさせるセーブデータを表示させてみようか」

「そーしてくんないと、困んもん!」

「実はこの方法を実現するには、KAGではなくTJSを書かないといけない」

「うそー!?」

「でも、すごく簡単だから丸暗記しちゃえばいい」

「ならいーもん!」

「書式についてだが、以下のように書く」

[link exp="kag.restoreBookMark(0)"]\
[emb exp="kag.getBookMarkPageName(0)"]\
[endlink]\

「(0)って?」

「KAGの栞は最大で999個使える。誰もそんなにたくさん使わないと思うけど」

「そりゃそーでしょもー!」

「それぞれの栞には0から998までの番号が与えられている。つまり、一番目の栞をロードするには上のように書けばいいし、2番目の栞の場合は、(0)を(1)に書き換えてやればいい。3番目は(2)、4番目は(3)だ」

「んーと、それじゃー、100こ目の栞は、(99)になるのかなー?」

「そういうことだ。すでに [link][endlink] タグがついているから、そのままこれをスクリプト内に書き込めば、クリックするとセーブデータがロードされるようになる」

「んぢゃー、早速書いてみんもん!」

「そうしてごらん」

*dataload
[ct]\
[layopt layer=message0 page=back visible=false]\
[image storage="cami" layer=base page=back]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
[ct]\
[layopt layer=message0 page=fore visible=false]\
[delay speed=nowait]\
[locate x=40 y=20]再開する栞を選んでください。

[style align=center]\
[link exp="kag.restoreBookMark(0)"]\
[emb exp="kag.getBookMarkPageName(0)"]\
[endlink]\
[link exp="kag.restoreBookMark(1)"]\
[emb exp="kag.getBookMarkPageName(1)"]\
[endlink]\
[link exp="kag.restoreBookMark(2)"]\
[emb exp="kag.getBookMarkPageName(2)"]\
[endlink]\
[link exp="kag.restoreBookMark(3)"]\
[emb exp="kag.getBookMarkPageName(3)"]\
[endlink]\
[link exp="kag.restoreBookMark(4)"]\
[emb exp="kag.getBookMarkPageName(4)"]\
[endlink]\
[style align=default]\

[locate x=400 y=360][link target=*return_menu]メニューに戻る[endlink]\
[delay speed=user]\
[backlay]\
[layopt layer=message0 page=back visible=true]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
[s]
;--------------------------------------------
*return_menu
[layopt layer=message0 page=back visible=false]\
[image storage="title.bmp" layer=base page=back]\
[trans rule="trans1" time=2000 vague=100]\
[wt]\
[ct]\
[jump target=*menu]
[s]

「ちゃーんと [style] でレンダリングしたもんねー!」

「センタリングだってば……」

「いーぢゃんよもー!」

「とにかく実行させてごらん」

「いけー!」

「んきゃー!?」

「当たり前だろ。全部の [endlink] の末尾に¥マークを書いているんだから」

「直すもん! ついでに場所もきちんとして、色なんかつけちゃうもん!」

*dataload
[ct]\
[layopt layer=message0 page=back visible=false]\
[image storage="cami" layer=base page=back]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
[ct]\
[layopt layer=message0 page=fore visible=false]\
[delay speed=nowait]\
[locate x=40 y=20]再開する栞を選んでください。

[font color=0xff0080]\
[locate y=100]

[style align=center]\
[link exp="kag.restoreBookMark(0)"]\
[emb exp="kag.getBookMarkPageName(0)"]\
[endlink]
[link exp="kag.restoreBookMark(1)"]\
[emb exp="kag.getBookMarkPageName(1)"]\
[endlink]
[link exp="kag.restoreBookMark(2)"]\
[emb exp="kag.getBookMarkPageName(2)"]\
[endlink]
[link exp="kag.restoreBookMark(3)"]\
[emb exp="kag.getBookMarkPageName(3)"]\
[endlink]
[link exp="kag.restoreBookMark(4)"]\
[emb exp="kag.getBookMarkPageName(4)"]\
[endlink]
[style align=default]\
[font color=default]\

[locate x=400 y=360][link target=*return_menu]メニューに戻る[endlink]\
[delay speed=user]\
[backlay]\
[layopt layer=message0 page=back visible=true]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
[s]
;--------------------------------------------
*return_menu
[layopt layer=message0 page=back visible=false]\
[image storage="title.bmp" layer=base page=back]\
[trans rule="trans1" time=2000 vague=100]\
[wt]\
[ct]\
[jump target=*menu]
[s]

「いけー!」

「だいたいおっけーかなー?」

「そうだな。あと、細かい文字の配置については [locate] を使って直せばOKだ」

「うーん……」

「ん? 何見てんだ?」

「んでもなー」

「んでも、何だ?」

「マウスが上に来た時の色が変なんだよねー。もっといー色に変えたいなー」

「それじゃ、変えてごらんよ。前に勉強した [font color=0x16進数] と同じ要領で [link] タグも色をつけられるから」

「ほんとー!? それぢゃーたとえば、選択肢の種類によって色をいろいろつけられんのかなー!?」

「もちろんできる。そういう、ユーザーに歓喜の涙を流させる細やかな自由度がKAGの魅力……あれ? 以前にも同じことを言ったような気が……」

「さっそくやってみんもん!」

(前略)
[locate x=40 y=20]再開する栞を選んでください。

[font color=0xff0080]\
[locate y=100]
[style align=center]\
[link exp="kag.restoreBookMark(0)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(0)"]\
[endlink]
[link exp="kag.restoreBookMark(1)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(1)"]\
[endlink]
[link exp="kag.restoreBookMark(2)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(2)"]\
[endlink]
[link exp="kag.restoreBookMark(3)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(3)"]\
[endlink]
[link exp="kag.restoreBookMark(4)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(4)"]\
[endlink]
[style align=default]\
[font color=default]\

[locate x=400 y=360][link target=*return_menu]メニューに戻る[endlink]\
(以下略)

「白っぽーい四角にしてみたもん」

「実行してごらん」

「うん。白っぽくなってるねー」

「それじゃ、それはその辺にして、次はゲームを終了させるスクリプトを書こう」

「それぢゃー、スクリプトは、メインメニューのやつを使うんだね?」

「そうだ」

;--------------------------------------------
*end
[ct]\
おしまい。
[s]

「ここだっけっかなー?」

「いや、そのラベルは必要ない。ざっくり消しちゃっていいぞ」

「うそー!? なんでー!?」

「ゲームを終了させるスクリプトは一行で書ける。書く場所は下の黄色の部分だ」

[title name="タイトル"]\
[wc time=20]\
*start|スタート
[playbgm storage="title"]\
[layopt layer=message0 page=fore visible=false]\
[image storage="title" page=back layer=base]\
[backlay layer=message0]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
[ct]\
[backlay]\
[layopt layer=message0 page=back visible=true]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
[locate y=300]\
[delay speed=nowait]\
[style align=center]\
[link target=*opening]  ゲームをはじめる  [endlink]
[link target=*dataload]セーブデータをロードする[endlink]
[link target=*option]    オプション    [endlink]
[link target=*end]  ゲームを終了する  [endlink]\
[style align=default]\
[delay speed=user]\
[s]
;--------------------------------------------
*opening
[ct]\
(4日目の内容を参照)
[s]
;--------------------------------------------
*dataload
[ct]\
(別項参照)
[s]
;--------------------------------------------
*return_menu
[layopt layer=message0 page=back visible=false]\
[image storage="title.bmp" layer=base page=back]\
[trans rule="trans1" time=2000 vague=100]\
[wt]\
[ct]\
[jump target=*menu]
[s]
;--------------------------------------------
*option
[ct]\
おぷしょんぺーじだもん。
[s]
;--------------------------------------------
*end
[ct]\
おしまい。
[s]

「今のままだと、『*end』というラベルにジャンプしてから終了処理をするようになっているが、その必要はない」

「どーやんのかなー!」

「こんなふうに直す。これも丸暗記するといいよ」

「んー」

(前略)
[style align=center]\
[link target=*opening]  ゲームをはじめる  [endlink]
[link target=*dataload]セーブデータをロードする[endlink]
[link target=*option]    オプション    [endlink]
[link exp="kag.close()" color=0xff0000]  ゲームを終了する  [endlink]\
[style align=default]\
(以下略)

「あー、変数のとこでやった exp が出てきたー」

「そう。このことからもわかるように、これはKAGのスクリプトと言うよりは、TJS式だ。この式を [link] と一緒に扱うことで、吉里吉里はクローズし、ゲームは終了する。書式だけ書くと、こうなる」

[link exp="kag.close()" color=0x選択肢上の矩形の色]

「選択肢に色がついてるねー」

「うん、そうだね。でも、それはどうしても必要なものじゃない。だから、ただ単純にゲームを終了させるだけなら、色を指定する部分は不要だよ」

「んーと……」

「まだ何か質問があるかい?」

「あのねー、終了すんときに、いちいち終了するか聞いてこないよーにわ、できないのかなー?」

「できるよ。でも、それはプレイヤーに不親切じゃないか?」

「そーぢゃなくて、ゲームを作ってんときにわいっぱつで終了してほしーんだもん。んだから、ほかのひとに見せるときにわ、直すもん」

「そういう場合はこうやって書くといい」

(前略)
[style align=center]\
[link target=*opening]  ゲームをはじめる  [endlink]
[link target=*dataload]セーブデータをロードする[endlink]
[link target=*option]    オプション    [endlink]
[link exp="system.exit()" color=0xff0000]  ゲームを終了する  [endlink]\
[style align=default]\
(以下略)

「これは終了確認をせずに吉里吉里を終了させる。書式はこうなる」

[link exp="system.exit()" color=0x選択肢上の矩形の色]

「ちゃんと用意されてんだねー!」

「だから、自由度は高いって言ってるだろ?」

「そーだねー! んでも、ふつー、ほかのソフトわ、こーゆーとこまでわ、触らせてくんないんだよー。しすてむー、とかゆっちゃって。しすてむー」

「そうだな。そして、おいらが吉里吉里/KAGをこよなく愛する理由は、正にそこにあるわけだ」

「そーだねー」

「他に、何か質問はあるかい?」

「んーと、ないもん」

「それじゃ、ここで復習だ。完成したゲームのメニュー画面のスクリプトを見ながら、今まで勉強してきたことをまとめてみよう」

「んーと、セーブデータのページから戻ってくるためのラベルをつけて……」

[title name="タイトル"]\
[wc time=20]\
*start|スタート
[playbgm storage="title"]\
;↓タイトル画像の読み込み
[layopt layer=message0 page=fore visible=false]\
[image storage="title" page=back layer=base]\
[backlay layer=message0]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
;↓文字レイヤーの表示と、メニュー文字の表示
[ct]\
[backlay]\
[layopt layer=message0 page=back visible=true]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
;↓セーブデータロードのページから戻ってくる時のラベル
*menu
[locate y=300]\
[delay speed=nowait]\
[style align=center]\
[link target=*opening]  ゲームをはじめる  [endlink]
[link target=*dataload]セーブデータをロードする[endlink]
[link target=*option]    オプション    [endlink]
[link exp="system.exit()" color=0xff0000]  ゲームを終了する  [endlink]\
[style align=default]\
[delay speed=user]\
[s]
;--------------------------------------------
;--------------------------------------------
*opening
[ct]\
;↓トランジションによる背景画像の切り替え
[layopt layer=message0 page=back visible=false]\
[image storage="ほてる.jpg" layer=base page=back]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
;↓文字レイヤーの表示と文字表示
[ct]\
[backlay]\
[layopt layer=message0 page=back visible=true]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
謹啓[l]

チャーチホテル ChristmasEve へお越しいただきまして、真にありがとうございます。[l]


それでは、まずはお客様とお連れ様のサーネーム(姓)およびファーストネーム(名)を、こちらの宿泊カードにご記入ください。[l]
*inputname
;----------------------------------------------------
;▼男性の苗字を入力
[input name=f.sname1 prompt="あなた(男性)の姓をご記帳下さい" title="名前の入力"]\
;----------------------------------------------------
;入力文字列が長い場合
[if exp="f.sname1.length>3"]\
[ct]\
苗字は3文字までにして下さい。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;入力文字列がカラの場合
[if exp="f.sname1==''"]\
[ct]\
苗字を入力してください。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;▼男性の名前を入力
[input name=f.name1 prompt="あなた(男性)の名をご記帳下さい" title="名前の入力"]\
;----------------------------------------------------
;入力文字列が長い場合
[if exp="f.name1.length>3"]\
[ct]\
名前は3文字までにして下さい。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;入力文字列がカラの場合
[if exp="f.name1==''"]\
[ct]\
名前を入力してください。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;▼女性の苗字を入力
[input name=f.sname2 prompt="お連れ様(女性)の姓をご記帳下さい" title="名前の入力"]\
;----------------------------------------------------
;入力文字列が長い場合
[if exp="f.sname2.length>3"]\
[ct]\
苗字は3文字までにして下さい。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;入力文字列がカラの場合
[if exp="f.sname2==''"]\
[ct]\
苗字を入力してください。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;▼女性の名前を入力
[input name=f.name2 prompt="お連れ様(女性)の名をご記帳下さい" title="名前の入力"]\
;----------------------------------------------------
;入力文字列が長い場合
[if exp="f.name2.length>3"]\
[ct]\
名前は3文字までにして下さい。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;入力文字列がカラの場合
[if exp="f.name2==''"]\
[ct]\
名前を入力してください。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;▼車の名前を入力
[input name=f.carname prompt="キーをお預かりしますが、お車の型は?" title="名前の入力"]\
;----------------------------------------------------
;入力文字列が長い場合
[if exp="f.carname1.length>6"]\
[ct]\
車の名前は6文字までにして下さい。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;入力文字列がカラの場合
[if exp="f.carname==''"]\
[ct]\
車の名前を入力してください。[p]
[jump target=*return_name]\
[endif]\
;----------------------------------------------------
;↓文字変数の確認表示
お客様のお名前は[font color=0xffff00][emb exp=f.sname1][emb exp=f.name1][font color=default]様、
お連れ様のお名前は[font color=0xffff00][emb exp=f.sname2][emb exp=f.name2][font color=default]様、
お車は[font color=0xffff00][emb exp=f.carname][font color=default]でよろしいですか?
[delay speed=nowait]\
[locate y=360]\
[link target=*scene01]A.よろしい[endlink]
[link target=*return_name]B.よろしくない[endlink]\
[delay speed=user]\
[s]\
;--------------------------------------------
;↓名前再入力前の文字レイヤークリア
*return_name
[ct]\
[jump target=*inputname]\
[s]\
;--------------------------------------------
;--------------------------------------------
*dataload
[ct]\
;↓トランジションによる背景画像の切り替え
[layopt layer=message0 page=back visible=false]\
[image storage="cami" layer=base page=back]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
;↓文字レイヤーの非表示と文字表示(裏画面)
[ct]\
[layopt layer=message0 page=fore visible=false]\
[delay speed=nowait]\
[locate x=40 y=20]再開する栞を選んでください。

[font color=0xff0080]\
[locate y=100]
[style align=center]\
[link exp="kag.restoreBookMark(0)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(0)"]\
[endlink]
[link exp="kag.restoreBookMark(1)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(1)"]\
[endlink]
[link exp="kag.restoreBookMark(2)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(2)"]\
[endlink]
[link exp="kag.restoreBookMark(3)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(3)"]\
[endlink]
[link exp="kag.restoreBookMark(4)" color=0xffffff]\
[emb exp="kag.getBookMarkPageName(4)"]\
[endlink]
[style align=default]\
[font color=default]\

;↓戻るリンクの表示(裏画面)
[locate x=400 y=360][link target=*return_menu]メニューに戻る[endlink]\
[delay speed=user]\
;↓文字を裏画面から表画面にトランジションで表示
[backlay]\
[layopt layer=message0 page=back visible=true]\
[trans time=2000 rule="trans1" vague=100]\
[wt]\
[s]
;--------------------------------------------
*return_menu
;↓メニューに戻る前の背景および文字レイヤーの制御
[layopt layer=message0 page=back visible=false]\
[image storage="title.bmp" layer=base page=back]\
[trans rule="trans1" time=2000 vague=100]\
[wt]\
[ct]\
[jump target=*menu]
[s]
;--------------------------------------------
;--------------------------------------------
;↓いつか作りたいオプションページ
*option
[ct]\
おぷしょんぺーじだもん。
[s]
;--------------------------------------------
*scene01
ゲームの本シナリオへ。
[s]

「んわーんわー!? すきゃんてぃこーんな長いスクリプト書いたのかなー!? ちょー長いぢゃんよでやー!」

「スクリプトは、書けば書くほどややこしくなってくる。だから、後々のことを考えて、自分で理解しやすい書き方をした方がいい。短いうちはどうってことないけど、本格的なノベルゲームを作ることになったらすぐに1000行2000行になってしまうからね」

「んでもって、オプションページは?」

「そこに手を入れるのは、もっとずっと先のことだよ。エンディング達成度一覧やメッセージ履歴の記録帳、BGMのリスニングルームなどなど、KAGを使いこなせるようになってきたら、ゲームのコンセプトに合わせて作ればいい」

「そーだねー。それじゃすきゃんてぃも、もっともっと頑張んなくちゃなー!」

「オプションページの構築についてはこの心中日記ではやらない。また、いつか、中級編の心中日記を書くことがあったらそっちで説明しよう」

「わかったもん」

練習日記 8日目 次へ


トップページへ戻る