DNMLタグ解説


 DNML付属のリファレンスに書かれていることは、基本的には書いていない。
 基礎は理解しているものとして解説する。


ENTER / EXIT
ACT
P / BR
W
BACKGROUND
BGM
SOUND
A HREF
A NAME
QUESTION
MEMO
EVENT
FONT
NEWLINE(NL) / NEWPAGE(NP)
INDENT
POSITION
CLIP
B / I / U / S
SHADOW
EFFECTキー
KICK
WAIT
SUNGLASS
CURTAIN
TIMER
ALIAS
WRITE
INCLUDE
STAGE
SCREEN
SPACE
WINDOW
PLUGIN
ICON
CURSOR
FORM
INPUT
COMMAND
BOOKMARK
TITLE
COVER
END
SNAP
TRAP
! / #
カード関連
その他




ENTER / EXIT

 ENTER出来る人物は、最大20人まで。これを超えると、エラーメッセージが出る。

 通常、後からENTERされた人物の方が上に表示される。が、正確には、人物がENTERされる時、その時点で一番深いレイヤーにその人物が配置される。、  具体的に例を挙げて書いておく。

<ENTER NAME="1">
<ENTER NAME="2">
<ACT NAME="1" SRC="~">
<ACT NAME="2" SRC="~">
<EXIT NAME="1">
<ENTER NAME="3">
<ACT NAME="3" SRC="~">

 この場合、"3"の画像が"2"より下に来る。"1"がEXITされた時点で、一番深いレイヤーが空く。ここで新たに"3"がENTERされた時、この時点で空いている最も深いレイヤーは"1"のあった所となり、"3"はここに割り当てられることになる。
 このため、後からENTERされたにも関わらず、"3"は"2"よりも深いレイヤーとなる。
 下に汚い図を示しておく。




ACT

 ALPHA属性を指定したとき、LEFT属性もしくはTOP属性に負の値を指定した場合、その値が適用されない。適用されないだけでなく、画像が歪む場合もある。

 ALPHA属性でマスク画像が指定されている場合、TRANSPARENT属性は無視される。

 マスク処理をする際、WIDTH属性及びHEIGHT属性で画像を拡大・縮小する場合は、マスク画像を表示サイズに合わせておく必要がある。



P / BR



W



BACKGROUND



BGM

</BGM TIME="500" MODE="PASS">

のように、BGMをフェードアウトさせている途中で、更に

</BGM>

と入れると、ボリュームコントロールの音量が下がる。
TIMEで指定した時間+200msほど経過していれば、問題ない。
この辺はPCの性能によって誤差があるかもしれない。



SOUND



A HREF

 Aタグはヘルプにもある通り、

<A HREF="選択1" ALT="選択肢1">
<A HREF="選択2" ALT="選択肢2">
<A HREF="選択3" ALT="選択肢3">

というように、間にAタグ以外のタグ(コメント行も含む)を挟まずに並べなければならない。逆に言えば、Aタグだけを延々並べて、選択肢を沢山表示する事も出来ることになる。
 しかし、無限に表示することは出来ない。正常に動作するのは、100個目のAタグまでである。実際には画面に収まらないので、通常特に意識する必要はない。
 以下、検証方法(参考)

<A HREF="選択" ALT="選択肢" VIEW="0">

という文を99個並べてから、続けて

<A HREF="選択" ALT="選択肢">

という文を適当に並べる。結果は選択肢が1つだけ表示される。99個目までの選択肢は、VIEW属性が偽であるため、表示されない。100個目はVIEW属性が真である(省略すると、真として扱われる)為、正常に表示される。101個目以降は、VIEW属性は真だが、限界数をオーバーしている為表示されない。



A NAME

 1つのファイルの中に同名のラベルが複数存在する場合、一番最後のラベルが参照される。

 HTMLでは、#を付けても正常に動作することがあるが、DNMLではつけてはならない。


<A NAME="{LABEL}">

とした場合、"LABEL"というカードが存在していると、参照することが不可能となる。
 また、LABELに何らかの値が入っていたとしても、"{LABEL}"というラベルとして扱われる。



QUESTION



MEMO

 →関連



EVENT



FONT



NEWLINE(NL) / NEWPAGE(NP)



INDENT



POSITION



CLIP



B / I / U / S



SHADOW



EFFECTキー

 デフォルトのエフェクトは、テンプレート内でALIASとして指定されている。

<ALIAS SRC="EF_DEFAULT_BACK" DEST="~">
<ALIAS SRC="EF_DEFAULT_CHAR" DEST="~">

で再指定可能。EF_DEFAULT_BACKがBACKGROUNDや/CURTAINの時のエフェクト、EF_DEFAULT_CHARがACTの時のエフェクトである。



KICK



WAIT



SUNGLASS

 COLOR="#808080" でSUNGLASSを使用していないときと同じになる。



