中級者向けTIPS

■ INDEX

01.スプライトリストのススメ  02.汎用変数のススメ  03.サブルーチンのススメ  04.オーバーフロー回避  05.btnwaitについて  06.スクリーンショットの画質  07.高速化  08.セーブのタイミングなど  09.textgosub時の自動saveoffについて  10.リセットとロード  11.音楽ファイルについて(偽装とSTREAMING)  12.スキップについて  13.スキップについて2  14.gettextについて  15.エフェクト用マスク  16.SEデータのループ再生  17.defsubについて(1)配列では受けられない  18.半角文字について  19.bg命令の不思議な挙動  20.ズーム処理の座標について  21.背景回転で欠けがない背景サイズ  22.ボタン定義の特殊事例  23.ボタン定義の特殊事例2  24.スプライトアニメ  25.デコード対策  26.パッチを考えた上でのnsa化  27.座標間の距離を求めたい  28.選択肢カスタマイズの注意点  29.splitの動作メモ  30.getspsizeの動作メモ  31.テキスト表示階層について  32.自動描画範囲について  33.btnwaitについての動作メモ  34.pretextgosubについて  35.セーブデータについて  36.レイヤ順を考える  37.Tabキーは極力使わない  38.シスカマ時のページ毎表示  39.defsubについて(2)必ず消化する  40.日本語ファイル名でスクリプトを管理  41.autosaveoffについて  42.nsaとns2とoggプラグイン  43.btimeについて  44.lchkについて  45.新ボタンとスペースキー  46.ver296の外字について  47.modとif……式と命令の優先順位  48.fileexistはタグなしで  49.filelogはタグなしで  50.defsubについて(3)オーバーロード  51.midの勘違い  52.zenkakkoについて  53.自動でバージョンをチェック 

※ 注意
本サイトでは中級者をシステムカスタマイズを行っている制作者と想定しています。
以下、当時のNScripter公式サンプルに合わせて、textgosubの飛び先ラベル名を*text_lbとして記述します。
記述に対応するバージョン表記をしています(nscr2.82nscr2.95nscr2.96)H25時点の最新はver2.96です。


スプライトリストのススメ

手元の紙なり、PC上でのメモ帳でも構いませんので
「スプライト番号リスト・文字列変数リスト($)・数値変数リスト(%)」
この3種類を必ず作成しておきましょう。これが何よりも大切です。
後々に重複使用してバグを出さないようにする近道となります。
エフェクト効果番号リストも演出を打ち込むときに手元にあると便利です。
ちなみに紛失すると死ぬ思いするのでご注意ください。

(追記)各種リスト印刷用pdfを作成してみました。よろしければご利用ください。
  listpdf.zip ←右クリックして保存を選んでください

△page top

汎用変数のススメ

汎用変数を作っておきましょう。サブルーチンや普段のfor nextで活躍してくれます。
defsub 時の getparam などの一時取得用などにも使えます。
数値変数や文字列変数を両者あらかじめ10個くらいキープしておけば便利でしょう。

(追記)
getparamで受ける変数は、汎用変数を使わずに一つ一つ確保した方がいいかもしれません。
その方がdefsub内でさらにdefsub利用命令を組み合わせた時にバッティングが起きません。
定義説でnumaliasしておき、明示的にやった方が扱いやすいと思われます。
ちなみに、スタックが作れる方は、バッティングを気にしなくて良いのでどんどん利用しましょう。

△page top

サブルーチンのススメ

アイキャッチのルーチンや、画面に出てるスプライトを一時的に隠すルーチンなどなど、
よく使うルーチンは全部サブルーチンにしてしまいましょう。
打つ手間が省け、同時にミスも減り、結果的にコードも綺麗になります。
ちなみにdefsubで作った命令も¥@も実質は単なるサブルーチンです。

何故よく使う記述をサブルーチンとして纏めておいた方がよいのでしょうか?
例えばスクリプトに20箇所ほど似たようなルーチンが点在しているとして、
ミスに気付いて修正する時、手を加えたい時に、その20箇所全てを書き直す手間が生じます。
また、点在している記述毎に変数番号が違ったりした場合には、周りに影響が出ないか確認が必要です。
これをサブルーチンとして一つに纏めておけば修正漏れが起きる可能性がグンと落ちますね。

△page top

オーバーフロー回避

nscr2.82nscr2.95nscr2.96
ボタン待ち判定について(以下例文)


*keywait_loop
spbtn 200,50
btnwait %0
if %0==50 goto *OK;  キー判定のif文
goto *keywait_loop;  該当しないキーだったからから戻す。
;(↑ここで戻さないと、次のコードに流れていく)

例えば上記のように書いたとします。
この例のように、ループ内容に spbtn などのボタン定義文が入っている場合には、
ループが何度も繰り返されたときにオーバーフローしてNスクが落ちてしまいます。
(※具体的には「押さえておきたい仕様など」で触れた、上限値511個を越えたときに落ちます)


*keywait_loop
btndef clear; ←← これが大事
spbtn 200,50
btnwait %0
if %0==50 goto *OK
goto *keywait_loop

必ずループラベルの直後にボタン定義のクリア命令を挟んでおきましょう。
たったこれだけでオーバーフローが回避されます。
触りはじめの間には結構見落としがちな事例なので注意が必要です。

nscr2.95nscr2.96
新ボタンでの例文も追加しておきます。
(※こちらも「押さえておきたい仕様など」で触れた、bspの上限数256個を越えたときに落ちます)


*keywait_loop
bclear; ←← これが大事
bsp 200
bexec $0
if $0=="S200" goto *OK
goto *keywait_loop

△page top

btnwaitについて(textbtnwait・cselbtnwaitも同様)

nscr2.82nscr2.95nscr2.96
初級者向けのところに書こうと思いましたが、こちらに記述しておきます。

コードを実行して、btnwait 命令に来たところで動作が止まることを覚えておきましょう。
そこで、キーボード、マウスなどで何かしら入力した途端に、再び動き始めて次のコードに流れていきます。
重要な点は btnwait 上ではキー取得しかできないこと。
Nスクの特徴である「並列して他の作業が出来ない」という事を理解しておきましょう。

もう一点。このキー取得は、デフォルト状態ではキーダウン時ではなくキーアップ時に行われます。
もしキーダウン時に取得したい場合は btndown 命令をはさむことで変更することが出来ます。

