システムカスタマイズについてダラダラやるよーその9
システムカスタマイズについてダラダラやるよーその8 - 永字八法の続き。
NScripterのシステムカスタマイズについて、1から話をしてみようと思う。その第9回目。
今回はオートモードについて。
オートモード
何も操作しなくても、一定時間ごとにクリックを押したのと同じ扱いになるモード。
元々NScripterにもデフォルトで存在しているが、何か操作すると解除されると言う弱装版である。
現在のところ、ユーザーの要求では、選択肢などがあったとしても解除されない強装版が求められているようなので、本稿でもそれを実装してみた。
現在のところ、Aキーでオートモードのオンオフが切り替えられるようになっている。
どれくらい待つのか。
ボイスの有無で少し変わる。
ボイスがない場合は、文字数の長さに比例+最低限の時間が待ち時間になる。
ボイスがある場合は、ボイスモードによる。
ボイスとの関係
ボイスモードと関係する。
ボイスモードがマルチであれば、ボイスの長さに関係なくテキストの長さだけが問題となる。
ボイスモードがシングルであれば、やはりボイスの長さに関係なくテキストの長さで待つが、次にボイスが演奏される時には、演奏前に今のボイスの演奏終了を待つ処理が入る。
次回予告
現在のスクリプト
00.txt
;$V2000G1000S800,600L10000
01.txt
*start gosub *start_window gosub *start_cast gosub *start_textwindow gosub *start_text gosub *start_nameplate gosub *start_saveload gosub *start_if gosub *start_if1 gosub *start_if2 gosub *start_if3 gosub *start_if4 gosub *start_if5 gosub *start_if6 gosub *start_skip gosub *start_sound gosub *start_sprite gosub *start_global
10.txt
click [キャラ1/0001] うぐう。\ 名前欄が消えるかな?\ [キャラ2/0002] が、がお。\ もう一度、消えるかな?\ [キャラ3/0003] ぶらーぼ\ [キャラ15/0004] [キャラ4/0006] あ\ [/0007] い\ [キャラ6/0008] う\ え\ お\ か\ き\ く\ け\ こ\ さ\ し\ す\ せ\ そ\ た\ ち\ つ\ て\ と\
97.txt
end *define gosub *define_numalias gosub *define_global gosub *define_window gosub *define_background gosub *define_cast gosub *define_textwindow gosub *define_text gosub *define_nameplate gosub *define_saveload gosub *define_bexec gosub *define_debug gosub *define_exec gosub *define_fileexist gosub *define_if gosub *define_linear gosub *define_newsposition gosub *define_skip gosub *define_sound gosub *define_sprite game
98.txt
*loadgosub_lb gosub *loadgosub_chvol return
99.txt
*define_numalias ; numalias 定義用の一時変数 mov %0,100 ; 100番から。 ; スプライト番号は逆に奥から。 mov %1,900 return *define_global ; グローバル変数を使いますよ。 globalon ; グローバル用numaliasの定義変数 mov %2,1000 ; グローバル変数の初期化をしたかしていないかのフラグ。 numalias global_initialize,%2:inc %2 return *define_window ; メニューは全部消す。 deletemenu ; ウィンドウサイズを保存する変数。 numalias window_width,%0:inc %0 numalias window_height,%0:inc %0 return *start_window ; これからずっと使う、ウィンドウのサイズを取得しておく getwindowsize %window_width,%window_height return *define_background ; 画像の読み込みのログを取る。 ; これがないと、画像鑑賞が面倒になるので。 filelog return *define_cast ; 立ち絵の処理 ; 立ち絵のスプライト並びでの位置を決めます。 numalias sp_casts,%1:dec %1 humanz sp_casts ; キャラクターの総数を設定する。 numalias cast_max,10 ; とりあえず、10人 ; キャラクターは名前で判別する。 ; キャラクターにはそれぞれ好感度とボイスボリュームを設定できるとする。 ; キャラクター名を番号に変換する命令 defsub name2number numalias n2n_name,%0:inc %0 numalias n2n_number,%0:inc %0 numalias n2n_hit,%0:inc %0 return *start_cast ; 立ち絵の高さを決めます。 ; 画面サイズを変えてもデフォルトのままなので、 ; 画面サイズを動的に取得してそれに合わせた設定にします。 underline %window_height-1 return ; キャラクター名を番号に変える関数。 ; 該当がなければ0が戻ってくる。 *name2number getparam i%n2n_number,$n2n_name ; まずは0に設定する。 mov %%n2n_number,0 ; キャラクターの名前や数が変われば、以下の行も適当にコピペしたりして編集してください。 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ1":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ2":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ3":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ4":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ5":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ6":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ7":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ8":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ9":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ10":if_int_return %n2n_hit,0 ; 最終的には、やはり0に設定する。 mov %%n2n_number,0 return *define_textwindow ; テキストウィンドウ用のスプライト番号を定義 numalias sp_textwindow,%1:dec %1 ; 念の為に作っておく。文字スプライト用のスプライト番号 numalias sp_text,%1:dec %1 ; テキストウィンドウをスプライトの位置まで引っ込ませる。 windowback ; テキストウィンドウの画像タグを格納する変数(グローバル変数) numalias textwindow_file,%2:inc %2 ; テキストウィンドウの不透明度の変数(グローバル) numalias textwindow_alpha,%2:inc %2 ; テキストウィンドウの大きさの変数 numalias textwindow_width,%0:inc %0 numalias textwindow_height,%0:inc %0 ; テキストウィンドウの左上の位置の変数 numalias textwindow_x,%0:inc %0 numalias textwindow_y,%0:inc %0 ; 表示する文字のフォントの大きさの変数 numalias font_width,%0:inc %0 numalias font_height,%0:inc %0 ; 文字間横と縦の変数 numalias font_space,%0:inc %0 numalias line_space,%0:inc %0 ; 文字を太字にするかどうかの変数 numalias font_bold,%0:inc %0 ; 文字にシャドウをつけるかどうかの変数 numalias font_shadow,%0:inc %0 ; ルビ用フォントの大きさの変数 numalias font_ruby_width,%0:inc %0 numalias font_ruby_height,%0:inc %0 ; フォントの色 numalias font_color,%0:inc %0 numalias font_color_clickable,%0:inc %0 numalias font_color_choose,%0:inc %0 numalias font_color_choosed,%0:inc %0 ; 以上のフォントデータから、文字列スプライト用のタグを作って格納する変数 numalias font_sprite,%0:inc %0 ; テキストウィンドウと、実際の表示領域までのスペースの変数 numalias textwindow_padding_top,%0:inc %0 numalias textwindow_padding_bottom,%0:inc %0 numalias textwindow_padding_left,%0:inc %0 numalias textwindow_padding_right,%0:inc %0 ; 実際の表示領域の大きさの変数 numalias textwindow_area_width,%0:inc %0 numalias textwindow_area_height,%0:inc %0 ; テキストウィンドウの文字数と行数の変数 numalias textwindow_col,%0:inc %0 numalias textwindow_row,%0:inc %0 ; 自作のテキストウィンドウ初期化命令の定義 defsub set_textwindow return *start_textwindow ; テキストウィンドウの画像と不透明度を定義 if %global_initialize=0 mov $textwindow_file,":c;>600,200,#888888" if %global_initialize=0 mov %textwindow_alpha,255 ; 色の設定 mov $font_color,"#FFFFFF" mov $font_color_clickable,"#0000FF" mov $font_color_choose,"#FF0000" mov $font_color_choosed,"FF00FF" ; エフェクト中もテキストウィンドウが消えないようにする。 erasetextwindow 0 ; 念のため、右クリックを殺しておく。 rmode 0 ; 一度実行しておく。 set_textwindow return ; テキストウィンドウを設定した値に変更する。 *set_textwindow ; テキストウィンドウの画像読み込み lsph sp_textwindow,$textwindow_file,0,0,%textwindow_alpha ; テキストウィンドウのサイズを取得 getspsize sp_textwindow,%textwindow_width,%textwindow_height ; テキストウィンドウの配置場所の決定(左下にしている) news_position %textwindow_x,%textwindow_y,%window_width,%window_height,%textwindow_width,%textwindow_height,-1,1 ; 各種フォントの設定 mov %font_width,22 mov %font_height,22 mov %font_space,2 mov %line_space,2 mov %font_bold,0 mov %font_shadow,1 mov %font_ruby_width,11 mov %font_ruby_height,11 ; フォントの各値を、文字列スプライトで使えるように文字列化しておく。 itoa $font_width,%font_width itoa $font_height,%font_height itoa $font_space,%font_space mov $font_sprite,":s/"+$font_width+","+$font_height+","+$font_space+";" ; パディングの設定 mov %textwindow_padding_top,8 mov %textwindow_padding_bottom,8 mov %textwindow_padding_left,12 mov %textwindow_padding_right,12 ; 実際の表示領域の広さを計算する。 mov %textwindow_area_width,%textwindow_width-%textwindow_padding_left-%textwindow_padding_right mov %textwindow_area_height,%textwindow_height-%textwindow_padding_top-%textwindow_padding_bottom ; 表示領域の広さから、行数や文字数を計算する。 mov %textwindow_col,%textwindow_area_width/(%font_width+%font_space) mov %textwindow_row,%textwindow_area_height/(%font_height+%line_space+%font_ruby_height) ; 数値を反映した値にする。 setwindow %textwindow_x+%textwindow_padding_top,%textwindow_y+%textwindow_padding_left,%textwindow_col,1+%textwindow_row,%font_width,%font_height,%font_space,%line_space+%font_ruby_height,0,%font_bold,%font_shadow,#000000,%textwindow_x,%textwindow_y,%window_width,%window_height ; ルビも設定する。 rubyon %font_ruby_width,%font_ruby_height ; テキストウィンドウの位置を設定 amsp sp_textwindow,%textwindow_x,%textwindow_y return ; テキストウィンドウを表示する。 *print_textwindow vsp sp_textwindow,1 vsp sp_text,1 return ; テキストウィンドウを非表示にする。 *delete_textwindow vsp sp_textwindow,0 vsp sp_text,0 return *define_text ; システムカスタマイズの宣言 textgosub *text_lb pretextgosub *pretext_lb ; 既読スキップ有りで。 kidokuskip ; テキストウィンドウに表示している文字を取得するための変数 numalias text_pre,%0:inc %0 numalias text_before,%0:inc %0 numalias text_add,%0:inc %0 numalias text_after,%0:inc %0 ; テキストスピード(グローバル変数) numalias text_speed,%2:inc %2 ; texton/textoffを上書き defsub texton defsub textoff ; テキストウィンドウを表示しているかいないかを格納する変数 numalias text_visible,%0:inc %0 ; pretext用タグ取得変数 numalias gettag1,%0:inc %0 numalias gettag2,%0:inc %0 numalias gettag3,%0:inc %0 ; 発言者名 numalias talker_name,%0:inc %0 ; 実際に表示する名前 numalias talker_label,%0:inc %0 ; 現在再生しているボイスファイル。 numalias voice_playing,%0:inc %0 ; 仮の再生ファイル numalias voice_temp,%0:inc %0 ; オートモードの処理 ; オートモードが否かを格納する変数 numalias is_automode,%0:inc %0 numalias automode_a,100 ; 一文字50ミリ秒 numalias automode_b,300 ; 最低限、300ミリ秒待つ ; オートモードの待ち時間のコンフィグ numalias automode_speed,%2:inc %2 return *start_text ; 文字速度の初期設定 if %global_initialize=0 mov %text_speed,40 if %global_initialize=0 mov %automode_speed,5 ; 文字速度をそれに設定する。 textspeed %text_speed return *pretext_lb ; タグを取得する。 gettag $gettag1,$gettag2,$gettag3 ; 現在の表示内容を取得しておく。 getlogtext $text_pre,0 len %text_pre,$text_pre ; $gettag1が空でなければ、ネームプレート処理をする。 notif_str_gosub $gettag1,"",*pretext_lb_talker ; ボイスがあった時の処理 notif_str_gosub $gettag2,"",*pretext_lb_voice ; 念のため、表示 texton print 1 ; 念のため、文字速度を設定 textspeed %text_speed return *pretext_lb_talker ; $gettag1があれば、それを表示する名前にする。 mov $talker_name,$gettag1 mov $talker_label,$gettag1 ; $gettag3があれば、それをネームプレートにするが、内部的には発言者は変わらない。 len %gettag3,$gettag3 skip 1 + 1/(%gettag3+1) ; 飛ばす処理 mov $talker_label,$gettag3 ; 表示する。 putname $talker_label return *pretext_lb_voice ; 仮のファイル名を作成 mov $voice_temp,voice_folder+$gettag2+voice_extension ; ファイルの存在確認 fileexist %fileexist,$voice_temp ; なければ何もしない if_int_return %fileexist,0 ; 存在するので、ファイルとして登録 mov $voice_playing,$voice_temp ; 名前も確定しているはずなので、演奏する。 voice $talker_name,$voice_playing ; $voice_playing に登録があれば、それはボイスボタンで再生できるとする。 return *text_lb ; 現在の表示内容を取得しておく。 getlogtext $text_before,0 len %text_before,$text_before ; 前回から、何文字テキストが増えているかを取得する。 mov %text_add,%text_before-%text_pre *text_lb_loop1 ; スキップモードなら、すぐに飛ばす。 isskip %is_skip if_int_goto %is_skip,1,*text_lb_loop3 ; CTRLは例外とする。 checkkey %checkkey,"CTRL":skip %checkkey+1 wait_noinput ; キーアップまで待つ。 ; 入力待ち設定開始 bclear ; オートモードなら、時間待ち設定をする。 if_int_gosub %is_automode,1,*automode_btime *text_lb_loop2 bexec $bexec,%bexec *text_lb_loop3 ; スキップモードの判定と、スキップモードへの変更 if_str_gosub $bexec,"K",*skipon ; スキップモードを取得 isskip %is_skip ; スキップモードなら、飛ばす。 if_int_goto %is_skip,1,*text_lb_end ; オートモードの判別 if_str_gosub $bexec,"A",*automode_change ; クイックセーブとクイックロード if_str_gosub $bexec,"Q",*text_quick_save if_str_gosub $bexec,"W",*text_quick_load ; ボイス再生 if_str_gosub $bexec,"V",*text_voice_replay ; 次に進む処理 if_str_goto $bexec,"LCLICK",*text_lb_end if_str_goto $bexec,"SPACE",*text_lb_end if_str_goto $bexec,"RETURN",*text_lb_end if_str_goto $bexec,"WHEELDOWN",*text_lb_end if_str_goto $bexec,"PAGEDOWN",*text_lb_end if_str_goto $bexec,"CTRL",*text_lb_end if_str_goto $bexec,"TIMEOUT",*text_lb_end ; 正しい入力ではなかったので、ループする。再入力待ち goto *text_lb_loop2 ; 次に進む。 *text_lb_end ; \マークで来ていたら、テキストウィンドウの中身を消す。 texec ; 現在の表示内容を取得しておく。 getlogtext $text_after,0 len %text_after,$text_after ; もし、最後の表示内容の長さが0になっていれば、テキストが消去された可能性がある。 if_int_gosub %text_after,0,*check_textclear return ; テキストウィンドウの中身が消去されたかどうかを確認するルーチン *check_textclear ; texec直前のテキストウィンドウの中身が存在していなければ、変化なしと判断する。 if_large_goto %text_before,%text_after,*check_textclear_main return *check_textclear_main ; ここに来たと言うことは、textclearが実行されたと判断する。 ; やるべきことは、 ; 1.今まで表示していた内容(発言者欄・ボイス・テキスト)のバックログへの追加(未実装) ; 2.発言者欄の消去 ; 3.現在再生しているボイスファイルの削除 ; 発言者欄の消去 nameclear print 1 ; ボイスファイルの削除 mov $voice_playing,"" return *texton ; 既に表示状態なら、何もしない。 if_int_return %text_visible,1 ; 一連の処理その1 gosub *print_textwindow gosub *print_nameplate ; 画面を更新 print 1 ; デフォルトの処理をする。 _texton ; フラグ管理 mov %text_visible,1 return *textoff ; 既に非表示状態なら、何もしない。 if_int_return %text_visible,0 ; 一連の処理その2 gosub *delete_textwindow gosub *delete_nameplate ; 画面を更新 print 1 ; デフォルトの処理をする。 _textoff ; フラグ管理 mov %text_visible,0 return *automode_btime ; 待ち時間を決める。 btime ( %text_add * automode_a + automode_b ) * %automode_speed / 10 return ; オートモードを切り替える。 *automode_change mov %is_automode,1-%is_automode return *text_lb_loop1 ; クイックセーブ *text_quick_save gosub *quick_save return *text_lb_loop1 ; クイックロード *text_quick_load gosub *quick_load return *text_lb_loop1 ; ボイス再生 *text_voice_replay ; ボイスがあるかどうか確認。 if_str_goto $voice_playing,"",*text_voice_replay_end ; ボイスがあれば、再生する。 se $voice_playing *text_voice_replay_end return *text_lb_loop1 *define_nameplate ; スプライト設定 ; 発言者欄 numalias sp_nameplate,%1:dec %1 ; 発言者欄のスプライトファイル numalias nameplate_file,%0:inc %0 ; 発言者欄の各値 numalias nameplate_x,%0:inc %0 numalias nameplate_y,%0:inc %0 numalias nameplate_width,%0:inc %0 numalias nameplate_height,%0:inc %0 ; 発言者名の各値 numalias sp_name,%1:dec %1 ; 発言者欄の各値 numalias name_x,%0:inc %0 numalias name_y,%0:inc %0 numalias name_width,%0:inc %0 numalias name_height,%0:inc %0 ; 表示する発言者名 numalias name_string,%0:inc %0 ; 現在、発言者名が設定されているかいないか。 numalias name_exist,%0:inc %0 ; 発言者欄の初期化命令 defsub set_nameplate ; 発言者名に文字を出力 defsub putname ; 発言者名を削除する命令 defsub nameclear return *start_nameplate ; ファイルの設定 if $nameplate_file="" mov $nameplate_file,":c;>100,30,#888888" ; 初期化 set_nameplate return ; ネームプレートの初期化 *set_nameplate ; ネームプレートのファイルの読み込み。不透明度はテキストウィンドウと同じ。 lsph sp_nameplate,$nameplate_file,0,0,%textwindow_alpha csp sp_name ; 念のため、今表示している名前は削除 mov %name_exist,0 ; サイズの取得 getspsize sp_nameplate,%nameplate_width,%nameplate_height ; 位置を決定 ; テキストウィンドウの左上にくっつける。 mov %nameplate_x,%textwindow_x mov %nameplate_y,%textwindow_y-%nameplate_height ; 位置を操作 amsp sp_nameplate,%nameplate_x,%nameplate_y return ; ネームプレートに文字を表示する。 *putname ; 表示する文字列を取得する。 getparam $name_string ; 文字列をスプライト化する。不透明度は255で固定 lsph sp_name,$font_sprite+$font_color+$name_string,0,0,255 ; 大きさを取得 getspsize sp_name,%name_width,%name_height ; 正しい位置を計算 mov %name_x,%nameplate_x+%nameplate_width/2-%name_width/2 mov %name_y,%nameplate_y+%nameplate_height/2-%name_height/2 ; 正しい位置に移動 amsp sp_name,%name_x,%name_y vsp sp_name,1 ; フラグ管理 mov %name_exist,1 return *nameclear ; スプライトを削除 csp sp_name ; フラグ管理 mov %name_exist,0 return ; ネームプレートを表示する。 *print_nameplate vsp sp_nameplate,1 vsp sp_name,%name_exist return ; ネームプレートを非表示にする。 *delete_nameplate vsp sp_nameplate,0 vsp sp_name,0 return *define_saveload ; セーブデータを格納するフォルダを決める。 savedir "savedata" ; セーブデータの最大数。デフォルトの右クリックメニューを使うのでない限り実は意味がない。 savenumber 200 ; クイックセーブに使う番号 numalias quick_savedata,200 ; イエス・ノー numalias saveload_yesno,%0:inc %0 return *start_saveload return *quick_save savegame quick_savedata mesbox "クイックセーブしました。","Quick Save" return *quick_load yesnobox %saveload_yesno,"クイックロードしますか?","Quick Load" if_int_return %saveload_yesno,0 loadgame quick_savedata return *define_bexec ; bexec回りの定義 ; 専用変数 numalias bexec,%0:inc %0 ; 何も入力がない状態まで待つ関数 defsub wait_noinput ; checkkey用専用変数 numalias checkkey,%0:inc %0 return *wait_noinput bclear ; 時間待ちをする。 btime 10 ; 入力待ち bexec $bexec,%bexec ; 入力がタイムアウトでなければ何もしない。 if_str_return $bexec,"TIMEOUT" goto *wait_noinput *define_debug ; デバッグログを有効にする。 debuglog 1 return *define_exec ; exec_dll関係 ; 命令群を作成 defsub exec_clear defsub exec_setdll defsub exec_arg defsub exec_arg_int defsub execute stralias exec_slush,"/" stralias exec_comma,"," ; 実行する文字列全体 numalias exec_string,%0:inc %0 ; 実行するdll名 numalias exec_dllname,%0:inc %0 ; 引数 numalias exec_arg,%0:inc %0 ; 引数の数 numalias exec_arg_count,%0:inc %0 ; 結果を受け取る専用変数 numalias getret,%0:inc %0 return *exec_clear ; 初期化 mov $exec_dllname,"" mov %exec_arg_count,0 mov $exec_string,"" return *exec_setdll exec_clear getparam $exec_dllname mov $exec_string,$exec_dllname add $exec_string,exec_slush return *exec_arg getparam $exec_arg skip 2-1/(1+%exec_arg_count) add $exec_string,exec_comma add $exec_string,$exec_arg inc %exec_arg_count return *execute exec_dll $exec_string ; 結果を先に受け取っておく。 getret $getret getret %getret exec_setdll $exec_dllname return *define_fileexist ; fileexist専用変数 numalias fileexist,%0:inc %0 return *define_if ; ifの代替命令群の定義 defsub if_str_goto defsub if_str_gosub defsub if_int_goto defsub if_int_gosub defsub notif_str_goto defsub notif_str_gosub defsub notif_int_goto defsub notif_int_gosub defsub if_str_return defsub if_int_return defsub notif_str_return defsub notif_int_return defsub if_large_goto defsub if_small_goto defsub if_large_gosub defsub if_small_gosub defsub if_large_return defsub if_small_return numalias if_a,%0:inc %0 numalias if_b,%0:inc %0 numalias if_label,%0:inc %0 return *start_if if_str_goto ""," ",*dummy if_str_gosub ""," ",*dummy if_int_goto 0,1,*dummy if_int_gosub 0,1,*dummy notif_str_goto "","",*dummy notif_str_gosub "","",*dummy notif_int_goto 0,0,*dummy notif_int_gosub 0,0,*dummy if_str_return ""," " if_int_return 0,1 notif_str_return "","" notif_int_return 0,0 if_str_gosub "","",*if_in_advance_dummy if_str_goto "","",*if_in_advance1 *if_in_advance1 if_int_gosub 0,0,*if_in_advance_dummy if_int_goto 0,0,*if_in_advance2 *if_in_advance2 notif_str_gosub ""," ",*if_in_advance_dummy notif_str_goto ""," ",*if_in_advance3 *if_in_advance3 notif_int_gosub 0,1,*if_in_advance_dummy notif_int_goto 0,1,*if_in_advance4 *if_in_advance4 gosub *start_if1 gosub *start_if2 gosub *start_if3 gosub *start_if4 if_large_goto 0,0,*if_in_advance_dummy if_small_goto 0,0,*if_in_advance_dummy if_large_gosub 0,0,*if_in_advance_dummy if_small_gosub 0,0,*if_in_advance_dummy if_large_return 0,0 if_small_return 0,0 if_large_goto 1,0,*if_in_advance5 *if_in_advance5 if_large_goto 0,1,*if_in_advance6 *if_in_advance6 gosub *start_if5 gosub *start_if6 return *start_if1 if_str_return "","" return *start_if2 if_int_return 0,0 return *start_if3 notif_str_return ""," " return *start_if4 notif_int_return 0,1 return *start_if5 if_large_return 1,0 return *start_if6 if_small_return 0,1 return ; if 代替命令群本体ルーチン *if_str_goto getparam $if_a,$if_b,$if_label if $if_a=$if_b return $if_label return *if_str_gosub getparam $if_a,$if_b,$if_label if $if_a=$if_b goto $if_label return *if_int_goto getparam %if_a,%if_b,$if_label if %if_a=%if_b return $if_label return *if_int_gosub getparam %if_a,%if_b,$if_label if %if_a=%if_b goto $if_label return *notif_str_goto getparam $if_a,$if_b,$if_label notif $if_a=$if_b return $if_label return *notif_str_gosub getparam $if_a,$if_b,$if_label notif $if_a=$if_b goto $if_label return *notif_int_goto getparam %if_a,%if_b,$if_label notif %if_a=%if_b return $if_label return *notif_int_gosub getparam %if_a,%if_b,$if_label notif %if_a=%if_b goto $if_label return *if_int_return getparam %if_a,%if_b if %if_a=%if_b return *if_in_advance_dummy return *if_str_return getparam $if_a,$if_b if $if_a=$if_b return *if_in_advance_dummy return *notif_int_return getparam %if_a,%if_b notif %if_a=%if_b return *if_in_advance_dummy return *notif_str_return getparam $if_a,$if_b notif $if_a=$if_b return *if_in_advance_dummy return *if_large_goto getparam %if_a,%if_b,$if_label if %if_a>%if_b goto $if_label return *if_small_goto getparam %if_a,%if_b,$if_label if %if_a<%if_b goto $if_label return *if_large_gosub getparam %if_a,%if_b,$if_label if %if_a>%if_b gosub $if_label return *if_small_gosub getparam %if_a,%if_b,$if_label if %if_a<%if_b gosub $if_label return *if_large_return getparam %if_a,%if_b if %if_a>%if_b return *if_in_advance_dummy return *if_small_return getparam %if_a,%if_b if %if_a<%if_b return *if_in_advance_dummy return *if_in_advance_dummy ; 何もしないよ。 return *define_linear ; linear命令を作成 defsub linear ; linear命令で使う変数を定義 numalias ln_x,%0:inc %0 numalias ln_y,%0:inc %0 numalias ln_a,%0:inc %0 numalias ln_b,%0:inc %0 numalias ln_c,%0:inc %0 numalias ln_d,%0:inc %0 return ; 数直線上に点aとbとxがあるとする。 ; 別の数直線上に点cと点dがあるとする。 ; 点aと点cが対応し、点bと点dが対応する時、 ; 点xと対応する点yはどうなるか。 *linear ; 引数の取得 getparam %ln_a,%ln_b,%ln_x,%ln_c,%ln_d,i%ln_y ; 回答の初期化 mov %%ln_y,0 ; %ln_cと%ln_dが同値なら、回答が不定になってしまうので何もせずに返す。 if_int_return %ln_b-%ln_a,0 ; 計算する。 mov %%ln_y,%ln_c+(%ln_d-%ln_c)*(%ln_x-%ln_a)/(%ln_b-%ln_a) return *define_newsposition ; 画面内の位置のNEWS指定 defsub news_position numalias news_ax,%0:inc %0 numalias news_ay,%0:inc %0 numalias news_x,%0:inc %0 numalias news_y,%0:inc %0 numalias parent_width,%0:inc %0 numalias parent_height,%0:inc %0 numalias child_width,%0:inc %0 numalias child_height,%0:inc %0 return *news_position ; ある領域の中で、小さな領域を配置する時のための座標を計算する。 getparam i%news_x,i%news_y,%parent_width,%parent_height,%child_width,%child_height,%news_ax,%news_ay mov %%news_x,%parent_width-%child_width if %news_ax=-1 mov %%news_x,0 if %news_ax=0 div %%news_x,2 mov %%news_y,%parent_height-%child_height if %news_ay=-1 mov %%news_y,0 if %news_ay=0 div %%news_y,2 return *define_skip ; skiponを作成し、skipoffを上書きする。 defsub skipon defsub skipoff ; スキップ状態を格納する変数 numalias is_skip,%0:inc %0 return *start_skip ; 一回実行しておく。 skipon skipoff return *skipon ; スキップ状態にする。 systemcall skip isskip %is_skip return *skipoff ; スキップ状態を解除する。 _skipoff isskip %is_skip return *define_sound ; BGM/BGV/SEの音量(グローバル) numalias bgm_vol,%2:inc %2 numalias bgv_vol,%2:inc %2 numalias se_vol,%2:inc %2 ; ボイスループ用変数 numalias voice_loop,%0:inc %0 ; ボイスボリューム numalias voice_vol,%0:inc %0 ; 配列にする。 dim ?voice_vol[cast_max+1] for %voice_loop=1 to cast_max mov ?voice_vol[%voice_loop],%2:inc %2 ; グローバル変数を割り当てる。 next ; ボイスモード(グローバル) numalias voice_mode,%2:inc %2 ; ボイスモードの数値の意味 numalias single,0 ; 単一再生 numalias mulch,1 ; 多重再生を許す ; BGM命令を上書きして、自動でボリュームも設定するようにする。 defsub bgm defsub bgmstop numalias bgm_file,%0:inc %0 ; BGV命令を作る。 defsub bgv defsub bgvstop ; チャンネルを49に。(適当) numalias bgv_channel,49 numalias bgv_file,%0:inc %0 ; SE命令を作る。単発専用。 ; 空いているチャンネルを自動で選ぶ。 defsub se ; 使っていいチャンネルの範囲 numalias se_channel_first,10 numalias se_channel_last,45 numalias se_channel,%0:inc %0 numalias se_file,%0:inc %0 defsub se_channel_countup ; ボイス用命令 defsub voice ; キャラクターの名前とファイルを指定する。 ; キャラクターの名前からボリュームを取得してファイルを演奏する。 ; ただし、ボリュームが0の場合、演奏はしない。 ; チャンネルは、ボイスモードがsingleなら0で確定。mulchなら、適当にバラけさせる。 numalias voice_castname,%0:inc %0 numalias voice_volume,%0:inc %0 numalias voice_file,%0:inc %0 ; ボイスを格納するフォルダ stralias voice_folder,"voice\" ; ボイスファイルの拡張子 stralias voice_extension,".ogg" ; ボリューム関連 defsub chvol ; 上書きする。 numalias chvol_ch,%0:inc %0 numalias chvol_vol,%0:inc %0 numalias chvol_loop,%0:inc %0 dim ?chvol_vol[50] return *start_sound ; 初期設定 if %global_initialize=1 goto *start_sound2 mov %bgm_vol,50 mov %bgv_vol,50 mov %se_vol,50 for %voice_loop=1 to cast_max mov %?voice_vol[%voice_loop],50 next mov %voice_mode,single *start_sound2 ; SEのボリュームだけは設定しておく。 sevol %se_vol ; 使っていいチャンネルの設定 gosub *se_channel_countup_down return *bgm ; 演奏するファイルを取得 getparam $bgm_file ; 演奏開始 _bgm $bgm_file ; ボリュームを設定 bgmvol %bgm_vol return *bgmstop ; 演奏停止 _bgmstop mov $bgm_file,"" return *bgv ; 演奏するファイルを取得 getparam $bgv_file ; 演奏開始 dwaveloop bgv_channel,$bgv_file ; ボリュームを設定 chvol bgv_channel,%bgv_vol return *bgvstop ; 演奏停止 dwavestop bgv_channel mov $bgv_file,"" return *se ; 演奏するファイル名を取得 getparam $se_file ; 演奏する。 dwave %se_channel,$se_file chvol %se_channel,%se_vol ; 次のためにチャンネルを変える。 se_channel_countup return *se_channel_countup ; カウントアップ inc %se_channel if_large_gosub %se_channel,se_channel_last,*se_channel_countup_down return *se_channel_countup_down ; 最低値に戻す mov %se_channel,se_channel_first return *voice getparam $voice_castname,$voice_file ; ボリュームは0にしておく mov %voice_volume,0 ; 名前を番号に変換 name2number %voice_castname,$voice_castname ; 登録のない名前なら何もしないで終る。 if_int_return %voice_castname,0 ; ボリュームを取得 mov %voice_volume,%?voice_vol[%voice_castname] ; ボリュームが0なら、やはり演奏しない。 if_int_return %voice_volume,0 ; オートモードならば、再生までしばらく待つ。 if_int_gosub %is_automode,1,*voice_wait ; 演奏する(ボイスモードで分岐) dwave %voice_mode*%se_channel,$voice_file chvol %voice_mode*%se_channel,%voice_volume se_channel_countup ; 0でもカウントアップする。減るもんじゃなし。 return *voice_wait bclear btime 1,1 bexec $bexec,%bexec notif_str_goto $bexec,"TIMEOUT",*voice_wait return *chvol getparam %chvol_ch,%chvol_vol _chvol %chvol_ch,%chvol_vol mov ?chvol_vol[%chvol_ch],%chvol_vol return *loadgosub_chvol ; 音のサイズを再現する。 for %chvol_loop=0 to 49 _chvol %chvol_loop,?chvol_vol[%chvol_loop] next return *define_sprite ; getspsize用汎用変数 numalias getspsize_width,%0:inc %0 numalias getspsize_height,%0:inc %0 ; 中心部を指定してスプライトを動かすamspラッパー defsub camsp ; それ用の変数 numalias camsp_sp,%0:inc %0 numalias camsp_x,%0:inc %0 numalias camsp_y,%0:inc %0 return *start_sprite return ; amspのラッパー ; 点を指定すると、そこが中心点になるようにスプライトを動かす。 *camsp getparam %camsp_sp,%camsp_x,%camsp_y getspsize %camsp_sp,%getspsize_width,%getspsize_height div %getspsize_width,2 div %getspsize_height,2 amsp %camsp_sp,%camsp_x-%getspsize_width,%camsp_y-%getspsize_y return *start_global ; グローバル変数の初期化はしたと言う印。 mov %global_initialize,1 return
システムカスタマイズについてダラダラやるよーその9
システムカスタマイズについてダラダラやるよーその8 - 永字八法の続き。
NScripterのシステムカスタマイズについて、1から話をしてみようと思う。その第9回目。
今回はオートモードについて。
オートモード
何も操作しなくても、一定時間ごとにクリックを押したのと同じ扱いになるモード。
元々NScripterにもデフォルトで存在しているが、何か操作すると解除されると言う弱装版である。
現在のところ、ユーザーの要求では、選択肢などがあったとしても解除されない強装版が求められているようなので、本稿でもそれを実装してみた。
現在のところ、Aキーでオートモードのオンオフが切り替えられるようになっている。
どれくらい待つのか。
ボイスの有無で少し変わる。
ボイスがない場合は、文字数の長さに比例+最低限の時間が待ち時間になる。
ボイスがある場合は、ボイスモードによる。
ボイスとの関係
ボイスモードと関係する。
ボイスモードがマルチであれば、ボイスの長さに関係なくテキストの長さだけが問題となる。
ボイスモードがシングルであれば、やはりボイスの長さに関係なくテキストの長さで待つが、次にボイスが演奏される時には、演奏前に今のボイスの演奏終了を待つ処理が入る。
次回予告
現在のスクリプト
00.txt
;$V2000G1000S800,600L10000
01.txt
*start gosub *start_window gosub *start_cast gosub *start_textwindow gosub *start_text gosub *start_nameplate gosub *start_saveload gosub *start_if gosub *start_if1 gosub *start_if2 gosub *start_if3 gosub *start_if4 gosub *start_if5 gosub *start_if6 gosub *start_skip gosub *start_sound gosub *start_sprite gosub *start_global
10.txt
click [キャラ1/0001] うぐう。\ 名前欄が消えるかな?\ [キャラ2/0002] が、がお。\ もう一度、消えるかな?\ [キャラ3/0003] ぶらーぼ\ [キャラ15/0004] [キャラ4/0006] あ\ [/0007] い\ [キャラ6/0008] う\ え\ お\ か\ き\ く\ け\ こ\ さ\ し\ す\ せ\ そ\ た\ ち\ つ\ て\ と\
97.txt
end *define gosub *define_numalias gosub *define_global gosub *define_window gosub *define_background gosub *define_cast gosub *define_textwindow gosub *define_text gosub *define_nameplate gosub *define_saveload gosub *define_bexec gosub *define_debug gosub *define_exec gosub *define_fileexist gosub *define_if gosub *define_linear gosub *define_newsposition gosub *define_skip gosub *define_sound gosub *define_sprite game
98.txt
*loadgosub_lb gosub *loadgosub_chvol return
99.txt
*define_numalias ; numalias 定義用の一時変数 mov %0,100 ; 100番から。 ; スプライト番号は逆に奥から。 mov %1,900 return *define_global ; グローバル変数を使いますよ。 globalon ; グローバル用numaliasの定義変数 mov %2,1000 ; グローバル変数の初期化をしたかしていないかのフラグ。 numalias global_initialize,%2:inc %2 return *define_window ; メニューは全部消す。 deletemenu ; ウィンドウサイズを保存する変数。 numalias window_width,%0:inc %0 numalias window_height,%0:inc %0 return *start_window ; これからずっと使う、ウィンドウのサイズを取得しておく getwindowsize %window_width,%window_height return *define_background ; 画像の読み込みのログを取る。 ; これがないと、画像鑑賞が面倒になるので。 filelog return *define_cast ; 立ち絵の処理 ; 立ち絵のスプライト並びでの位置を決めます。 numalias sp_casts,%1:dec %1 humanz sp_casts ; キャラクターの総数を設定する。 numalias cast_max,10 ; とりあえず、10人 ; キャラクターは名前で判別する。 ; キャラクターにはそれぞれ好感度とボイスボリュームを設定できるとする。 ; キャラクター名を番号に変換する命令 defsub name2number numalias n2n_name,%0:inc %0 numalias n2n_number,%0:inc %0 numalias n2n_hit,%0:inc %0 return *start_cast ; 立ち絵の高さを決めます。 ; 画面サイズを変えてもデフォルトのままなので、 ; 画面サイズを動的に取得してそれに合わせた設定にします。 underline %window_height-1 return ; キャラクター名を番号に変える関数。 ; 該当がなければ0が戻ってくる。 *name2number getparam i%n2n_number,$n2n_name ; まずは0に設定する。 mov %%n2n_number,0 ; キャラクターの名前や数が変われば、以下の行も適当にコピペしたりして編集してください。 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ1":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ2":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ3":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ4":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ5":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ6":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ7":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ8":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ9":if_int_return %n2n_hit,0 inc %%n2n_number:cmp %n2n_hit,$n2n_name,"キャラ10":if_int_return %n2n_hit,0 ; 最終的には、やはり0に設定する。 mov %%n2n_number,0 return *define_textwindow ; テキストウィンドウ用のスプライト番号を定義 numalias sp_textwindow,%1:dec %1 ; 念の為に作っておく。文字スプライト用のスプライト番号 numalias sp_text,%1:dec %1 ; テキストウィンドウをスプライトの位置まで引っ込ませる。 windowback ; テキストウィンドウの画像タグを格納する変数(グローバル変数) numalias textwindow_file,%2:inc %2 ; テキストウィンドウの不透明度の変数(グローバル) numalias textwindow_alpha,%2:inc %2 ; テキストウィンドウの大きさの変数 numalias textwindow_width,%0:inc %0 numalias textwindow_height,%0:inc %0 ; テキストウィンドウの左上の位置の変数 numalias textwindow_x,%0:inc %0 numalias textwindow_y,%0:inc %0 ; 表示する文字のフォントの大きさの変数 numalias font_width,%0:inc %0 numalias font_height,%0:inc %0 ; 文字間横と縦の変数 numalias font_space,%0:inc %0 numalias line_space,%0:inc %0 ; 文字を太字にするかどうかの変数 numalias font_bold,%0:inc %0 ; 文字にシャドウをつけるかどうかの変数 numalias font_shadow,%0:inc %0 ; ルビ用フォントの大きさの変数 numalias font_ruby_width,%0:inc %0 numalias font_ruby_height,%0:inc %0 ; フォントの色 numalias font_color,%0:inc %0 numalias font_color_clickable,%0:inc %0 numalias font_color_choose,%0:inc %0 numalias font_color_choosed,%0:inc %0 ; 以上のフォントデータから、文字列スプライト用のタグを作って格納する変数 numalias font_sprite,%0:inc %0 ; テキストウィンドウと、実際の表示領域までのスペースの変数 numalias textwindow_padding_top,%0:inc %0 numalias textwindow_padding_bottom,%0:inc %0 numalias textwindow_padding_left,%0:inc %0 numalias textwindow_padding_right,%0:inc %0 ; 実際の表示領域の大きさの変数 numalias textwindow_area_width,%0:inc %0 numalias textwindow_area_height,%0:inc %0 ; テキストウィンドウの文字数と行数の変数 numalias textwindow_col,%0:inc %0 numalias textwindow_row,%0:inc %0 ; 自作のテキストウィンドウ初期化命令の定義 defsub set_textwindow return *start_textwindow ; テキストウィンドウの画像と不透明度を定義 if %global_initialize=0 mov $textwindow_file,":c;>600,200,#888888" if %global_initialize=0 mov %textwindow_alpha,255 ; 色の設定 mov $font_color,"#FFFFFF" mov $font_color_clickable,"#0000FF" mov $font_color_choose,"#FF0000" mov $font_color_choosed,"FF00FF" ; エフェクト中もテキストウィンドウが消えないようにする。 erasetextwindow 0 ; 念のため、右クリックを殺しておく。 rmode 0 ; 一度実行しておく。 set_textwindow return ; テキストウィンドウを設定した値に変更する。 *set_textwindow ; テキストウィンドウの画像読み込み lsph sp_textwindow,$textwindow_file,0,0,%textwindow_alpha ; テキストウィンドウのサイズを取得 getspsize sp_textwindow,%textwindow_width,%textwindow_height ; テキストウィンドウの配置場所の決定(左下にしている) news_position %textwindow_x,%textwindow_y,%window_width,%window_height,%textwindow_width,%textwindow_height,-1,1 ; 各種フォントの設定 mov %font_width,22 mov %font_height,22 mov %font_space,2 mov %line_space,2 mov %font_bold,0 mov %font_shadow,1 mov %font_ruby_width,11 mov %font_ruby_height,11 ; フォントの各値を、文字列スプライトで使えるように文字列化しておく。 itoa $font_width,%font_width itoa $font_height,%font_height itoa $font_space,%font_space mov $font_sprite,":s/"+$font_width+","+$font_height+","+$font_space+";" ; パディングの設定 mov %textwindow_padding_top,8 mov %textwindow_padding_bottom,8 mov %textwindow_padding_left,12 mov %textwindow_padding_right,12 ; 実際の表示領域の広さを計算する。 mov %textwindow_area_width,%textwindow_width-%textwindow_padding_left-%textwindow_padding_right mov %textwindow_area_height,%textwindow_height-%textwindow_padding_top-%textwindow_padding_bottom ; 表示領域の広さから、行数や文字数を計算する。 mov %textwindow_col,%textwindow_area_width/(%font_width+%font_space) mov %textwindow_row,%textwindow_area_height/(%font_height+%line_space+%font_ruby_height) ; 数値を反映した値にする。 setwindow %textwindow_x+%textwindow_padding_top,%textwindow_y+%textwindow_padding_left,%textwindow_col,1+%textwindow_row,%font_width,%font_height,%font_space,%line_space+%font_ruby_height,0,%font_bold,%font_shadow,#000000,%textwindow_x,%textwindow_y,%window_width,%window_height ; ルビも設定する。 rubyon %font_ruby_width,%font_ruby_height ; テキストウィンドウの位置を設定 amsp sp_textwindow,%textwindow_x,%textwindow_y return ; テキストウィンドウを表示する。 *print_textwindow vsp sp_textwindow,1 vsp sp_text,1 return ; テキストウィンドウを非表示にする。 *delete_textwindow vsp sp_textwindow,0 vsp sp_text,0 return *define_text ; システムカスタマイズの宣言 textgosub *text_lb pretextgosub *pretext_lb ; 既読スキップ有りで。 kidokuskip ; テキストウィンドウに表示している文字を取得するための変数 numalias text_pre,%0:inc %0 numalias text_before,%0:inc %0 numalias text_add,%0:inc %0 numalias text_after,%0:inc %0 ; テキストスピード(グローバル変数) numalias text_speed,%2:inc %2 ; texton/textoffを上書き defsub texton defsub textoff ; テキストウィンドウを表示しているかいないかを格納する変数 numalias text_visible,%0:inc %0 ; pretext用タグ取得変数 numalias gettag1,%0:inc %0 numalias gettag2,%0:inc %0 numalias gettag3,%0:inc %0 ; 発言者名 numalias talker_name,%0:inc %0 ; 実際に表示する名前 numalias talker_label,%0:inc %0 ; 現在再生しているボイスファイル。 numalias voice_playing,%0:inc %0 ; 仮の再生ファイル numalias voice_temp,%0:inc %0 ; オートモードの処理 ; オートモードが否かを格納する変数 numalias is_automode,%0:inc %0 numalias automode_a,100 ; 一文字50ミリ秒 numalias automode_b,300 ; 最低限、300ミリ秒待つ ; オートモードの待ち時間のコンフィグ numalias automode_speed,%2:inc %2 return *start_text ; 文字速度の初期設定 if %global_initialize=0 mov %text_speed,40 if %global_initialize=0 mov %automode_speed,5 ; 文字速度をそれに設定する。 textspeed %text_speed return *pretext_lb ; タグを取得する。 gettag $gettag1,$gettag2,$gettag3 ; 現在の表示内容を取得しておく。 getlogtext $text_pre,0 len %text_pre,$text_pre ; $gettag1が空でなければ、ネームプレート処理をする。 notif_str_gosub $gettag1,"",*pretext_lb_talker ; ボイスがあった時の処理 notif_str_gosub $gettag2,"",*pretext_lb_voice ; 念のため、表示 texton print 1 ; 念のため、文字速度を設定 textspeed %text_speed return *pretext_lb_talker ; $gettag1があれば、それを表示する名前にする。 mov $talker_name,$gettag1 mov $talker_label,$gettag1 ; $gettag3があれば、それをネームプレートにするが、内部的には発言者は変わらない。 len %gettag3,$gettag3 skip 1 + 1/(%gettag3+1) ; 飛ばす処理 mov $talker_label,$gettag3 ; 表示する。 putname $talker_label return *pretext_lb_voice ; 仮のファイル名を作成 mov $voice_temp,voice_folder+$gettag2+voice_extension ; ファイルの存在確認 fileexist %fileexist,$voice_temp ; なければ何もしない if_int_return %fileexist,0 ; 存在するので、ファイルとして登録 mov $voice_playing,$voice_temp ; 名前も確定しているはずなので、演奏する。 voice $talker_name,$voice_playing ; $voice_playing に登録があれば、それはボイスボタンで再生できるとする。 return *text_lb ; 現在の表示内容を取得しておく。 getlogtext $text_before,0 len %text_before,$text_before ; 前回から、何文字テキストが増えているかを取得する。 mov %text_add,%text_before-%text_pre *text_lb_loop1 ; スキップモードなら、すぐに飛ばす。 isskip %is_skip if_int_goto %is_skip,1,*text_lb_loop3 ; CTRLは例外とする。 checkkey %checkkey,"CTRL":skip %checkkey+1 wait_noinput ; キーアップまで待つ。 ; 入力待ち設定開始 bclear ; オートモードなら、時間待ち設定をする。 if_int_gosub %is_automode,1,*automode_btime *text_lb_loop2 bexec $bexec,%bexec *text_lb_loop3 ; スキップモードの判定と、スキップモードへの変更 if_str_gosub $bexec,"K",*skipon ; スキップモードを取得 isskip %is_skip ; スキップモードなら、飛ばす。 if_int_goto %is_skip,1,*text_lb_end ; オートモードの判別 if_str_gosub $bexec,"A",*automode_change ; クイックセーブとクイックロード if_str_gosub $bexec,"Q",*text_quick_save if_str_gosub $bexec,"W",*text_quick_load ; ボイス再生 if_str_gosub $bexec,"V",*text_voice_replay ; 次に進む処理 if_str_goto $bexec,"LCLICK",*text_lb_end if_str_goto $bexec,"SPACE",*text_lb_end if_str_goto $bexec,"RETURN",*text_lb_end if_str_goto $bexec,"WHEELDOWN",*text_lb_end if_str_goto $bexec,"PAGEDOWN",*text_lb_end if_str_goto $bexec,"CTRL",*text_lb_end if_str_goto $bexec,"TIMEOUT",*text_lb_end ; 正しい入力ではなかったので、ループする。再入力待ち goto *text_lb_loop2 ; 次に進む。 *text_lb_end ; \マークで来ていたら、テキストウィンドウの中身を消す。 texec ; 現在の表示内容を取得しておく。 getlogtext $text_after,0 len %text_after,$text_after ; もし、最後の表示内容の長さが0になっていれば、テキストが消去された可能性がある。 if_int_gosub %text_after,0,*check_textclear return ; テキストウィンドウの中身が消去されたかどうかを確認するルーチン *check_textclear ; texec直前のテキストウィンドウの中身が存在していなければ、変化なしと判断する。 if_large_goto %text_before,%text_after,*check_textclear_main return *check_textclear_main ; ここに来たと言うことは、textclearが実行されたと判断する。 ; やるべきことは、 ; 1.今まで表示していた内容(発言者欄・ボイス・テキスト)のバックログへの追加(未実装) ; 2.発言者欄の消去 ; 3.現在再生しているボイスファイルの削除 ; 発言者欄の消去 nameclear print 1 ; ボイスファイルの削除 mov $voice_playing,"" return *texton ; 既に表示状態なら、何もしない。 if_int_return %text_visible,1 ; 一連の処理その1 gosub *print_textwindow gosub *print_nameplate ; 画面を更新 print 1 ; デフォルトの処理をする。 _texton ; フラグ管理 mov %text_visible,1 return *textoff ; 既に非表示状態なら、何もしない。 if_int_return %text_visible,0 ; 一連の処理その2 gosub *delete_textwindow gosub *delete_nameplate ; 画面を更新 print 1 ; デフォルトの処理をする。 _textoff ; フラグ管理 mov %text_visible,0 return *automode_btime ; 待ち時間を決める。 btime ( %text_add * automode_a + automode_b ) * %automode_speed / 10 return ; オートモードを切り替える。 *automode_change mov %is_automode,1-%is_automode return *text_lb_loop1 ; クイックセーブ *text_quick_save gosub *quick_save return *text_lb_loop1 ; クイックロード *text_quick_load gosub *quick_load return *text_lb_loop1 ; ボイス再生 *text_voice_replay ; ボイスがあるかどうか確認。 if_str_goto $voice_playing,"",*text_voice_replay_end ; ボイスがあれば、再生する。 se $voice_playing *text_voice_replay_end return *text_lb_loop1 *define_nameplate ; スプライト設定 ; 発言者欄 numalias sp_nameplate,%1:dec %1 ; 発言者欄のスプライトファイル numalias nameplate_file,%0:inc %0 ; 発言者欄の各値 numalias nameplate_x,%0:inc %0 numalias nameplate_y,%0:inc %0 numalias nameplate_width,%0:inc %0 numalias nameplate_height,%0:inc %0 ; 発言者名の各値 numalias sp_name,%1:dec %1 ; 発言者欄の各値 numalias name_x,%0:inc %0 numalias name_y,%0:inc %0 numalias name_width,%0:inc %0 numalias name_height,%0:inc %0 ; 表示する発言者名 numalias name_string,%0:inc %0 ; 現在、発言者名が設定されているかいないか。 numalias name_exist,%0:inc %0 ; 発言者欄の初期化命令 defsub set_nameplate ; 発言者名に文字を出力 defsub putname ; 発言者名を削除する命令 defsub nameclear return *start_nameplate ; ファイルの設定 if $nameplate_file="" mov $nameplate_file,":c;>100,30,#888888" ; 初期化 set_nameplate return ; ネームプレートの初期化 *set_nameplate ; ネームプレートのファイルの読み込み。不透明度はテキストウィンドウと同じ。 lsph sp_nameplate,$nameplate_file,0,0,%textwindow_alpha csp sp_name ; 念のため、今表示している名前は削除 mov %name_exist,0 ; サイズの取得 getspsize sp_nameplate,%nameplate_width,%nameplate_height ; 位置を決定 ; テキストウィンドウの左上にくっつける。 mov %nameplate_x,%textwindow_x mov %nameplate_y,%textwindow_y-%nameplate_height ; 位置を操作 amsp sp_nameplate,%nameplate_x,%nameplate_y return ; ネームプレートに文字を表示する。 *putname ; 表示する文字列を取得する。 getparam $name_string ; 文字列をスプライト化する。不透明度は255で固定 lsph sp_name,$font_sprite+$font_color+$name_string,0,0,255 ; 大きさを取得 getspsize sp_name,%name_width,%name_height ; 正しい位置を計算 mov %name_x,%nameplate_x+%nameplate_width/2-%name_width/2 mov %name_y,%nameplate_y+%nameplate_height/2-%name_height/2 ; 正しい位置に移動 amsp sp_name,%name_x,%name_y vsp sp_name,1 ; フラグ管理 mov %name_exist,1 return *nameclear ; スプライトを削除 csp sp_name ; フラグ管理 mov %name_exist,0 return ; ネームプレートを表示する。 *print_nameplate vsp sp_nameplate,1 vsp sp_name,%name_exist return ; ネームプレートを非表示にする。 *delete_nameplate vsp sp_nameplate,0 vsp sp_name,0 return *define_saveload ; セーブデータを格納するフォルダを決める。 savedir "savedata" ; セーブデータの最大数。デフォルトの右クリックメニューを使うのでない限り実は意味がない。 savenumber 200 ; クイックセーブに使う番号 numalias quick_savedata,200 ; イエス・ノー numalias saveload_yesno,%0:inc %0 return *start_saveload return *quick_save savegame quick_savedata mesbox "クイックセーブしました。","Quick Save" return *quick_load yesnobox %saveload_yesno,"クイックロードしますか?","Quick Load" if_int_return %saveload_yesno,0 loadgame quick_savedata return *define_bexec ; bexec回りの定義 ; 専用変数 numalias bexec,%0:inc %0 ; 何も入力がない状態まで待つ関数 defsub wait_noinput ; checkkey用専用変数 numalias checkkey,%0:inc %0 return *wait_noinput bclear ; 時間待ちをする。 btime 10 ; 入力待ち bexec $bexec,%bexec ; 入力がタイムアウトでなければ何もしない。 if_str_return $bexec,"TIMEOUT" goto *wait_noinput *define_debug ; デバッグログを有効にする。 debuglog 1 return *define_exec ; exec_dll関係 ; 命令群を作成 defsub exec_clear defsub exec_setdll defsub exec_arg defsub exec_arg_int defsub execute stralias exec_slush,"/" stralias exec_comma,"," ; 実行する文字列全体 numalias exec_string,%0:inc %0 ; 実行するdll名 numalias exec_dllname,%0:inc %0 ; 引数 numalias exec_arg,%0:inc %0 ; 引数の数 numalias exec_arg_count,%0:inc %0 ; 結果を受け取る専用変数 numalias getret,%0:inc %0 return *exec_clear ; 初期化 mov $exec_dllname,"" mov %exec_arg_count,0 mov $exec_string,"" return *exec_setdll exec_clear getparam $exec_dllname mov $exec_string,$exec_dllname add $exec_string,exec_slush return *exec_arg getparam $exec_arg skip 2-1/(1+%exec_arg_count) add $exec_string,exec_comma add $exec_string,$exec_arg inc %exec_arg_count return *execute exec_dll $exec_string ; 結果を先に受け取っておく。 getret $getret getret %getret exec_setdll $exec_dllname return *define_fileexist ; fileexist専用変数 numalias fileexist,%0:inc %0 return *define_if ; ifの代替命令群の定義 defsub if_str_goto defsub if_str_gosub defsub if_int_goto defsub if_int_gosub defsub notif_str_goto defsub notif_str_gosub defsub notif_int_goto defsub notif_int_gosub defsub if_str_return defsub if_int_return defsub notif_str_return defsub notif_int_return defsub if_large_goto defsub if_small_goto defsub if_large_gosub defsub if_small_gosub defsub if_large_return defsub if_small_return numalias if_a,%0:inc %0 numalias if_b,%0:inc %0 numalias if_label,%0:inc %0 return *start_if if_str_goto ""," ",*dummy if_str_gosub ""," ",*dummy if_int_goto 0,1,*dummy if_int_gosub 0,1,*dummy notif_str_goto "","",*dummy notif_str_gosub "","",*dummy notif_int_goto 0,0,*dummy notif_int_gosub 0,0,*dummy if_str_return ""," " if_int_return 0,1 notif_str_return "","" notif_int_return 0,0 if_str_gosub "","",*if_in_advance_dummy if_str_goto "","",*if_in_advance1 *if_in_advance1 if_int_gosub 0,0,*if_in_advance_dummy if_int_goto 0,0,*if_in_advance2 *if_in_advance2 notif_str_gosub ""," ",*if_in_advance_dummy notif_str_goto ""," ",*if_in_advance3 *if_in_advance3 notif_int_gosub 0,1,*if_in_advance_dummy notif_int_goto 0,1,*if_in_advance4 *if_in_advance4 gosub *start_if1 gosub *start_if2 gosub *start_if3 gosub *start_if4 if_large_goto 0,0,*if_in_advance_dummy if_small_goto 0,0,*if_in_advance_dummy if_large_gosub 0,0,*if_in_advance_dummy if_small_gosub 0,0,*if_in_advance_dummy if_large_return 0,0 if_small_return 0,0 if_large_goto 1,0,*if_in_advance5 *if_in_advance5 if_large_goto 0,1,*if_in_advance6 *if_in_advance6 gosub *start_if5 gosub *start_if6 return *start_if1 if_str_return "","" return *start_if2 if_int_return 0,0 return *start_if3 notif_str_return ""," " return *start_if4 notif_int_return 0,1 return *start_if5 if_large_return 1,0 return *start_if6 if_small_return 0,1 return ; if 代替命令群本体ルーチン *if_str_goto getparam $if_a,$if_b,$if_label if $if_a=$if_b return $if_label return *if_str_gosub getparam $if_a,$if_b,$if_label if $if_a=$if_b goto $if_label return *if_int_goto getparam %if_a,%if_b,$if_label if %if_a=%if_b return $if_label return *if_int_gosub getparam %if_a,%if_b,$if_label if %if_a=%if_b goto $if_label return *notif_str_goto getparam $if_a,$if_b,$if_label notif $if_a=$if_b return $if_label return *notif_str_gosub getparam $if_a,$if_b,$if_label notif $if_a=$if_b goto $if_label return *notif_int_goto getparam %if_a,%if_b,$if_label notif %if_a=%if_b return $if_label return *notif_int_gosub getparam %if_a,%if_b,$if_label notif %if_a=%if_b goto $if_label return *if_int_return getparam %if_a,%if_b if %if_a=%if_b return *if_in_advance_dummy return *if_str_return getparam $if_a,$if_b if $if_a=$if_b return *if_in_advance_dummy return *notif_int_return getparam %if_a,%if_b notif %if_a=%if_b return *if_in_advance_dummy return *notif_str_return getparam $if_a,$if_b notif $if_a=$if_b return *if_in_advance_dummy return *if_large_goto getparam %if_a,%if_b,$if_label if %if_a>%if_b goto $if_label return *if_small_goto getparam %if_a,%if_b,$if_label if %if_a<%if_b goto $if_label return *if_large_gosub getparam %if_a,%if_b,$if_label if %if_a>%if_b gosub $if_label return *if_small_gosub getparam %if_a,%if_b,$if_label if %if_a<%if_b gosub $if_label return *if_large_return getparam %if_a,%if_b if %if_a>%if_b return *if_in_advance_dummy return *if_small_return getparam %if_a,%if_b if %if_a<%if_b return *if_in_advance_dummy return *if_in_advance_dummy ; 何もしないよ。 return *define_linear ; linear命令を作成 defsub linear ; linear命令で使う変数を定義 numalias ln_x,%0:inc %0 numalias ln_y,%0:inc %0 numalias ln_a,%0:inc %0 numalias ln_b,%0:inc %0 numalias ln_c,%0:inc %0 numalias ln_d,%0:inc %0 return ; 数直線上に点aとbとxがあるとする。 ; 別の数直線上に点cと点dがあるとする。 ; 点aと点cが対応し、点bと点dが対応する時、 ; 点xと対応する点yはどうなるか。 *linear ; 引数の取得 getparam %ln_a,%ln_b,%ln_x,%ln_c,%ln_d,i%ln_y ; 回答の初期化 mov %%ln_y,0 ; %ln_cと%ln_dが同値なら、回答が不定になってしまうので何もせずに返す。 if_int_return %ln_b-%ln_a,0 ; 計算する。 mov %%ln_y,%ln_c+(%ln_d-%ln_c)*(%ln_x-%ln_a)/(%ln_b-%ln_a) return *define_newsposition ; 画面内の位置のNEWS指定 defsub news_position numalias news_ax,%0:inc %0 numalias news_ay,%0:inc %0 numalias news_x,%0:inc %0 numalias news_y,%0:inc %0 numalias parent_width,%0:inc %0 numalias parent_height,%0:inc %0 numalias child_width,%0:inc %0 numalias child_height,%0:inc %0 return *news_position ; ある領域の中で、小さな領域を配置する時のための座標を計算する。 getparam i%news_x,i%news_y,%parent_width,%parent_height,%child_width,%child_height,%news_ax,%news_ay mov %%news_x,%parent_width-%child_width if %news_ax=-1 mov %%news_x,0 if %news_ax=0 div %%news_x,2 mov %%news_y,%parent_height-%child_height if %news_ay=-1 mov %%news_y,0 if %news_ay=0 div %%news_y,2 return *define_skip ; skiponを作成し、skipoffを上書きする。 defsub skipon defsub skipoff ; スキップ状態を格納する変数 numalias is_skip,%0:inc %0 return *start_skip ; 一回実行しておく。 skipon skipoff return *skipon ; スキップ状態にする。 systemcall skip isskip %is_skip return *skipoff ; スキップ状態を解除する。 _skipoff isskip %is_skip return *define_sound ; BGM/BGV/SEの音量(グローバル) numalias bgm_vol,%2:inc %2 numalias bgv_vol,%2:inc %2 numalias se_vol,%2:inc %2 ; ボイスループ用変数 numalias voice_loop,%0:inc %0 ; ボイスボリューム numalias voice_vol,%0:inc %0 ; 配列にする。 dim ?voice_vol[cast_max+1] for %voice_loop=1 to cast_max mov ?voice_vol[%voice_loop],%2:inc %2 ; グローバル変数を割り当てる。 next ; ボイスモード(グローバル) numalias voice_mode,%2:inc %2 ; ボイスモードの数値の意味 numalias single,0 ; 単一再生 numalias mulch,1 ; 多重再生を許す ; BGM命令を上書きして、自動でボリュームも設定するようにする。 defsub bgm defsub bgmstop numalias bgm_file,%0:inc %0 ; BGV命令を作る。 defsub bgv defsub bgvstop ; チャンネルを49に。(適当) numalias bgv_channel,49 numalias bgv_file,%0:inc %0 ; SE命令を作る。単発専用。 ; 空いているチャンネルを自動で選ぶ。 defsub se ; 使っていいチャンネルの範囲 numalias se_channel_first,10 numalias se_channel_last,45 numalias se_channel,%0:inc %0 numalias se_file,%0:inc %0 defsub se_channel_countup ; ボイス用命令 defsub voice ; キャラクターの名前とファイルを指定する。 ; キャラクターの名前からボリュームを取得してファイルを演奏する。 ; ただし、ボリュームが0の場合、演奏はしない。 ; チャンネルは、ボイスモードがsingleなら0で確定。mulchなら、適当にバラけさせる。 numalias voice_castname,%0:inc %0 numalias voice_volume,%0:inc %0 numalias voice_file,%0:inc %0 ; ボイスを格納するフォルダ stralias voice_folder,"voice\" ; ボイスファイルの拡張子 stralias voice_extension,".ogg" ; ボリューム関連 defsub chvol ; 上書きする。 numalias chvol_ch,%0:inc %0 numalias chvol_vol,%0:inc %0 numalias chvol_loop,%0:inc %0 dim ?chvol_vol[50] return *start_sound ; 初期設定 if %global_initialize=1 goto *start_sound2 mov %bgm_vol,50 mov %bgv_vol,50 mov %se_vol,50 for %voice_loop=1 to cast_max mov %?voice_vol[%voice_loop],50 next mov %voice_mode,single *start_sound2 ; SEのボリュームだけは設定しておく。 sevol %se_vol ; 使っていいチャンネルの設定 gosub *se_channel_countup_down return *bgm ; 演奏するファイルを取得 getparam $bgm_file ; 演奏開始 _bgm $bgm_file ; ボリュームを設定 bgmvol %bgm_vol return *bgmstop ; 演奏停止 _bgmstop mov $bgm_file,"" return *bgv ; 演奏するファイルを取得 getparam $bgv_file ; 演奏開始 dwaveloop bgv_channel,$bgv_file ; ボリュームを設定 chvol bgv_channel,%bgv_vol return *bgvstop ; 演奏停止 dwavestop bgv_channel mov $bgv_file,"" return *se ; 演奏するファイル名を取得 getparam $se_file ; 演奏する。 dwave %se_channel,$se_file chvol %se_channel,%se_vol ; 次のためにチャンネルを変える。 se_channel_countup return *se_channel_countup ; カウントアップ inc %se_channel if_large_gosub %se_channel,se_channel_last,*se_channel_countup_down return *se_channel_countup_down ; 最低値に戻す mov %se_channel,se_channel_first return *voice getparam $voice_castname,$voice_file ; ボリュームは0にしておく mov %voice_volume,0 ; 名前を番号に変換 name2number %voice_castname,$voice_castname ; 登録のない名前なら何もしないで終る。 if_int_return %voice_castname,0 ; ボリュームを取得 mov %voice_volume,%?voice_vol[%voice_castname] ; ボリュームが0なら、やはり演奏しない。 if_int_return %voice_volume,0 ; オートモードならば、再生までしばらく待つ。 if_int_gosub %is_automode,1,*voice_wait ; 演奏する(ボイスモードで分岐) dwave %voice_mode*%se_channel,$voice_file chvol %voice_mode*%se_channel,%voice_volume se_channel_countup ; 0でもカウントアップする。減るもんじゃなし。 return *voice_wait bclear btime 1,1 bexec $bexec,%bexec notif_str_goto $bexec,"TIMEOUT",*voice_wait return *chvol getparam %chvol_ch,%chvol_vol _chvol %chvol_ch,%chvol_vol mov ?chvol_vol[%chvol_ch],%chvol_vol return *loadgosub_chvol ; 音のサイズを再現する。 for %chvol_loop=0 to 49 _chvol %chvol_loop,?chvol_vol[%chvol_loop] next return *define_sprite ; getspsize用汎用変数 numalias getspsize_width,%0:inc %0 numalias getspsize_height,%0:inc %0 ; 中心部を指定してスプライトを動かすamspラッパー defsub camsp ; それ用の変数 numalias camsp_sp,%0:inc %0 numalias camsp_x,%0:inc %0 numalias camsp_y,%0:inc %0 return *start_sprite return ; amspのラッパー ; 点を指定すると、そこが中心点になるようにスプライトを動かす。 *camsp getparam %camsp_sp,%camsp_x,%camsp_y getspsize %camsp_sp,%getspsize_width,%getspsize_height div %getspsize_width,2 div %getspsize_height,2 amsp %camsp_sp,%camsp_x-%getspsize_width,%camsp_y-%getspsize_y return *start_global ; グローバル変数の初期化はしたと言う印。 mov %global_initialize,1 return
システムカスタマイズについてダラダラやるよーその9
システムカスタマイズについてダラダラやるよーその8 - 永字八法の続き。
NScripterのシステムカスタマイズについて、1から話をしてみようと思う。その第9回目。
今回はオートモードについて。
オートモード
何も操作しなくても、一定時間ごとにクリックを押したのと同じ扱いになるモード。
元々NScripterにもデフォルトで存在しているが、何か操作すると解除されると言う弱装版である。
現在のところ、ユーザーの要求では、選択肢などがあったとしても解除されない強装版が求められているようなので、本稿でもそれを実装してみた。
現在のところ、Aキーでオートモードのオンオフが切り替えられるようになっている。
どれくらい待つのか。
ボイスの有無で少し変わる。
ボイスがない場合は、文字数の長さに比例+最低限の時間が待ち時間になる。
ボイスがある場合は、ボイスモードによる。
ボイスとの関係
ボイスモードと関係する。
ボイスモードがマルチであれば、ボイスの長さに関係なくテキストの長さだけが問題となる。
ボイスモードがシングルであれば、やはりボイスの長さに関係なくテキストの長さで待つが、次にボイスが演奏される時には、演奏前に今のボイスの演奏終了を待つ処理が入る。
次回予告
現在のスクリプト
00.txt
;$V2000G1000S800,600L10000
01.txt
*start gosub *start_window gosub *start_cast gosub *start_textwindow gosub *start_text gosub *start_nameplate gosub *start_saveload gosub *start_if gosub *start_if1 gosub *start_if2 gosub *start_if3 gosub *start_if4 gosub *start_if5 gosub *start_if6 gosub *start_skip gosub *start_sound gosub *start_sprite gosub *start_global
10.txt
click [キャラ1/0001] うぐう。\ 名前欄が消えるかな?\ [キャラ2/0002] が、がお。\ もう一度、消えるかな?\ [キャラ3/0003] ぶらーぼ\ [キャラ15/0004] [キャラ4/0006] あ\ [/0007] い\ [キャラ6/0008] う\ え\ お\ か\ き\ く\ け\ こ\ さ\ し\ す\ せ\ そ\ た\ ち\ つ\ て\ と\
97.txt
end *define gosub *define_numalias gosub *define_global gosub *define_window gosub *define_background gosub *define_cast gosub *define_textwindow gosub *define_text gosub *define_nameplate gosub *define_saveload gosub *define_bexec gosub *define_debug gosub *define_exec gosub *define_fileexist gosub *define_if gosub *define_linear gosub *define_newsposition gosub *define_skip gosub *define_sound gosub *define_sprite game
98.txt
*loadgosub_lb gosub *loadgosub_chvol return
99.txt
*define_numalias ; numalias 定義用の一時変数 mov %0,100 ; 100番から。 ; スプライト番号は逆に奥から。 mov %1,900 return *define_global