CURTAIN

 /CURTAINまでにHREFを使用すると、EF_NONEと同等の効果でCURTAINが解除される。INCLUDEならば、このようなことは起こらない。



TIMER

 初心者にありがちなミスだが、BGMとの同期を取るためのタグであるので、ウェイトを取る目的で使用してはならない。ウェイトを取る場合は、Wタグを使う。



ALIAS

 INCLUDEと同様、ブックが読み込まれた時点で、そのファイル中に含まれるALIASタグは、全て解決される。その際、EVENTタグ等による分岐は無視される。



WRITE

 同じ名前のカードとエイリアスが同時に存在する場合、カードの値が出力される。

<QUESTION ANSWER="(WRITE=[CARD])">
<ALIAS SRC="WRITE" DEST="ALIAS">
<WRITE SRC="WRITE">

というコードの出力は、

CARD

である。



INCLUDE

 INCLUDEタグは、大抵『環境設定.dnml』やテンプレートを読み出す時にしか利用されてないのだろうが、非常に便利な物である。但し、制約も多い。

・ 仕様
 ブックが読み込まれた時点で、そのファイル中に含まれるINCLUDEタグは、全てその中身に置き換えられる。その際、EVENTタグによる分岐は無視される。

 以下、補足事項。

1. パス指定で『{ }』は使えない

<INCLUDE SRC="{変数}/テンプレート.dnml">

 例えば、このような文は正常に動作しない。  INCLUDEはそのDNMLブックが読み込まれた時点で、全て最初に読み込まれる為、値が変動する可能性がある変数は使用出来ないようになっているのかもしれない。

2. INCLUDEされるファイル内ではA NAMEを使用してはならない
 A NAMEタグが使われているファイルを、同一ブック内で複数回INCLUDEすると、想定外の動作をする。
 以下に例を挙げる。

HREF.SDNMLの内容
  ・・・
  <A HREF="#1">
  ・・・
  <A NAME="1">
  ・・・

INCLUDE.DNML
  1<P>
  <INCLUDE SRC="HREF.SDNML">
  2<P>
  <INCLUDE SRC="HREF.SDNML">
  3<P>
  <INCLUDE SRC="HREF.SDNML">
  4<P>

 このINCLUDE.DNMLを実行した時、1の行の後に4の行に飛ぶ。INCLUDE.DNMLのINCLUDE文は、HREF.SDNMLの内容に置き換えられている。同一ブック内でA NAMEで同名のラベルを配置すると、最後のみが有効となる(→
関連)。そのため、1の行の後のINCLUDE文中のコードを実行中に、3の行の後のINCLUDE文中に移動している。そして、INCLUDE文中のコードを実行後、4の行となる。
 回避方法は、HREFを使わずにEVENTで処理する、もしくはINCLUDEを使わずにHREFを使う、のどちらかの手段を用いればよい。

3. INCLUDEされるファイルが実行されるディレクトリはINCLUDEした側が実行されるディレクトリである
 INCLUDEされるファイルのコードは、全てINCLUDEした側のコード中に置き換えられている。このため、INCLUDEされるファイル中のコードのカレントディレクトリは、INCLUDEした側のカレントディレクトリとなる。  以下に例を挙げる。
 Aというディレクトリ(フォルダ)の中にあるBというディレクトリにB1.SDNMLとG.JPGというファイルがあるとする。B.SDNMLには、

<BACKGROUND SRC="G.JPG">

という文を含むとする。
 ディレクトリAにあるDNMLブックから、B.SDNMLをINCLUDEするには、

<INCLUDE SRC="B/B1.SDNML">

という文を書けばよい。
 これを実行すると、画像表示でエラーが起こる。B.SDNMLのBACKGROUNDでは、カレントディレクトリがA/なので、A/G.JPGを読み込もうとしている。G.JPGは、A/B/G.JPGが正しいパスなので、エラーが起こる。

4. 自分自身をINCLUDEすることは出来ない。
 例を挙げると、A.SDNMLというファイルの中でA.SDNMLをINCLUDEするとエラーが起こる。
 また、A.SDNMLからB.SDNMLをINCLUDEし、そのB.SDNMLからA.SDNMLをINCLUDEしても、同様にエラーが起こる。
 これにより、INCLUDEを使った再帰処理は不可能と言う事になるが、そんなことをしようとする人は少ないと思われる。



STAGE

 ウインドウサイズは640×480以下でなければならない。
 どこかにある非公式パッチを適用させれば、800×600まで動作可能。ただし、自己責任で。URLも提示はしない。



SCREEN



SPACE



WINDOW



PLUGIN



ICON



CURSOR



FORM



INPUT



COMMAND



BOOKMARK



TITLE



COVER



END



SNAP



TRAP



! / #