(textbtnwaitはスキップ状態で止まらず0を返すなど少々機能に違いがあります。
(3種類のbtnwait命令は、それぞれの用途に見合った場面で利用しましょう。

△page top

スクリーンショットの画質

nscr2.82nscr2.95
winXPとwin98で動作確認したところ、XPではセーブサムネイルの画質が98機よりも鮮明です。
スクリーンショットの画質はOS依存するようです。

特に目に見える害はなさそうですが、getscreenshot で取得した画像を使い終えましたら、
忘れずに deletescreenshot でメモリから解放しておきましょう。

△page top

高速化

nscr2.82nscr2.95nscr2.96
大前提として、重くなる箇所は画像描画と音楽再生(する為のデータのデコード)です。
その点を留意してコードを組むとユーザさんに快適なシステムを提供出来るのではないでしょうか。
前者はビデオ依存、後者はCPU依存すると思われます。

無意味に repaint を使わないようにしましょう。
repaint は普段の負荷も重いですが特にスキップ低速化の原因になります。
この命令は不定画面の正常化など、必要な場合にのみ利用しましょう。
また、スキップを早くするには effectcut も必須です。スキップは早ければ早い程良いです。

大量のスプライトを描画する場合、lspする毎にprintしていくと非常に動作が重くなります。
たった一瞬であってもバラバラに画面に表示されてしまうので、見た目もよろしくありませんね。
そこで、纏めてlspした後に一度のprintで画面に描画すると綺麗で動作も軽くなります。
演出上の制約が無い限りは、このように、描画の回数を出来るだけ少なく組んでいきましょう。

setwindowでのウィンドウ範囲は常に再描画対象になりますので、その範囲が小さいほど早くなります。
もちろん背景指定する画像も大きいほど重くなります。必要サイズへのスリムアップは必須ですね。

画像ファイルはnsaアーカイブからデコードした後に、メモリに読み込みます。その後描画などを行いますね。
このアーカイブからの読み込み時間が意外と曲者です。(これはCPU依存)
生データ時には最速であったBMPファイルが、逆にそのファイルサイズのお陰でデコード時間分遅くなります。
アーカイブ化した後はJPGやPNGデータの方が表示が軽くなるという逆転現象が起こります。
状況に合わせ、JPGを使っても問題ない画像にはJPGをと、柔軟に最適な画像形式を利用しましょう。

コンフィグ画面や右クリックメニューなど、何度も使い回す画像の場合、一々lsp、cspを行うよりも、
事前にlsphで読んでおいて、必要時にvsp ?,0、vsp ?,1で管理してprintさせた方が軽くなります。
特に低スペックマシンや、処理するファイルが多くなるほど実感できます。
これは、スプライト読み込みのlsp命令、スプライト消去のcsp命令もそれぞれ一定の処理時間がかかるためです。
下記のコードを実行すれば、定義と削除だけの命令にもスペックによってかなり負荷がかかることがわかります。


;どんなCGでもいいので、適当にリネームして「test.jpg」を用意してください。
;放置しておけば処理は終了します。画像ファイルサイズによっては相当重くなります。
resettimer
for %0=0 to 999:lsp %0,"test.jpg",0,0:next
for %0=0 to 999:csp %0:next
gettimer %0
処理時間は%0ミリ秒でした。¥

saveoff を記述すると、セーブ情報の準備を行わなくなる(※次項にて解説)ために動作が軽くなります。
複数行に渡るサブルーチンなどで事前に記述しておくと見違える程の効果があります。
例えば、スプライトの大量描画前にはほぼ必須と言ってよいでしょう。

システムカスタマイズを行う場合には、テキストのキー待ちルーチン(*text_lb)入るときに、
ルーチンの頭で saveoff を、texec直後に saveon を書いておきましょう。

巨大な画像を動かす場合について、
msp を使って1ピクセルずつ動かすと低スペックマシンでは非常に重く感じます。
代わりにbltで描画した方が圧倒的に早く処理が出来ます。
bltが使えそうな場面では迷わずこちらを選択しましょう。
また、msp・amspを使った場合でも、ある程度の stepを入れておくか、加速を付けると、
随分と体感速度が変わります。色々と試してみましょう。
もし、全画面のスクロールであるなら、エフェクト番号11〜14番が便利です。
繋がる背景を二枚用意してそちらで表示させると、綺麗で負荷が軽く、時間指定まで可能になります。
そして、これらの処理においても saveoff を事前に行っておくと処理が非常に軽くなります。

△page top

セーブのタイミング。セーブについて色々

nscr2.82nscr2.95nscr2.96
セーブは「行単位」で準備されます。「ラベル単位」ではありません。
スクリプトの次行に入る度に毎回セーブ準備を行っている様子です。
データ内容は「スクリプトの再開行、通常変数の値、スプライト内容、再生中BGM情報」等でしょう。

saveoff しておくとNスクの動作が軽くなるのはこのセーブ準備を行わなくなるからです。
起動時のデフォルトが saveon 状態です。
一度 saveoff しますと、次にsaveon が書かれるまでセーブ情報の準備を行わなくなります。

saveoff している間に書かれた savegame 命令では、
最後にセーブ準備された内容、つまりsaveoff 直前行までの内容をsave??.datに書き出します。
そのデータを loadgame でロードしますと、先のsaveoffの直前行から再開となります。

これらを把握して使わないと、ロードした瞬間想定外の位置からスタートしてしまうことがあります。
例えば、saveoff させた後に saveon し忘れたスクリプトにおいて、
ゲーム終盤でセーブした後にロードしても、「あれ?ここゲームの頭?」といった状況が発生します。
さしあたり慣れるまでは、前項の高速化にて触れたように
*text_lbの頭で saveoff を、texec直後に saveon を書いておけばひとまず問題ありません。

△page top

textgosub時の自動saveoffについて

nscr2.82nscr2.95nscr2.96
少々複雑ですが解説してみます。
シスカマ時には、前提として覚えておかなければいけないNScripterの隠れ仕様が2点あります。

まず、システムカスタマイズを行っている状態、つまりtextgosubを設定している場合では
テキスト行の冒頭において必ず自動的にsaveoffが行われます。

これは、pretextgosubを利用している場合においても同様です。システムカスタマイズ状態では
テキスト行にさしかかる度に「毎回セーブ準備フラグはOFFになる」と押さえておいてください。

次に、Nスク自体に「自動saveoff範囲というものが存在」します。
テキスト行の冒頭からその次のtextclearまでがその範囲となります。

(※texecでは¥の場合にtextclearを実行しますので、¥時のtexecまでと考えてください)

この間に何度saveon命令を挟んで準備フラグをONにしても、セーブ準備を行いません。
そこで、「自動saveoff範囲の入出の際に、準備フラグの操作は行われない」ことが重要です。
こちらについてはシステムカスタマイズを行っていてもいなくても固定の仕様です。

上記の2点はNScripterの基本仕様であり(ver2.93より前のバージョンでは)変更出来ません。
これらを押さえておかないとシステムカスタマイズ時に色々と悩まされる事になります。

nscr2.82
具体的にシステムカスタマイズされたスクリプトを動かして検証してみましょう。

1.*text_lb内部で一切saveon/offを記述しない場合。
  テキスト行冒頭で勝手にsaveoffが呼ばれ、セーブ準備フラグがOFFになっていますので、
  その先どこかで saveon しておかない限り、延々とセーブ情報が作られません。
  終盤まで読み進んだ先でセーブをしても、ゲーム先頭のテキストからロードとなってしまいます。

2.*text_lbの頭で saveoff を記述、texecの直後に saveon を記述した場合。
  問題なく動作します。
  テキスト行冒頭で自動でsaveoffが呼ばれているので、実はsaveoffを記す必要はありませんが、
  後で読むときにon/offの対がわかりやすくなります。(onはreturn直前でも良いです)

3.*text_lbの頭で saveon のみを記述した場合。
  問題なく動作します。
  ルーチンに入ってすぐにセーブ準備フラグをONに戻しましたが、
  自動saveoffの範囲内ですので、¥時のtexecまではセーブ準備が行われません。

前項、前々項から勧めていたように2番の記述で書くと直感的に動作が分かりやすいでしょう。

(自動saveoff範囲が本当に存在するのかなど、細かい部分を知りたい方は、
(動作確認に使った簡単なスクリプトを置いておきますので  ←こちらを参照してください。
(また、後述の「34.pretextgosubについて」にて範囲を図示をしてあります。

nscr2.95nscr2.96
ver2.93以降で仕様が変わりました。
「自動saveoff範囲」についての記述が厳格化されているために注意が必要です。
どう変わったのか、スクリプトを実行して検証してみました。

1.*text_lb内部で一切saveon/offを記述しない場合。
  テキスト行冒頭で勝手にsaveoffが呼ばれ、セーブ準備フラグがOFFになっていますので、
  その先どこかで saveon しておかない限り、延々とセーブ情報が作られません。
  終盤まで読み進んだ先でセーブをしても、ゲーム先頭のテキストからロードとなってしまいます。

2.*text_lbの頭で saveoff を記述、texecの直後に saveon を記述した場合。
  問題なく動作します。
  テキスト行冒頭で自動でsaveoffが呼ばれているので、実はsaveoffを記す必要はありませんが、
  後で読むときにon/offの対がわかりやすくなります。(onはreturn直前でも良いです)

3.*text_lbの頭で saveon のみを記述した場合。
  うまく動作しなくなりました。
  ルーチンに入ってすぐにセーブ準備フラグをONに戻したつもりですが効いていません。
  自動saveoff範囲内でのフラグ操作は無視されるようになったと考えられます。
  そのため、2番のようにtexec以降にsaveonを記述する必要があります。
  『あどばんすどNScripter オフィシャルガイド』ではこの記述法なので最新エンジンではバグります。
  同書スクリプト中のtexec直後にsaveonをもう一度記述すればOKです。

つまりシステムカスタマイズは必ず2番の記述で書くようにしなくてはいけません。

また、「テキスト行頭の自動saveoff」という仕様については、
ver2.93から追加されたautosaveoff命令で変更出来るようになりました。
これについては41.autosaveoffについてにて後述します。

△page top

リセットとロード

nscr2.82nscr2.95nscr2.96
おまじない。
RESETloadgameする際には、直前にcsp -1を挟んでおきましょう。

dwaveで長めの効果音を再生している状態でRESETloadgameを行っても、
命令時点で音が切れません。命令先のタイトルやロード先でも効果音が途切れずに続いてしまいます。
普段は特に気にする必要はありませんが、再生時間が長い効果音を使う場合には、
RESETloadgame時に先に効果音を止める処理を入れましょう。
ちなみに、dwaveplayloopなどで再生しているループ効果音は命令時点で音が止まってくれます。

ループ効果音情報はセーブデータに確保されません。
例えば、dwaveplayloop 1で効果音をループ再生中にセーブ。
そのデータをロードしてもループ効果音は自動で再演奏されません。
そのためdefsub等で効果音ループ命令を作成し、変数にフラグを確保した上でループ再生。
loadgosubラベルにてそのフラグを判断し、当該データを再演奏。といった形にする必要があります。

(記述の変更に関して)
2005年当時のメモだったので、「スプライトをリセットしてくれない」という状況再現が出来ません(汗)
当時、ログ自作でかなり苦労してcsp -1で解決した記憶があるのですが……。
最近の某所でも報告がありますし、やはりこの問題は残っているのではないかと思われます。
どなたか再現スクリプトがありましたら提供頂けますと助かります。
念のため、おまじないといった形でこちらに記述を残しておきました。

△page top

音楽ファイルについて

音楽ファイルの偽装

nscr2.82nscr2.95nscr2.96
たとえば「music01.mp3」を「music01.dat」と拡張子を変えても再生することができます。
単純な偽装ですが一定の効果はあるでしょう。mpgなどの動画ファイルでも有効なテクニックです。
生ファイルをアーカイブ外に置く場合にお世話になる場合があるかもしれません。

生ファイルの場合、仕様外ですが「日本語ファイル名」の音楽も読み込んで再生することができます。
例えば「情景A.mp3」だとか、それを拡張子偽装した「情景A.dat」もいけます。
(ただし、ver2.95でnsogg2.dllを利用している場合には、日本語ファイル名まではいけますが、
(加えて拡張子偽装があると読み込めません。(ver2.82のnsogg.dll有では再生できました)

余談ですが、mp3はパテント関係で結構面倒のようです。
何やら頒布数5000越えだとライセンス問題が発生するとか何とか。
詳しくは「フラウンホーファー mp3 パテント」等々のワードで検索してみましょう。
そのため、当サイトではそういった面で不安の無いoggファイルの利用を推奨します。

ストリーミング再生について

nsa/ns2アーカイブ内に音楽ファイルを入れておくと、基本的にはデコードしてから再生を行います。
つまり、ファイルサイズの大きなBGMを使う場合は毎度デコードを待っての再生になるので重くなります。
(生ファイルの場合はデコードする必要はないので一瞬です)

この問題はプラグインを利用することで解決します。ストリーミングという再生方法では、
データ終端までデコードを終えなくても、読み込んだ分から先に音声データを再生することができます。
つまり、デコードし終わるのを待つ必要がなくなり、体感的に非常に軽くなるワケです。

nscr2.82
外部プラグインを利用することでoggのストリーミング再生を行うことが出来ます。
ver2.82ではNスク公式で過去配布されていたnsogg.dll、またはnscrplgさんのNScripterDS.dllが利用できます。
前者は置くだけですが単機能。後者は多彩な機能があって素晴らしいのですがスクリプト技術が必要です。
現時点でver2.82エンジンを使われる方は是非NScripterDS.dllを利用してみてください。

nscr2.95nscr2.96
外部プラグインを利用することでoggのストリーミング再生を行うことが出来ます。
ver2.95ではns2アーカイブに対応するnsogg2.dllを利用します。
最新版パッケージの「実行ファイル/DLL」に入っています。使い方は置くだけでOK。
このDLLはそのままでもいくつか機能がありますが、Luaとの連携で真価を発揮しますので、
Luaが使える方は音楽再生周りを色々と触ってみてください。演出で非常に便利です。

△page top

スキップについて

nscr2.82nscr2.95nscr2.96
スキップ中の挙動は
 textbtnwait %0 で自動的に 0(左クリック)を返します。
スキップ終了時(クリックやスペース等で止めた時)には
 textbtnwait %0 の上で待機します。つまり終了と同時の並列作業は実行不可。

ただし、getskipoff時のみ、textbtnwait %0上で待機せずに-60をもって流れます。
これによってスキップ終了直後に作業させることがが可能となります。
この場合、何か作業させた後にボタン待ちのループに戻しておくのを忘れないようにしましょう。
また、後述する通り、未読行で既読スキップが止まった場合-60は返ってこないので注意が必要です。

(キー待ちでbtnwaitbexecを使う場合は、textbtnwaitと違って0で流れず止まります。
btnwaitはキー待ち命令上で、bexec"SKIP"を返して次行に進んだ上でskipoff状態に。
(これらでやる場合はskip時のみ事前判定してコードの経路を変えるなどしておきましょう。
(新ボタンのbexecの性能が圧倒的に良いので、個人的にはテキスト待ちでもbexecの方をおすすめです。

◎ isskipについて

nscr2.82nscr2.95nscr2.96
isskip命令は現在の状態がスキップ状態かどうかを変数に取得できる命令です。
スキップ中は1を返します。
*text_lb内では全スキップ中は1を返します。既読スキップ中も同様に1を返します。
既読スキップ実行中、未読行で止まった場合での*text_lb内ではisskipすると0が返ってきます。

◎ 既読未読の判定について

nscr2.82nscr2.95nscr2.96

既読か否かは各行頭で判定されているようです。例えば上記のテキストを表示させた場合。
行頭の(a)地点で未読か否かを判断し、未読でしたらその時点でスキップを止めているようです。
スキップ中ではなくなりますので、あああ(略)の表示は通常通りの文章速度になります。
(b)地点の¥まで来ないと、*text_lbへは飛ばないのですから、
とっくにスキップが止まっている状態の*text_lb内部でisskipを行っても0が返ってくるのです。
同様に、getskipoffをしていても、既に止まっている状態なのでtextbtnwaitは-60を返しません。

(※良い機会なので、カスタマイズを分かりやすく考えましょう。
( 「@」と「¥」は、「gosub *text_lb」の省略記号である。
( こう考えておけば色々な場面で挙動を理解し易いと思います。

◎ スキップ開始タイミングについて


スキップの動作実験¥
systemcall skip
isskip %0:itoa $0,%0
mesbox $0,"スキップ状態"
テキスト行1¥
isskip %0:itoa $0,%0
mesbox $0,"スキップ状態"
テキスト行2¥
テキスト行3¥

nscr2.82
最初のダイアログでは 0 、次は 1 が返ってきていますね。
このことから、systemcall skipではスキップ開始フラグをONにするだけであり、
「テキスト行」の頭にさしかかったところで初めてスキップが実行されることがわかります。
systemcall skip後にいくらコード行を挟んでも、テキストが来るまではスキップが実行されていません。

例えば、effectcutした状態でsystemcall skipしているはずなのに、スキップ後、
最初のエフェクトが何故かエフェクトカットされない――といった事が起きるのはこのためです。

nscr2.95nscr2.96
ver2.93以降からスキップの挙動が変わりました。
動作実験スクリプトを動かすとどちらのダイアログでも 1 が返ります。

現在では、effectcutした状態でsystemcall skipした場合に、
スキップ後直後のエフェクトでもちゃんとエフェクトカットが行われます。

△page top

スキップについて2 −既読スキップとif文−

nscr2.82nscr2.95nscr2.96
自作のスキップボタンを作っておき、既読行のところでスキップさせてみても、
1度目は動かずに、2度目に押して初めて既読スキップが動作するような事がよくあります。
その原因は、テキスト行だけでなく、コード行でも既読未読判定が行われているからです。

if文の行を通過していても、条件が成立していない場合はその行は未読扱いになっています。
そのために、1度目にボタンを押した時に初めてスキップを呼ぶ処理のコードを読みに行くことになり、
その時点では既読ではないのでスキップがコード行でストップしているということです。
この流れを分かっていれば対応させることは充分可能ですね。

△page top

gettextについて

nscr2.82nscr2.95nscr2.96
gettextで文章を取得すると、「改行」は取得されませんが、「ルビ部分」はそのまま取得されます。
文字列変数の中身に(/)などの記号が残ったままになります。
半角文字列が混入するのでその扱いには注意しましょう。

△page top

エフェクト用マスク

エフェクト番号18番用のマスク画像では特にデータ形式を気にする必要はありませんが、
エフェクト番号15番用のマスク画像にはbmpやpngを使うべきです。

jpgの圧縮率によっては大幅に劣化してしまうため15番のマスクに使うと粗が目立ってしまいます。
その点、粗のないbmpやpngは15番のエフェクトには最適だと言えます。
pngはその形式で作成した時点でサイズが圧縮されますので、個人的にはpngの利用をおすすめします。

△page top

SEデータのループ再生

nscr2.82nscr2.95nscr2.96
単純に dwaveloop 1,"se01.wav" とした場合、ループ毎にタイムラグが起きる事があります。
それを回避するには dwaveload 1,"se01.wav":dwaveplayloop 1 のように
先に読む命令を打ち込んでおきますと問題が発生しません。

△page top

defsubについて(1)配列では受けられない

nscr2.82nscr2.95nscr2.96
getparam にて値を受けるときに配列変数は使えません。
また、defsub命令同士の変数バッティングを防ぐため、02.汎用変数のススメで触れましたように、
個別で変数を確保させた方がよいと思われます。

△page top

半角文字について

nscr2.82nscr2.95nscr2.96
テキスト中に半角を使いたくとも、NScripterでは半角文字はサポート外です。
しかし、仕様外の方法ではありますが半角を使うことは可能です。

半角文字を偶数単位で使ってみると、2バイト文字列と認識してくれるのか表示することができます。
たとえば"AAAA""AAA "なら全角二文字分といった認識で扱われるようです。
これは英字だけでなく、半角数字や半角カナでも同じ動作になります。
しかし、偶数半角であっても"_A"" a"という場合が問題です。
偶数であっても先頭1バイト目が半角スペースや半角アンダーバーだとそれらが無視されてしまいます。
この動作を押さえた上で、色々と文字列を調整してみましょう。
(※ これは普段のテキスト表示のみならず、文字列スプライトに関しても同様です)

また、テキスト行の先頭で半角英字を書いた場合には命令文と勘違いされてエラーになってしまいます。
先頭に半角英字を使いたい場合は文字列として扱われるようにフォローした上で記述しましょう。

△page top

bg命令の不思議な挙動

nscr2.82nscr2.95nscr2.96
例えば800x600画面で100x100pixの画像をbg表示しますと、
何故か自動的にセンタリングされた状態で表示されます。
背景の裏は黒単色なので、黒地の画像を中央に表示するときには容量の節約が出来ます。
またセンタリング座標をわざわざ指定する手間も省け、ちょっとした演出に便利です。

しかし、この動作には問題があります。その状態でセーブしたデータをロードすると、
中央配置だったはずの背景が左上インデントされて表示されます。
しかも元の中央位置の領域が不安定になってしまいます。
とはいえ、わざわざ小さい背景を使ってゲームを進める機会はまずないでしょうから、
この例外処理はセーブする可能性のない連続的な演出などで利用するとよいかもしれません。

△page top

ズーム処理の座標について

画面サイズ800x600で(167,117)座標を中心に300%拡大したいときは下記の表記になります。


drawbg2 1099,849,300,300,0

中央からの移動距離を倍率に比例して計算するので一見わかりにくいですね。
そこで簡単に計算式を置いておきます。

まず、中心座標(x,y)、倍率(s)を先に決めておいてください。倍率は250%ならば250です。
drawbg2 a,b,s,s,0
だとして、

640x480サイズであれば、次のa,bを上に代入します。
a=320+(320-x)*(s/100)
b=240+(240-y)*(s/100)

800x600サイズであればこちら。
a=400+(400-x)*(s/100)
b=300+(300-y)*(s/100)

ちなみにこの命令、はみ出た部分は描画されず、前の画像が残ってしまいます。
その場合は事前にdrawclearで消しておきましょう。

△page top

背景回転で欠けがない背景サイズ

800x600サイズだと……1000x1000pixなら(400,300)を中心にして回転しても角が欠けません。
640x480サイズだと……800x800pixなら(320,240)を中心にして回転しても角が欠けません。

△page top

ボタン定義の特殊事例

nscr2.82nscr2.95nscr2.96
ボタン定義をした後に、その画像をmspamspによって移動させた場合、
画像は移動しても定義された範囲は移動しません。
かつて画像があった位置がボタンになったままです。
そのため、移動描画後に定義をやり直す必要が生じます。

このように何度も使われるボタン定義はサブルーチン化しておくと何かと便利です。

△page top

ボタン定義の特殊事例2

nscr2.82nscr2.95nscr2.96
大きいボタン範囲A(スプ番1)と小さいボタン範囲B(スプ番2)があるとして、
Aの範囲内にBのボタンがすっぽりと入っている状態です。どう書けばよいでしょう?


exbtn 1,1,"P11"
exbtn 2,2,"P12"

こう書けば、Bのボタンが機能します。B範囲からはみ出せばA範囲のボタンになります。


exbtn 2,2,"P12"
exbtn 1,1,"P11"

こう書いた場合はAの範囲だけ有効になり、Bのボタンは無視されます。

つまり、ボタン定義において後に書く方が優先されるということです。
優先順にスプライト番号やボタン番号は関係ありません。

△page top

スプライトアニメ

nscr2.82nscr2.95nscr2.96
アニメーション表示させているスプライトをmspamspによって移動させた場合でも、
アニメーションのセルは始点からリスタートになりません。そのまま連続してやってくれます。

△page top

デコード対策

大変遺憾ですが広まってるようですね。これはもう仕方がないかもしれません。
 1.コメントを全て削除する。
 2.空白行を削除して行間を詰める。(※skip命令使ってる人は要注意)
地味ですが、これだけでも相当読むのがウンザリするのでおすすめです。
いわゆる難読化というものです。コロンで繋いで一行を長くするなど色々とやり方があります。

これに加え、numaliasを使わないという手もあります。かわりに手元で変数番号を管理します。
しかし、自分がコードを読んでも読み辛いのでバグが出やすい諸刃の剣。覚悟の上でどうぞ(経験談)

○ NScripterコメント削除手順

免責事項:何らかの損害が生じたとしても、当方は一切の責任を負いません。
必ず先にバックアップを取ってから行ってください。
サクラエディタで開く→検索→置換→正規表現にチェックを入れて実行します。

1.行頭コメントの削除

	置換前:	^[ \t]*;.*\n
	置換後:	\n

2.末尾コメントの削除(※スプライトのタグ対策で"付コメントは除外

	置換前:	;[^"]*¥n
	置換後:	¥n

3.タブの削除

	置換前:	¥t
	置換後:

4.空白行の削除

	置換前:	^[ ¥t]*[¥r¥n]+
	置換後:

5.目視して手動削除→デバッグ

急いで書いたのでミスってたらご指摘をいただけますと幸いです。
パッチを当てる際に難読化後ソースだと泣けるので、バックアップは必ず別所に確保しましょう。

○ サクラエディタPPAマクロ

毎回置き換えするのがめんどいのでPPAマクロ作りました。
obfuscateNScr.zip (←右クリックして保存)
免責事項:何らかの損害が生じたとしても、当方は一切の責任を負いません。
NScripterコード(拡張子:txt,nsc)NSLuaコード(拡張子:lua)に対応しています。

2013,03,20追記 △page top

パッチを考えた上でのnsa化

nscr2.82
複数のnsaアーカイブ利用時に同名ファイルがあった場合、若い番号のアーカイブが優先されることを利用します。
例えばバージョン情報画像だけのarc.nsaファイルを作っておき、
普段のファイルを全部arc1.nsaに入れてある状態でリリースします。
パッチを当てないといけない事態になっても、arc.nsaだけの配布で済むので容量が少なくて済みます。

nscr2.95nscr2.96
複数のns2アーカイブ利用時に同名ファイルがあった場合は、後の番号のアーカイブが優先されます。
たとえば、まず、リリース版は00.ns2のみだとします。それに対してパッチの01.ns2を配布すれば、
00.ns2にあった問題ファイルを無視して新しいアーカイブの内容を参照してくれます。
パッチを出す度にカウントを増やしていくだけでCG関連のアップデートは済むように仕様が変わっています。
明らかに便利になりましたね。

nscr2.82nscr2.95nscr2.96
また、WDiffなどのバイナリ差分ツールを使ったパッチ配布も引き続きおすすめします。

△page top

座標間の距離を求めたい

nscr2.82
つまり直角三角形の斜辺の長さ。
二乗の和のルートですが、Nスクで√計算はできません。
というわけで、Moler-Morrisonでググってみましょう。

浮動小数点が使えないので適当に1000倍精度くらいでやるとよいかもです。
小数点以下が切り捨てられる分、どうしても正確には出来ませんが、
ある程度は参考になる数値が出せると思います。

(関連)絶対値の出し方 → if %0 < 0 mov %0,-%0

nscr2.95nscr2.96
luaの数学関数にmath.sqrtがあるので、現在はそちらで普通に「二乗の和のルート」するだけです。

△page top

(リクエスト)選択肢カスタマイズの注意点

nscr2.82nscr2.95nscr2.96
Q:cselbtnを使った瞬間落ちたけど?
A:setwindow範囲外に表示させようとすると落ちます。仕様です。

例)
たとえば、こういった設定の状況で……
setwindow 32,382,3,15,25,25,0,4,0,1,1,#AAAAAA,0,380,639,479
下記のボタンを定義しようとすると、ハイ落ちます。
cselbtn 0,1,100,100
cselbtn 1,2,100,120
つまり(100,100)と(100,120)は、(0,380)から(639,479)までの範囲内ではないのが原因です。

ではどうすればよいのでしょうか? いくつか打開策を挙げてみます。

打開策1:座標を変えてsetwindow範囲内に選択肢を表示させる。
打開策2:いっそsetwindowの範囲を全画面にする。(非推奨)
打開策3:getcselstrなどの専用命令を使った正攻法。
打開策4:むしろ専用命令のcsel系は使わずに全て自作。(推奨)

大体こんな感じですね。以下、かいつまんで簡単に説明してみます。

――打開策1 (説明不要だと思いますのでスルー)

――打開策2

 推奨しない理由は、ウィンドウ範囲が広がれば広がるほど動作が重くなるからです。
 極力、使用する範囲ギリギリに設定しておくのがセオリー。

――打開策3 (手順の一例)

 1.getcselstrで文字列を文字変数に取得。
 2.文字変数を使ってボタン用の文字列スプライトを作り、自由な位置に表示。
 3.spbtnexbtnでボタン定義。
 4.後はいつも通り。(selectbtnwaitで待ち、選択肢の番号返ってきてたらcselgotoで飛ぶ)

――打開策4 (手順の一例)

 1.cselを代替する命令はdefsubなりで使いやすいように適当に自作。
 2.普通にgetparamで受けた文字変数で文字スプ作って自由な位置に表示。
 3.普通にspbtnexbtnで定義して、普通にbtnwaitで待つ。
 4.返り値が選択肢の番号だったら、該当するラベルが入った文字変数でgotoして終了。

 推奨する理由としましては、
 今までの命令で充分に代用できるために、csel系の専用命令をわざわざ覚える必要がない事。
 ウィンドウ範囲内限定といった制限が発生しない事。
 自作した方が好きなように機能拡張する事ができる。……などなどが挙げられます。

 ※ 4の場合、自動saveoffの範囲外なので、誤ってセーブデータ準備をさせないように。

△page top

splitの動作メモ

nscr2.82nscr2.95nscr2.96
splitとは指定文字で切り分けて変数に受ける命令です。

受ける変数が足りない場合はそれらは無視してくれます。
受けるために切り分けた以上の変数を用意してあった場合には、それらを""または0で上書きします。
 (※ 変数に先に何か入っていても""か0で上書き)
切り出し用の文字列に全角は指定出来ません。


mov $100,"あ/い/う/え/おおおおおおお"
split $100,"/",$101,$102

文字列変数が3つ足りないが問題ない。
$101の内容は"あ"
$102の内容は"い"


mov $100,"あいう/えおおおおおおおおおお"
mov $105,"ん"
split $100,"/",$101,$102,$103,$104,$105

用意していたのに使われなかった変数は""で上書きされる。
$101の内容は"あいう"
$102の内容は"えおおおおおおおおおお"
$103の内容は""
$104の内容は""
$105の内容は""


mov $100,"あいうえお"
split $100,"/",$101,$102

文字列内に切り出し文字が無くても問題ない。
$101の内容は"あいうえお"
$102の内容は""

△page top

getspsizeの動作メモ

nscr2.82nscr2.95nscr2.96
getspsizeはスプライトのサイズを取得する命令文です。未使用スプライトでは幅,高さに0を返します。
それを利用してスプライトの利用状況リストを作れるのではないかと思いましたが、
一度利用後にcspしたスプライトでも、定義当時の幅,高さを取得出来てしまうので駄目でした。
デバッグ時に有効利用できるかと考えていたので少々残念です。

(080229追記)幻惑郷さんで同じ話題を扱っていました。
なるほど。cspの時に特定サイズのスプライトに置き換えておけば判別出来ますね。

△page top

テキスト表示の動作メモ …… 表示階層について

nscr2.82nscr2.95nscr2.96
humanz 数値)及び(windowback)でテキスト表示階層を変更していても、
普段のテキストの表示階層は下記の通りの動作になります。

(a)からテキストの表示がはじまりますが、(b)地点に到達するまでは、
テキストは無条件で「スプライト類の上部」に表示されます。
(b)地点に着いた瞬間、設定階層が有効になります。
ここでテキストより上部レイヤに設定されたスプライトがありますと、
テキストはそれらの影に隠れる事になります。

△page top

自動描画範囲について

nscr2.82nscr2.95nscr2.96
文字色指定の #FFFFFF などの色コード指定。
また、テキスト埋め込み用の省略記号である !s !sd !w !d 及び、 { } などでは、
自動でsetwindow範囲内のみの再描画がかかります。
texton命令及び、クリック待ちに¥@を使った場合なども同様です。

全画面ノベルを作っている場合にはさほど気にならない動作だと思いますが、
下4行表示などのADVゲームを作る場合には、少々気を使う必要があります。

さて、何故再描画されることが問題なのでしょうか?
lsp ?/vsp ?,1 などでメモリ上描画してる状態のスプライトがあるとした場合、
上に列記した命令が呼ばれた際にsetwindow範囲内のそれらを自動で再描画します。
しかし、範囲外は未だメモリ上にしか描かれていない「不定領域」になっています。
これら残りの範囲は、改めて描画命令が呼ばれるまで反映されません。
このため、本来描画させる予定外のタイミングで画面上に表示されてしまったり、
setwindow範囲の描画後にprint表示させるとチラつきで見栄えが悪くなったります。

以下、わかりやすいように画像で説明します。

1.まず状況を設定します。
(背景:黒と水色の雲模様/白枠:setwindow範囲/赤い長方形:メモリ上描画済スプライト)
図1

2.その状態で#FF0000と文字色を指定してみる。すると自動で再描画がかかります。
(黒い長方形:実際見えているスプライト)
図2

3.その際不定領域はこうなっています。
(半透明の黄色い範囲:不定領域)
図3

4.その状態で新たなスプライトをlspしてみます。分かりやすいように透過50%にしておきます。
図4

5.図4のスプライトをprint 1で描画すると左図5−1。
  (5−1では不定領域が無くなり、メモリ描画したスプライトが全て目に見える形に描画される)
  描画処理をせず#FFFFFFを記述した場合が右図5−2。
  (5−2ではsetwindow範囲内のみが再描画される)
図5-15−1 図5-25−2

6.図5−2において、残っている不定領域はこうなっています。
図6

◎ まとめ

テキスト行埋め込み用の命令はウィンドウ範囲の再描画を伴います。
下記のようにテキスト行中に埋め込むのが本来の用途です。


あああ#FF0000ああああ#FFFFFFあああああ¥

これらをコード行に記述しても動作しますが、
ここで長々と説明したような再描画を伴うため、使用を控えるべきです。
コード行では、同機能の別命令がありますのでそちら↓を利用しましょう。

#?????? → textcolor #??????
!s??    → textspeed ??
!sd     → textspeeddefault
!w??    → wait ??
!d??    → delay ??
{?,?}   → mov ?,?

ちなみに、english命令時にはテキスト埋め込み記号が使えませんので↓のような記述になります。


あああ/
textcolor #FF0000
ああああ/
textcolor #FFFFFF
あああああ¥

△page top

btnwaitについての動作メモ (自動_print 1)

nscr2.82nscr2.95nscr2.96
btnwaitで待つ瞬間、強制的に_print 1が呼ばれているようです。
反映前のスプライト類が強制的に描画されてしまうので注意が必要です。

デバッグ用に、コードの合間にクリック待ちを挟みたい場合は、
描画のかからないclickや、mesbox "",""あたりを使うべきでしょう。
※ mesbox命令で無限ループを作ると、Nスクを落とせなくなり、再起動するしかなくなるので注意

ちなみにtextoff命令でも同様に_print 1が呼ばれるようです。

△page top

pretextgosubについて

nscr2.82nscr2.95nscr2.96
pretextgosubで指定したラベルはテキスト行の行頭で読まれるようになります。
大変便利な命令なので動作を覚えておきましょう。タグを利用しない場合でも十分に使える命令です。
分かりやすいように、割り込みタイミングを図示しておきます。

nekodaisuki

緑色の★印がpretextgosubで割り込まれる箇所です。
※1や※2のように、ひとつの行の中に@でクリック待ちを置いた場合、
@が終わるたびにpretext用ラベルに飛ぶかというと、飛ばないのは周知の通り。
ここで注意したいのは、※3の矢印で示された箇所です。
1ページ内に演出を挟む為に半角スラッシュ(改行無視記号)を記述して、
演出挿入後に再びテキストを書くような場合の012行の頭でもpretextの割り込みが入ります。
また、005-006行のように、同じページ内でも改行があった場合には割り込みが入ります。
つまり、ひとつのページ内で一度しか実行させたくないような処理は、
pretext用ラベル内で気を使った記述をしなくてはいけません。

ちなみに、pretext用ラベル内にてテキスト表示させると必ず落ちます。

<おまけ解説> 既に上の方のTipで説明してある通り、
自動でsaveoffされる範囲は「テキスト行の行頭から、その次の¥まで」(※)である。
範囲の切れ目ごとにセーブの準備がされてる模様。
今回の例で言うと010-012行で範囲が切れないことも覚えておくと便利(?)。
textgosub用ラベルに飛ぶタイミングも前述の通り、記号が読まれたタイミングである。
(※ もっと正確に言うと、¥ではなく、¥で飛んだ先のtexecで呼ばれるtextclearまで)

△page top

セーブデータについて

nscr2.82nscr2.95nscr2.96

◎ 書き込みのタイミング

envdata gloval.sav kidoku.dat NScrllog.dat といった
セーブ関係ファイルが初めて作られるタイミングは、一番初めのボタン待ち命令に来てからです。
(ちなみに実行窓が表示されるのは*define節のgameが読まれて*startラベルを読む間)
このことから、グローバル変数やファイルログなどの情報に変更があったとしても、
次のボタン待ち命令に辿り着くまではファイルに書き込まれないことがわかります。

◎ envdataについて

初級者向けに書くべき内容のような気がしますがついでにここに。
起動すると自動で作られる「envdata」には、*define節の設定類(例えばsavedirなどの設定)、
現在使用しているフォント、現在のウィンドウ状態あたりの環境設定データが記述されています。
そのため、*define節のスクリプト内容を書き換えた場合は、一度envdataを削除しないと認識してくれません。
例えば、autoの時間を変えたのに反映されないぞという時にはenvdataを消してみましょう。

さらに、作品頒布後にパッチを当ててもらう必要がある場合、*define節を変更していた場合には、
ユーザーさん側でenvdataを一度削除してもらう手間が発生する事にも注意が必要です。

envdataを削除しますと、次の実行時にNScripterは再び*define節を読み直してenvdataを作ります。
削除前までenvdataにありました*define節の各種設定情報を改めて作り直しているようです。
そこでは勿論、「kidokuskipglobalonが書かれていた」という情報が無くなっていますので、
*define節でkidokuskipやglobalonが読まれた瞬間に、
改めて内部でkidoku.datやgloval.savの情報をゼロから新規作成してしまいます。
(実際にファイルを上書きするのは前述のようにボタン待ちの時ですね)
envdataを削除すると、既読スキップが出来なくなったり、グローバル変数が消えるのはこのためです。
セーブデータは無事なのでロード出来ますが、
フラグ類をグローバル変数に入れておいた場合は致命的バグの温床に……。
ちなみに何故かNScrllog.datは無事です(笑)

◎ グローバル変数について

saveoff状態でも上記に書いたキー待ちのタイミングでgloval.savは更新されます。
saveoffはあくまでセーブデータ準備を止めるだけなので注意。
ラベルや既読やファイルログも同様にsaveoffの影響を受けません。

△page top

レイヤ順を考える

最初の設計を失敗すると、一番地獄を見るのがこれでしょう。
ゲームにどんな機能が必要かよく考えて、それからはじめて制作に入るべきです。
そうしておかないと、仕様変更時に全てのスプライト番号をズラさなければならない重労働が発生します。
必ず、各システム画面で必要なスプライト数を事前に洗い出しておきましょう。
人それぞれやり方が違いますから一概には言えませんが、参考までに個人的な構成を晒しておきます。

<上>
………(ムービー)……………
………(数値ラベル)…………
………(バー)…………………
汎用キープ
インフォメ類
汎用キープ
各種システム系
右クリックメニュー
テキストウィンドウの機能ボタン
¥@カーソル画像
………(テキスト・立ち絵)………
発言者名表示
発言者顔グラ表示
テキストウィンドウ枠画像
演出総合(カットイン等)
エモーショナル演出用
目パチ演出用
立ち絵用
背景演出用
………(背景)…………………
<下>

ある程度演出拘ってる人は、msp出来るように大概立ち絵をスプライト化してると思います。
テキストウィンドウもスプライト化しておいた方が便利です(setwinは#FFFFFFでやる)
カーソルはスプライトで用意しといた方がα付き画像が使えて綺麗です。
最上層は汎用に数枚確保しておいた方が無難でしょう。
更に各機能の間に数枚確保しておくと、仕様追加に対応しやすいですね。
monocro命令の見栄えによってはhumanz位置をテキスト窓ボタンの直上に変えます。

ここまで書いておいて何ですが、
仕様変更機会が多い場合には、あらかじめスプライト番号を全てエイリアスにしておきますと、
*defineを弄るだけで好きに上下位置を変更できて便利です。

△page top

Tabキーは極力使わない

nscr2.82nscr2.95nscr2.96
旧ボタン命令でgettabをしておくと、btnwait時にTabキー入力の判定が出来ますが、極力避けましょう。
その理由は、ゲーム窓がアクティブかつbtnwaitで入力を待っている場合に、
ウィンドウズの基本ショートカットである Alt+Tab(窓切替)が効かなくなってしまう為です。
マウスを使わない場合に Alt+Tab が利用出来ないのは大変不便なものです。
例えば通勤中にノートPCでプレーする剛の者に嫌がられるかもしれません。
必要に迫られない限りは、出来るだけTabキー(gettab)の利用を避けましょう。

nscr2.95nscr2.96
そのためなのか、新ボタン命令ではtabキー取得は削られていますね。

△page top

システムカスタマイズ時の「ページ毎表示」について(リクエスト)

nscr2.82nscr2.95nscr2.96
システムカスタマイズ時にはご質問の通り「menu_click_page」が何故かおかしくなります。
そのためinsertmenu命令の「CLICKPAGE」も使うべきではありません。
メニューにある場合は削りましょう。

カスタマイズしている以上、自分でこの機能を作成することができます。
内容は非常に簡単です。まず、適当に変数を2つ用意します。
ここでは %clkPage という変数でページ毎表示か否かの管理をしてみます。
コンフィグメニューを作ることを考えてもグローバル変数で用意するとよいでしょう。
%0は一時取得用なので適当な汎用変数でどうぞ


*text_lb
ispage %0
if %0 == 0 && %clkPage == 1 texec:return

単純に、@で入ってきていてページ毎表示がONの場合には、何も行わずに戻すだけです。
ページ毎表示のON/OFF操作は適当に自作のコンフィグメニューに用意しましょう。

追記 2012/12/10 ご指摘をいただきましたので記述を修正しました。ありがとうございます)

△page top

defsubについて(2)必ず消化する

nscr2.82nscr2.95nscr2.96
まずは、下記のスクリプトを実行してみてください。


*define
	defsub neko
game
*start
	mov %0,1
	neko "neko"
	click
	mov %0,0
	neko "neko"
	click
end
*neko
	if %0 == 1 return
	getparam $1
	lsp 50,":s/20,20,0;#FFFFFF"+$1,200,300
	print 1
return

つまり、defsubで引数を渡した場合は必ず飛び先で使う(getparamする)ようにしなければいけません。
エフェクト類をdefsub化しておいた場合に、isskipが1の時はすぐ帰る――などすると、
エラーの原因になりますので、ちゃんと関数内で消化だけはしておきましょう。
ちなみに文字列でも数値でも同様の動作です。

△page top

日本語ファイル名でスクリプトを管理

スクリプトを日本語ファイル名で保存してあるとして、
単にnscr.exeを実行する前に、バッチファイルなどで変換させるだけです。


copy "*.txt" "00.txt"

これだけで出来ます。
同じディレクトリにあるtxtファイルを問答無用で結合して00.txtを作るだけです。(あれば強制上書)
お陰で日本語が使えますし、100ファイルまでという制限もなくなります。
可視性が大幅向上して、作業効率が上がるのでお試しあれ。

私はそれに加えて
現在日時名のフォルダを作らせてスクリプトファイルをバックアップさせてます。
更に、連番リネームさせたtxtファイルも一緒に作ってバックアップしておけば便利ですね。
エディタ設定のtxtとのバッティングも気になったので適当な拡張子をNスク用に割り当ててます。
そうしておけばnscr.exe実行前にバッチ実行して00.txt作成する必要がありますので、
必然的にバックアップの習慣が生まれて安心です。
(そもそもの動機が“バックアップ習慣→バッチが楽→なら日本語化も別拡張子もいける”の流れ)
簡単なバッチファイルを書くだけの手間で、かなり便利な環境を作れたりします。

で、ここまで書いて思いだしたのが、
NScripter Scripting Factoryさんで公開されているNScripter向けファイル名変換ツールです。
色々なオプションが付けられますので機能的です。06年には既に公開されてたワケですね……
日本語ファイル名でスクリプトを管理できると本当に便利なので、
自分でバッチファイル書くのがメンドイ方は是非そちらの導入をお勧めいたします。

(追記 H22/06/24)

要望があったのでバッチファイル置いておきます。
nscr_tool.zip ←右クリックして保存を選んでください

免責事項:何らかの損害が生じたとしても、当方は一切の責任を負いません。

△page top

autosaveoffについて

nscr2.95nscr2.96
ver2.93で追加されたautosaveoffは、表示文頭以外の自動のセーブポイント更新を停止します。
高速化の為に一々saveoff/onを書かなくても済むようになる非常に便利な命令ですが、
必須作業と言える注意点がありますのでここに記述しておきます。

◎ STEP 1


br
ああああああ@
いいいいいい\

問題1:
autosaveoffを利用すると、上記のようにページの冒頭がbrの場合は
「表示文頭」扱いにならないため、そのページでセーブできなくなります。

解決1:
defsubbr命令を上書きして、その中にsavepoint命令を入れておきましょう。

◎ STEP 2


ああああああ@
br
いいいいいい\

問題2:
br命令にsavepointを加えると、上記のようなスクリプトで新しく問題が発生するようになります。
冒頭ではなくページの途中でbrが存在すると、そこでもsavepointが呼ばれてしまいますので、
ページの冒頭ではなくページ中でのセーブデータが作成されてしまうのです。
そのデータをロードすると、3行目の「いいいいいい」からゲームが始まってしまいます。

解決2:
まず、textgosubの飛び先ラベルにて、ispageを実行させて変数に値を取得しておきましょう。
次に、先ほど制作したbr命令に手を加えます。
ispageで得た値によって¥の状態で入ってきたのか否かを判断出来ますので、
変数の値が1の場合(¥の場合)のみ、savepoint命令が実行されるようにしておきましょう。

◎ STEP 3


ああああああ
br
いいいいいい\

問題3:
同様に、上記例のように@を使わないままbrが書かれてしまうケースへの対処も必要になりますね。

解決3:
pretextgosubの飛び先ラベルにて、
先ほどispageで使った同じ変数の値を1以外の数値に変化させておきましょう。
そうすれば2行目にあるbrで冒頭と判断されてsavepoint命令が実行されてしまうことはなくなります。
これでbr対策は完了です。

◎ 必要に応じて、更にひと仕上げ

文章にすると長いですが、実際打つスクリプトは短いのでご心配なく。
以上のbr対策の必須作業」さえ終わらせておけば、
後はごくごく普通にいつも通りのNScripterを利用していけます。

ここまでご自身で書けるようでしたら、locate命令にもsavepointを噛ませたり、
連続した場合でのbrは、savepointを1度目だけにするなど、
簡単に対処スクリプトを書いていくことが出来るはずです。
(私の場合はこの二つは使わないので書きませんが、必要に応じて対処スクリプトを書きましょう)

デモなどでtextclear命令を利用する場合にも手を入れておく必要がありますね。
先ほどispageで使った同じ変数の値を1にしておきましょう。
¥の状態でtexecするのと同様の動作にしておくというわけです。

※ そもそもautosaveoff命令って何?

autosaveoffは基本的に「楽をするため」の命令になります。
シナリオの特定範囲から特定範囲まではセーブデータを作らせたくない――といった特殊な場合には、
テキスト行頭にて自動的にsavepointが呼ばれてしまうautosaveoffを使ってはいけません。
素のNScripterのまま、saveoffsaveonで丁寧に範囲指定してください。

どういった「楽」が出来るかといいますと、特に演出箇所での恩恵が挙げられます。
動作の高速化のために、毎回saveoffsaveonで挟む作業に辟易している方にお薦めです。
演出に拘っている方は労力が減ってバグ確率も減るため、是非autosaveoffを利用しましょう。

(特定範囲でセーブさせたくないゲームの代表例はシミュレーションやコマンド型アドベンチャーでしょう。
 シナリオを読み進める一般的なノベルゲームであればautosaveoffを利用した方がずっと楽になります)

△page top

nsaとns2とoggプラグイン

本サイトを読まれている方の使用エンジンは、新ボタン以前の安定版「ver2.82」(の第四弾)派と
Lua以降安定版の「ver2.95」以降派に分かれているのではないかと思われます。
v2.82派には必須といえるプラグインがnscrplgさんのNScripterDS.dllnscrpng.spiです。
こちら現行のns2アーカイブに対応していないため、最新エンジンへの移行に抵抗がある方もいそうですね。
また、エンジン自体はv2.95以降を利用しながら、アーカイブ化は旧ツールで行ってnsaを作成し、
NScripterDS.dllとnscrpng.spiを使い続けている方も予想されます。

で、それが何か? 問題あるの?

特にこれといった問題はありません。

状況整理 (※ 私はv2.45からのユーザーにつき、それ以前については知りません)

まずoggに関しては以下のような歴史があります。
v2.45時点:oggdec.dllが公式配布されていた。ストリーミング不可のためアーカイブ内不可。
v2.60当時:NScripterDS.dllが公開される。非同期。ストリーミング。パン。フェード。ループなど多機能。
v2.70以降:nsogg.dllが公式配布スタート。ストリーミング再生が可能に。
v2.91以降:nsogg2.dllが公式配布スタート。非同期動作。ループポイント設定が可能に。
v2.93以降:Luaを利用することで細かいフェード操作等が可能に。

次にpngに関しては以下のような歴史があります。
v2.60当時:nscrpng.spi公開される。遂にnscrでpng利用が可能になる。
v2.93以降:nspng.dllが公式配布スタート。(ここで初めて公式でpng対応開始)

見ていただいて分かるとおり、nscrplgさんによるプラグインの存在感は凄まじいものがありますね。
(ちなみに、nscrはv2.93を大きく境にしてセーブやボタンやLua関係など多数の変化があります)

基本的にはエンジンのバージョンに合わせて次のプラグインを利用するのが一般的な構成でしょう。
ver2.93以前を利用する場合:NScripterDS.dllとnscrpng.spi(対応アーカイブ:nsa)
ver2.93以降を利用する場合:nsogg2.dllとnspng.dll(対応アーカイブ:ns2)

ここから本題

nscr2.95nscr2.96
Luaを使いたい→つまりns2アーカイブを使いたい→でもNScripterDS.dllを使いたい
そういった場合にかなり困ると思いますが、解決方法は簡単です。
00.ns2(CGとLuaコード)とarc.nsa(oggファイルのみ)を同時に使ってしまえばいいだけです。

ちなみに、左右PanやLength以外の大抵の機能はもう公式dll側でも再現可能ですから、
Luaを使えるような方ならサクッと公式dllに変えてしまった方が楽ではないかと思います。

(追記)※ 混ぜるのはやめた方が良いみたいです(senzogawaさんTwitterより)

nscrpng.spiですが、複数セルを持ったCGを作る場合は旧来通り横にマスクを並べる作り方になります。
nspng.dllのように透過pngのまま並べる方が作業効率が上がると思いますので移行を推奨いたします。
素材を作り直さなければならない分量によって判断するのがよいのではないかと思います。

将来的にnsaを作るための「旧ツール」類が公式で公開されなくなることも考えられますし、
今のうちに移行の準備されることをオススメします。

△page top

btimeについて

nscr2.95nscr2.96
新ボタンのbtime命令で待ち時間設定を行うと、bexec"LCLICK"などを通過しても
bclearが無い限り延々と設定が有効ですから注意しましょう。(ここまでは旧btnwait同様)

まず、一度消化するまで("TIMEOUT"を判定するまで)は常にbtimeの設定値で待ち、
更に、一度消化後には「btime 0 状態で継続する」という仕様を押さえておく必要があります。
特に後者の仕様に戸惑うことがあると思いますので、充分に注意が必要です。
ループを作る際にbexec直後にbclearを記述する癖をつけておけば大抵のケースで問題ないでしょう。


;検証スクリプト
btime 1000
bexec $btn
caption "1"
bexec $btn
caption "2"

バグっぽいので一応公式に報告しておきましたが、bclear入れておけば現状でも対処可能です。

△page top

lchkについて

nscr2.82nscr2.95nscr2.96
仕様チェック。マニュアルにある通り、元々文字列に入れたラベルを扱える。


*define
labellog
game
*start
mov $0,"*sta"
if lchk $0+"rt" mesbox "ok",$0+"rt"
end

↑このようにif文中で演算も可能なため、ラベル名をフレキシブルに扱うことができる。


mov $label,"*test"
gosub $label+"_01";(*test_01ラベルへgosub)

関連して、↑こういう事も可能です。

nscr2.96 2011,11,17 △page top

新ボタン(bexec)とスペースキー

nscr2.95nscr2.96
新ボタン命令が出た頃のメモが発掘されたので掲示。bexecの返値文字列の話。
bcursor命令を使っていない場合、エンターキーもスペースキーも"LCLICK"扱いになる。

bcursorを使わずに(カーソルはボタン間移動のまま)、エンター・スペースに機能を割当てたい場合は、
checkkeyでは普通に"RETURN""SPACE"で扱ってくれるので、
bexecの後に一度checkkeyを噛ませて判定し、bexec受取文字列内容を変更させるとよい。

関連)
同じく、bexecでは拾えないっぽい"N"キーや"D"キーもcheckkeyでやろう。(※訂正。拾えました)
NキーはNScripterのデフォ機能としてスキップ割当があるので、利用する場合はskipoffを加えておこう。
bexecでは"ENTER"ではなく"RETURN"で返ってくることを忘れやすいので注意。

nscr2.96 2011,11,17 △page top

ver296の外字について

nscr2.96
NS栗さんのプラグイン(NSFont.dll)利用で外字が利用できる。
ver2.95まではアーカイブ化しても参照出来たが、ver2.96では参照できなくなったので注意したい。
(※アーカイブ化前の生データでは取得出来ています)

ver2.95まで:00.ns2からBMPデータ取得可能
ver2.96現行:00.ns2からBMPデータ取得不可(NScripterが落ちます)
対策:PNG化すれば読めます。アーカイブ外に生ファイルでBMPを置いても読めます。前者をお薦めします。

nscr2.96 2011,11,19 △page top

modとif……式と命令の優先順位(リクエスト)

nscr2.82nscr2.95nscr2.96
基本的なmod命令の利用方は下記2通りです。


;命令文としてのmod
mov %0,101
mod %0,2
%0\

;式としてのmod
mov %0,101 mod 2
%0\

両者が特に競合することが無いように思われますが、実はif命令でのバッティングがおきます。


mov %1,101
if %0 == 0 mod %1,2
%0\
%1\

本来なら%0が0ならば%1を2で割った余りを%1に返すという動作です。
しかし、上記コードの実行結果は
,2
(クリック待ち)
101(クリック待ち)
となります。
これは、明確に条件式を区切らないNScripterの仕様によって発生しています。
(Cのifのように括弧でくくったり、Luaのようにthenを書くなどしておらず、半角スペのみのため)


if %0 == 0 →ならば→ mod %1,2
if %0 == 0 mod %1 →ならば→ ,2

前者のつもりで書いたつもりが、後者として取られたということですね。
これは式の方が優先順位が高いためです。
ちなみに、命令文扱いではない英数字はテキストとして扱われますので、
まずは「,2」がテキスト表示。文末改行して、さらに%0値がテキスト表示されています。

○ これを回避するには?

単純に、間にひとつ何か命令を入れればこういうことはおきません。(例. wait 1:)
しかし無駄な動きをさせるのはものすごく微妙ですね。というかやめましょう。
そこで、命令文を1行で連記する際に記述するコロンを利用します。
コロンを利用することで一行で複数の命令を書くことができます。
for %0=1 to 100:csp %0:next
例えば上記のような動作などでよく使われていることと思います。
if命令の直後↓のような位置にコロンを挟みます。


mov %1,101
if %0 == 0:mod %1,2
%0\
%1\

半角スペースの代わりにコロンを置くことで問題なく実行されます。
ちなみに他の数値演算命令 add sub mul div などは式で使われませんので問題はありません。
(そちらを式で利用したい場合には + - * / を利用してください)
if命令との組み合わせて気を遣わなくてはいけないのはmodのみと押さえておきましょう。

nscr2.96 2011,12,17 △page top

fileexistはタグなしで

nscr2.82nscr2.95nscr2.96
画像タグ(:c;など)がついたままだと返り値は0(存在しない)になる。


;※imageフォルダ内にsample.pngが存在するとする
fileexist %0,":a;image¥sample.png"
itoa $0,%0:mesbox $0,"返り値"
fileexist %0,"image¥sample.png"
itoa $0,%0:mesbox $0,"返り値"
;前者は0、後者は1に

これを覚えておけばlspなどを上書きして有無チェックを噛ませる場合に戸惑いません。
lenmidで文字列操作し、タグを取り除いたものでチェックすれば普通にいけます。

nscr2.96 2012,12,10 △page top

filelogはタグなしで

nscr2.82nscr2.95nscr2.96
直前のTIP48に関連してfilelogについても調べてみました。


*define
filelog
game
*start
lsp 0,":a;image/sample.png",0,0:print 1
click
if fchk ":a;image¥sample.png" mesbox "利用済み",":a;"
if fchk ":c;image¥sample.png" mesbox "利用済み",":c;"
if fchk "image¥sample.png" mesbox "利用済み","タグなし"
end
;反応するのは「タグなし」のみ

どんな画像タグで表示経験があっても統一して扱ってくれます。:a;や:c;で別扱いにならない。
フォルダの区切り文字は/スラッシュでも¥円マークでも構わない。

判定用に使う文字列には画像タグ(:c;など)がついたままではいけないということが分かります。
lspなどを上書きしたときにgetparamで拾える画像のファイルパス文字列を
そのまま判定には使えないということですね。一度文字列を操作してタグを削ると大丈夫です。

nscr2.96 2012,12,10 △page top

defsubについて(3)オーバーロード

nscr2.82nscr2.95nscr2.96
4年前に話題になっていたものを今頃お蔵出し。
ver282/295/296でnscript.dat化後も動作確認しましたが、隠れ仕様につき保証外動作です。


*define
defsub test
game
*start
test 52 3 400 5 666
おわり\
end
*test
getparam %0
itoa $0,%0:mesbox $0,"first"
getparam %1
itoa $0,%1:mesbox $0,"second"
getparam %2
itoa $0,%2:mesbox $0,"third"
getparam %3
itoa $0,%3:mesbox $0,"fourth"
getparam %4
itoa $0,%4:mesbox $0,"fifth"
return

これは下記2サイトさん(主に幻惑郷さん)の情報からの関連ハックですね。
数値と文字列を交互にする必要はなく、区切りも半角スペースでOKという実例です。
ちょっとだけ言語ハック - senzogawaのNな日々
オーバーロード可能? - 幻惑郷

これで何が期待出来るかというと可変引数です。
getparamでは必ず渡された引数の数だけ受け取るための変数を用意しなければいけませんが、
上記のテクニックで先に受ける数を指定すれば、それに合わせたgetparamが可能になりますね。
例) test 3 "壱","弐","参" : test 2 "壱","弐" ;(※同じtest関数を利用)

NSLuaを利用できれば、while NSCheckComma() doみたいな書き方でいいので指定などいらず、
いくらでも可変引数の命令を作成できますが、Luaなし縛りで命令を作成する場合
こういったテクニックは有効になる場合があるかもしれません。

問題は互換エンジンでは恐らく利用できないと予想されることです。(※未確認)
ONSなどのコンバーターでマルチプラットフォームを目指す場合は利用しないようにしてください。

nscr2.96 2012,12,10 △page top

midの勘違い

しばらくNSLuaばかりやってたせいでstring.subと混ざって大混乱したので自分用メモ。


mov $data,"test.png"
len %length,$data
mid $0,$data,0,%length-4
;
mov $data,":a;test.png"
len %length,$data
mid $0,$data,3,%length-7

拡張子カットの例。タグがあるときは3,x-4でなく3,x-7でないといけないのは、
midの最後の引数は「取得する文字数」、string.subの最後の引数は「終端位置」で別物だから。
教訓:うろ覚えのまま混乱していないで、マニュアルを確認しよう

nscr2.96 2012,12,10 △page top

zenkakkoについて

nscr2.95nscr2.96
(win7/64bitにて動作確認)以下の検証結果から、現在はzenkakko命令の利用を推奨しません。

ver2.82
利用可 ○ …… そのまま普段通りに利用できます。

ver2.93〜ver2.95 で autosaveoff を 使っていない 場合
利用可 ○ …… そのまま普段通りに利用できます。

ver2.93〜ver2.95 で autosaveoff を 使っている 場合
不可 × …… 起動中のセーブ&ロード動作が通るので一見動くように見えますが、利用できません。
    一度NScripterを終了して【】タグ部でのデータをロードした瞬間に下記のようなエラーで落ちます。

---------------------------
構文エラー
---------------------------
不正な命令"y"です。

00.txt line:55

|*start
|あいうえお\
>【
---------------------------
OK   
---------------------------

ver2.96
不可 × …… 文頭にある 【 に辿りついた瞬間に強制終了します。

(※ ver2.93以降であればNSLuaで自作することが可能です。参考:迷走か進化か - 永字八法 )

nscr2.96 2012,12,18 △page top

自動でバージョンをチェック

NScripterのバージョンではなく、制作したゲームのバージョンについての話です。
起動時にゲームの最新バージョンがあることをお知らせしてくれるソフトを見かけることがあります。
NScripterでもプラグインを利用することで最新版のお知らせが可能になります。
Despair & Hope プログラム支部さんで公開されているHybridScripter.dllを利用します。
実際にサンプルを作ってみました↓のでご覧下さい。

versioncheck.zip (←右クリックして保存) (矩形スプライト利用のためver2.93以降対応)

チェックのしくみはとても簡単です。サーバにアップしたversion.txtにアクセスさせて、
version.txtに書かれた文字列とゲーム側の現在バージョン文字列とを比較します。
それが違った場合にpatch.htmlをブラウザで開いて、パッチをDLしてくれるように誘導します。
同梱の[つかいかた.txt]に利用法を記しておきましたので、ご自由にご利用くださいませ。
大体見れば分かると思うのでコードの改変もお好きにどうぞ。

免責事項:何らかの損害が生じたとしても、当方は一切の責任を負いません。

nscr2.96 2013,02,10 △page top