カード関連

 カードに代入できる数は整数のみ。小数を代入しようとした場合、カードと解釈され、同名のカードが無い限り、代入される値は0となる。
 負の数を直接代入する場合、[ ]を使って文字列として代入しなければ正しく動作しない。

 演算結果の小数点以下は切り捨てられる。
 0で除算を行うと、結果は0となる。ついでに、剰余も0となる。

 整数の領域は、C言語で言うところの『long int型』の領域と等しい。
 16ビットのシステムでは、-231~231-1 = -2147483648~2147483647 の範囲。
 この範囲で考えておけば、恐らく問題ない。

 { }を二重に使うことはできない。例えば、{変数{変数2}}のような記述は、無効。


 半角数字で始まるカード名は、誤動作の可能性がある。

<QUESTION ANSWER="(変数=[aaaa])">
<write src="変数"><NL>
<QUESTION ANSWER="(変数2=変数)">
<write src="変数2"><NL>
<QUESTION ANSWER="(変数3={変数})">
<write src="変数3"><NL>
<QUESTION ANSWER="(変数4=[{変数}])">
<write src="変数4"><NL>
<NL>
<QUESTION ANSWER="(1変数=[aaaa])">
<write src="1変数"><NL>
<QUESTION ANSWER="(2変数=変数)">
<write src="2変数"><NL>
<QUESTION ANSWER="(3変数={変数})">
<write src="3変数"><NL>
<QUESTION ANSWER="(4変数=[{変数}])">
<write src="4変数"><NL>

 このようなブックを実行すると、結果は

aaaa
aaaa
0
aaaa

aaaa
1
0
aaaa

となる。
 変数2と2変数では処理内容が同じであるにもかかわらず、結果が違っている。
 大抵は問題ないが、文字列を扱う時に2変数のような、他の変数の値を代入する時に正常に動作しない。
 何かが間違ってる気がしないでもない。


<QUESTION ANSWER="(変数1={変数2})">

 これを実行すると、変数1の中身は0となっている。つまり、値を代入する時は、素直に

<QUESTION ANSWER="(変数1=変数2)">

としなければならない

<QUESTION ANSWER="((a=[A])&(b=[B]))">
<QUESTION ANSWER="(c=[{a}{b}])">
<WRITE SRC="c"><NL>

このようなブックを実行した時、実行結果は

AB

となる。
 PAW掲示板の過去ログにおいて、文字列連結の方法として書き込まれているものである。確かに連結されているように見えるが、実際には連結されていない。
 上のブックに、下記の文を加える。

<QUESTION ANSWER="(a=[α])">
<WRITE ANSWER="c"><NL>
<QUESTION ANSWER="(b=[β])">
<WRITE ANSWER="c"><NL>

これを実行すると、

AB
αB
αβ

となる。
 cの値は変えていないのに、aやbの値を変えると実行結果が変わっている。
 ここでcに入っている値は、aとbの文字列を連結させた『AB』では無く、『{a}{b}』という文字列である。これは、

<MEMO SRC="c" DEST="BOOK">

として、セーブしてみればわかる。
 見かけ上は連結されているので、通常使用する際には影響ないが、MEMOタグによって値をMEMOファイルに出力する時には注意する必要がある。上記の通り、cに入っている値は『{a}{b}』なので、『AB』という値が入っていると思っていても、もう一度開いた時には『AB』をいう出力結果は得られない。この場合は、aとbについてもMEMOファイルに出力しておく必要がある。ここでは2変数の連結について述べているが、1変数でも同様である。


<EVENT ANSWER="((J=(I+1))&(PASS_{I}?PASS_{J}))">

という文で、I=Jの時、結果は常に真となる。
 例えばI=J=3の時、この文で想定している動作は、

<EVENT ANSWER="((J=(3+1))&(PASS_3?PASS_4))">

であり、PASS_3とPASS_4を比較する事である。
 実際の動作は、

<EVENT ANSWER="((J=(3+1))&(PASS_3?PASS_3))">

となる。右側のJには、値が変わる前のJの値が入っている。その為、PASS_3とPASS_3を比較している。従って、Iがどんな値であろうと、同じ物同士を比べることになる。故に、恒真である。
 上ではI=Jのケースを上げたが、I≠Jでも問題は起こる。
 例えば、I=2,J=4で、PASS_2=34,PASS_3=34,PASS_4=23の時、想定する動作はPASS_2とPASS_3の比較である。過程の通り、想定する動作は真。実際の動作はPASS_2とPASS_4の比較であり、値は34と23の為、等しくない。つまり偽となる。
 これを正常に動作させる為には、

<QUESTION ANSWER="(J=(I+1))">
<EVENT ANSWER="(PASS_{I}?PASS_{J})">

とすればよい。
 ……まあ、そもそもこんなことを試す方がどうかしているのだが。



その他

 &amp;amp;

と記述すると、

 &

としか表示されない。本来ならば、&amp;と表示されるはずである。&amp;quot;、&amp;nbsp;でも同様の現象が発生する。&amp;lt;、&amp;gt;は正常に表示される。
 カードもしくはエイリアスとWRITEタグを使用すれば、強引に回避することが出来る。



Return