前回 STEP 2 の clearBack
メソッドをやったから、今回は STEP 3 の初期履歴メッセージを表示するスクリプトを見てくね。 ちなみに初期履歴メッセージってのは、メッセージ履歴画面を表示した時最初に表示される履歴メッセージのことね。 |
|
STEP 3 って STEP 3-1 と STEP 3-2 に分かれてるよね? | |
初期履歴メッセージの表示処理は everypage が true になってるか false になってるかで違ってるから、2種類表示処理があるんだ。 | |
※everypage については §10.4 参照。 | |
つまり、メッセージ履歴をページごとに表示するかどうかで実行するスクリプトが違うってことだよね? | |
そういうことだね。 それじゃとりあえず、STEP 3-1 の everypage が true の時(メッセージ履歴をページごとに表示する時)のスクリプトから見てくことにするね。 |
|
は〜い。 | |
この辺の処理はカスタマイズしてないから、 元々のメッセージ履歴レイヤ(HistoryLayer)クラスの dispInit メソッドに書いてあるスクリプトが実行されるよ。 |
<HistoryLayer クラスの dispInit メソッド(HistoryLayer.tjs より抜粋)>
今回は clearBack メソッドより先のスクリプトを見てくね。 | |
最初に “if(everypage) ” っていう
if ブロックがあるね。 これって everypage が true だったら if ブロックの中身が実行されるってことだから、 つまり if ブロックの中身が STEP 3-1 のスクリプトってことなのかな? |
|
ん、そうだよ。 で、逆に everypage が false だったら、こっちの else ブロックの中身の方が実行されるから… |
|
else ブロックの中身が STEP 3-2 のスクリプトってことだね。 | |
そ。じゃまずは if ブロックの中身から見てくね。 | |
if ブロックの中にまた
if ブロックがあるね。 今度は dataPages って値が 0 より大きいかどうかをチェックしてるみたいだけど。 |
|
dataPages は HistoryLayer クラスのメンバ変数で、
メッセージ履歴が何ページ分あるかを表してるんだ。 つまり “dataPages>0” はメッセージ履歴が1ページ分以上あれば真(true)になるってことだね。 |
|
じゃあ “dataPages>0” が偽(false)だったら、 メッセージ履歴が1ページもないってコト? | |
まぁそういうことだね。 で、dataPages が 0 より大きかったら if ブロック、 そうじゃなかったら else ブロックの中身がそれぞれ実行されるわけね。 |
|
どっちのブロックも canScroll と dispStart っていう変数?に値を代入してるね。 | |
canScroll と dispStart はどっちも HistoryLayer クラスのメンバ変数で、 everypage が true の時は、canScroll はページを切り替えられるかどうかを表してて、 dispStart は今何ページ目が表示されてるかを表してるんだ。 | |
えっと、じゃあ dataPages が 0 より大きかったら(dataPages>0)、 canScroll が true になるからページを切り替えられて、 あと、dispStart は dataPages - 1 になるから、 今表示されてるページは dataPages - 1 ページ目ってこと? | |
そう。ここでは「今表示してるページが dataPages - 1
ページ目」ってのは「メッセージ履歴画面に最初に表示されるページが
dataPages - 1 ページ目になる」って思っといて。 ちなみにページ数は 0 から始まるから、 dataPages - 1 ページ目は最後のページってことだよ。 |
|
じゃあメッセージ履歴画面を表示すると、 まずメッセージ履歴の最後のページが表示されるってことだよね。 | |
ん。で、dataPages が 0 より大きくない場合、 つまり dataPages が 0 の場合は… | |
※dataPages はマイナスにはならないので、dataPages が 0 より大きくないということは dataPages は 0 ということになります。 | |
canScroll が false になるからページを切り替えられなくて、あと dispStart は 0 になるから、メッセージ履歴画面に最初に表示されるページは 0 ページ目、つまりメッセージ履歴の最初のページってことだよね? | |
そういうこと。 | |
…あれ? でも dataPages が 0 ってことは、 履歴メッセージが1ページもないってことだから、何にも表示できないんじゃないの? |
|
dataPages が 0 の時(履歴メッセージが1ページ分に満たない時)は、 今まで表示したメッセージを全部メッセージ履歴画面に表示するようになってるんだ。 | |
? | |
要するに、履歴メッセージが1ページ分に満たない時は、 everypage を true にしてても、 everypage が false になってる時と同じように履歴メッセージが表示されるってこと。 | |
へぇ、そーなんだ。 | |
まとめると、dataPages が 0 より大きい時は canScroll が true になるから、 履歴メッセージのページ切り替えができて、 あとメッセージ履歴画面を表示した時に最初に表示されるのは、履歴メッセージの最後のページってことだね。 | |
dataPages が 0 の時は canScroll が false になるから、 履歴メッセージのページ切り替えはできなくて、 あとメッセージ履歴画面には everypage を false にしてる時と同じように履歴メッセージが表示されるんだよね。 | |
そう。 | |
あ、ちょっと思ったんだけど… | |
ん? | |
履歴メッセージが1ページ以上あれば canScroll が
true になるんだから、
履歴メッセージが1ページしかなくてもページを切り替えられるってことだよね? それってなんかヘンじゃない? |
|
…よくそこに気付いたね。 確かにそーなんだけど、実はメッセージ履歴が1ページしかない時(dataPages が 1 の時)は canScroll が true になっててもページが切り替えられないようになってるんだ(詳しい説明は省略させてもらうね)。 だからその辺はあんまり気にしないで。 |
|
そーなんだ。わかった。 じゃあその次で呼び出してる drawPage ってメソッドは何してるの? |
|
drawPage メソッドは現在のページ(dispStart に設定されてるページのことね)の履歴メッセージ内容を表示するメソッドだよ。 | |
ってことは、このメソッドの中でメッセージ履歴レイヤにメッセージを書き込んでるんだね。 | |
そうだよ。 このメソッドは直接カスタマイズするわけじゃないんだけど、 結構重要なメソッドだから詳しく見ていくことにするね。 |
|
わかった。 | |
これが drawPage メソッドのスクリプトだよ。 |
<drawPage メソッド(HistoryLayer.tjs より抜粋)>
じゃ、とりあえず最初から見てくね。 | |
最初に getPage ってメソッドを呼び出して、 戻り値を page って変数に代入してるみたいだね。 | |
getPage は引数に指定したページの履歴メッセージを取得するメソッドなんだ。 だから、getPage(dispStart) の戻り値は、 今表示してるページの履歴メッセージが格納されてる配列への参照になるの。 |
|
それって具体的にはどんな配列なの? | |
そーだね…これは図にしてみた方がわかりやすいかな。 例えば、こんなふうに今表示してるページに4行のメッセージがあったら、 page は4つの要素を持つ配列になるの。 |
<現在表示中のページの履歴メッセージが格納されている配列 page の内容>
0行目のメッセージ(横書きの場合は一番上の行のメッセージだね)の内容が
page[0] に入ってて、
1行目のメッセージが page[1] に入ってて…って感じだね。 1つの要素に1行分のメッセージが入ってるからわかりやすいでしょ? |
|
そーだね。 | |
だから、この配列の要素の中身を順番にメッセージ履歴レイヤに書き込んでいけば、 このページの履歴メッセージが全部書き込めるわけね。 | |
なるほどね。 | |
getPage メソッド自体は今回のカスタマイズに直接関係ないから、
詳しい説明は省略させてもらうね。 で、次はこの if ブロックのとこね。 |
|
“if(verticalView)” ってことは、 履歴メッセージを縦書き表示してる時に if ブロックの中身が実行されるんだね。 | |
そ。ちなみに横書き表示してる時は、こっちの else
ブロックの中身が実行されるよ。 横書き表示の方がよく使うと思うから、先に else ブロックの中身から見てくことにするね。 |
|
りょーかい。 | |
まずこの変数 y に代入してる値はわかるよね? | |
controlHeight + marginT だから、 「次ページ」とかのボタンの高さと履歴メッセージを表示するときの上側の余白の高さを足した値を y に代入してるんだよね。 | |
そ。この図を見るとわかると思うけど、 controlHeight + marginT は最初の行(0行目)のメッセージを表示する y 座標になるんだ。 | |
ホントだ。 じゃあ変数 y には最初の行のメッセージを表示する y 座標の値が代入されるってことだね。 |
|
ん。じゃ次いくね。 次はこの for ブロックなんだけど、 ループする条件はわかる? |
|
repageLine って今までに出てきたことあったっけ? | |
あ、そっか。まだ出てきてなかったね。 repageLine は HistoryLayer クラスのメンバ変数で、 メッセージ履歴レイヤに表示できるメッセージの行数が代入されてるんだ。 例えばこの図の例だと16行メッセージが表示できるから、 repageLine は 16 になってるの。 |
|
※横書き表示の時は repageLine = (height - marginT - marginB - controlHeight) \ lineHeight、縦書き表示の時は repageLine = (width - marginL - marginR) \ lineHeight と計算されます。 | |
ってことは…i が 0 から repageLine - 1 までの間、i を1ずつ増やしながらループするってことだね。 | |
メッセージ履歴レイヤに書き込む履歴メッセージは page[0]〜page[repageLine-1] に入ってるから、 この for ループの中で page[i] をチェックして、 履歴メッセージを1行ずつメッセージ履歴レイヤに書き込んでいくってことね。 | |
確かに for ループの中で最初に pages[i] が空文字列じゃないかどうかチェックしてるね。 | |
page[i] が空文字列だったらメッセージを書き込む必要ないから、 page[i] が空文字列じゃない時だけメッセージを書き込んでるんだ。 | |
そっか。なるほどね。 | |
ちなみに、さっきの例みたいに4行しか履歴メッセージがない時は、 page[4] から page[repageLine-1] までは void になってるんだ。 | |
え、じゃあ page[i] が void かどうかもチェックしなくちゃいけないんじゃないの? | |
page[i] が void の時は “ page[i]!="" ” は偽(false)になるでしょ。 | |
そーなの? | |
!= 演算子は両側の値の型が合わない時は、
自動的に両側の値の型を合わせて比較するからね。 で、void は文字列型にすると空文字列だから、 “ page[i]!="" ”は偽(false)になるの。 この辺は1章でやったでしょ。 |
|
※§1.9 参照。 | |
え〜っと…そーだったっけ? | |
そーだよ。 んで、page[i] が空文字列(または void)じゃなかったら、 drawText メソッドを呼び出してメッセージ履歴レイヤに履歴メッセージを書き込むわけね。 |
|
なんか第1引数に getLineStart2 っていうメソッドみたいのが入ってるんだけど、これって? | |
getLineStart2 メソッドはインデントの長さを取得するためのメソッドだよ。 …って言ってもよくわかんないかな? |
|
うん、わかんない。 | |
…だよね。 じゃこれも図にしてみよっか。 |
<getLineStart2 メソッドにより取得されるインデントの長さの例>
まず、indent タグと endindent タグは知ってる? | |
セリフとかを表示する時に、それぞれの行の文章の先頭の表示位置を合わせるのに使うよね。 例えば、この図の場合だと… |
<indent/endindent タグによるインデント(字下げ)の例>
こんなふうに書くと、2行目以降の文章の先頭が1行目の「例えば…」の下に表示されるんだよね。 | |
そうそう。 で、この図の場合だと、0行目と2行目と3行目にはインデントが無くて、 1行目にはインデントがあるよね。 |
|
そーだね。 | |
getLineStart2 メソッドはインデントの長さを返すメソッドだから、
0行目と2行目と3行目に対しては 0 になって、
1行目に対しては、1行目のインデントの長さ(この場合は
52(ピクセル)だね)になるわけね。 ちなみに getLineStart2 メソッドの第1引数にはページを指定して、 第2引数には何行目かを指定するようになってるよ。 |
|
えっと、じゃあ dispLineStart2(dispStart, 0) と dispLineStart2(dispStart, 2) と dispLineStart2(dispStart, 3) は 0 になって、 dispLineStart2(dispStart, 1) が 52 になるってことだよね。 | |
そ。だから、drawText メソッドの第1引数に “marginL + dispLineStart2(dispStart, i)” を指定すれば、インデントがあってもなくても、テキストの左端の位置がちゃんと揃うわけだね。 | |
インデントがなかったら dispLineStart2 メソッドの戻り値は 0 になるから、普通に marginL の位置にテキストを表示して、 インデントがあったら marginL にインデントの分をプラスした位置に表示するってことかな。 | |
ん、そういうこと。 あと第2引数〜第6引数はわかる? |
|
※drawText メソッドの引数については §3.4 参照。 | |
第2引数(テキストの上端の位置を指定する引数だよね)の y って、
最初に controlHeight + marginT を代入してたよね。 これって0行目のメッセージの位置だから、0行目のとこに書き込んでるってことだよね? |
|
for ブロックの中身が最初に実行された時はそうだね。 でもここで “y += lineHeight;” を実行してるから、 1回ループするごとに y の値は lineHeight ずつ増えていくよね。 |
|
…ってことは、lineHeight はメッセージ1行分の高さだから、 1回ループするごとに1行分ずつメッセージを書き込む位置が下に移動してくってことかな? | |
そ。つまり、for ループで1行ずつメッセージを書き込んでるってことね。 あと、第3引数が page[i] になってるでしょ。 |
|
page[i] って i 番目の行のメッセージってことだよね。 | |
ん。だから、最初のループ(i = 0)で0行目の位置(controlHeight + marginT)に0行目のメッセージ(page[0])を書き込んで、 次のループ(i = 1)で1行目の位置(controlHeight + marginT + lineHeight)に1行目のメッセージ(page[1])を書き込んで…って感じでそれぞれの行のメッセージが書き込まれていくわけね。 | |
なるほどね〜。 | |
あと、第4、第5、第6引数はそれぞれ文字の色、文字の不透明度、アンチエイリアスをするかどうかだね。 | |
第4引数の historyColor って、確か Config.tjs で設定してたよね。 | |
※§10.2 参照。 | |
そだね。 | |
第5引数は 255 だから、不透明ってことだよね。 あと第6引数は antialiased になってるけど、これって? |
|
antialiased は文字にアンチエイリアスをかけるかどうかを表す HistoryLayer クラスのメンバ変数で、 メニューバーとかからアンチエイリアスの設定を変更したりしてなければ、Config.tjs で設定できるアンチエイリアスの設定(defaultAntialiased)と同じ値になってるよ。 | |
そーなんだ。 | |
じゃこれで横書き表示の時のスクリプトは一通り確認できたから、
次は縦書き表示の時のスクリプトを見てくね。 …って言っても横書き表示のスクリプトとそんなに変わんないけどね。 |
|
確かに見た目は似てるね。 | |
まぁ一応最初から見てこっか。 まず、変数 x に値を代入してるとこからだね。 |
|
width - marginR っていう値を代入してるね。 | |
width - marginR はどんな値かわかる? | |
ん〜…横書き表示の時は、最初 y に0行目のメッセージの上端の位置を代入してたよね… 今度は縦書き表示だから、x に代入してるのは0行目のメッセージの左端の位置、かな? |
|
まぁそうなるような気はするんだけど、width - marginR は0行目のメッセージの左端じゃなくて右端の位置だよ。 | |
えっ、そーなの? | |
width - marginR が0行目のメッセージの右端の位置になってるってのは、 この図を見るとわかりやすいと思うよ。 | |
…確かに右端の位置になるね。 でもなんで左端じゃなくて右端なの? |
|
それはね、メッセージを縦書き表示する時にはちょっと特殊な設定をしなくちゃいけないからなんだけど、 詳しくはもうちょっと後で説明するから、ちょっと待ってね。 | |
そーなんだ、わかった。 | |
じゃ次は for ループのとこだね。 ループの条件は横書き表示の時と同じだから大丈夫だよね? |
|
うん、おっけーだよ。 | |
for ブロックの中身でやってることも基本的に横書き表示の時と同じだね。 | |
page[i] が空文字列(または void)じゃなかったら drawText メソッドでメッセージ履歴レイヤにメッセージを書き込んでるんだね。 | |
そう。 | |
あ、そーいえば… | |
ん? | |
drawText メソッドでメッセージをレイヤに書き込むと横書きになるよね? ここでフツーに drawText メソッドを呼び出してメッセージを書き込んだら横書きになっちゃうんじゃないの? |
|
うん、だからメッセージを縦書き表示する時にはちょっと特殊な設定をやらなくちゃいけないんだ。 | |
特殊な設定って? | |
Font クラスって憶えてる? | |
えっ? …えーと、確か前にフォントの種類とかサイズとかを指定するのに使ったよーな気がするけど…? |
|
ん、Font クラスの face プロパティでフォントの種類を指定したり、height プロパティでフォントサイズを指定したりしたよね。 | |
※Font クラスについては §3.5 参照。 | |
それとメッセージの縦書き表示にどんな関係があるの? | |
じゃあちょっとこのスクリプトを first.ks に書き込んで実行してみて? |
う〜ん…何のために実行するのかよくわかんないけど… とりあえず実行してみるね。 |
|
うん。 |
フツーに“あいうえお”って表示されたね。 | |
このスクリプトでやってることはわかるよね? | |
え〜っとね…kag.fore.base.font が表画面の背景レイヤのフォントのオブジェクトになってて、 face プロパティと height プロパティでフォントの種類とサイズを指定して、 それから drawText メソッドでレイヤに“あいうえお”って書き込んでるんだよね? | |
ん、そうそう。 それじゃ、次はこのスクリプトを first.ks に書き込んで実行してみて。 |
さっきとあんまり変わってないみたいだけど… “kag.fore.base.font.angle = 2700;” の行が追加されてるのかな? |
|
ん、そうだよ。 じゃちょっと実行してみて。 |
|
はーい。 |
あっ、メッセージが縦向きに表示されてる! | |
縦書き表示の時と同じ向きになってるでしょ。 | |
…でも字の向きが縦書き表示の時と違うよね? | |
じゃ今度はこのスクリプトを first.ks に書き込んで実行してみて。 |
これさっきのスクリプトとおんなじなんじゃ…? | |
確かによく似てるけど、kag.fore.base.font.face が “MS ゴシック” じゃなくて “@MS ゴシック” になってるでしょ? | |
あ、ホントだ。“@” が付いてる。 これってどーゆー意味なの? |
|
説明は後でまとめてするから、とりあえず実行してみて。 | |
う、うん。わかった。 |
あ、これこれ。これが縦書き表示だよね! | |
…ってワケで、Font クラスの angle プロパティと face プロパティを縦書き用に設定すれば、 こんなふうに縦書き表示ができるんだ。 | |
へぇ、縦書き表示って Font クラスを使うんだね。 | |
それじゃさっきのスクリプトを詳しく見てこっか。 | |
うんっ。 | |
まず angle プロパティだけど、 これは文字の角度(文字の向き)を設定するためのプロパティなんだ。 | |
2700 になってるけど、これってどんな角度なの? | |
angle プロパティに指定するのは角度の10倍の値だから、 2700 は 270°ってことだよ。 | |
270°…って言われてもどんな向きなのかあんまりよくわかんないんだけど…? | |
んー、そーだね… じゃいくつか例を挙げてみるね。 |
こんなふうに、angle プロパティの値を変えると
360°どの向きにでも表示できるよ。 ちなみに角度(angle)には 0°の時を基準にして反時計回りに何度回転させるかを指定するんだ。 |
|
なるほどねぇ… | |
ただ、これだけだと 270°に設定した時、 1つ1つの文字の向きも 270°回転しちゃうから、 文字の向きが変わっても縦書き表示に見えるようにするために、縦書き用フォントを使うの。 | |
縦書き用フォント? | |
さっき face プロパティにフォント名を設定する時に、 “@MS ゴシック” っていうふうに、 フォント名の前に “@” を付けてたでしょ。 | |
うん。 | |
フォント名の前に “@” を付けると縦書き用フォントって意味になるんだ。 | |
へぇ、そーなんだ。 | |
ちなみに、縦書き用フォントは… |
<普通のフォントと縦書き用フォント(角度はどちらとも 0°で表示)>
こんなふうに、元々それぞれの文字が回転してるから、 270°で表示した時にちゃんと縦書き表示になるんだ。 | |
へぇ、こんなフォントがあるんだね… | |
ただし、“MS ゴシック” とか “MS 明朝” みたいによく使われるフォントには縦書きフォントがあることが多いけど、 どんなフォントでも縦書き用のフォントが用意されてるとは限らないから注意してね。 | |
そーなんだ。わかった。 | |
あともう1つ注意しないといけないのが、drawText メソッドで文字を書き込む時の位置だね。 | |
え、どこに注意しなくちゃいけないの? | |
今まで drawText メソッドの第1引数と第2引数は、 文字を表示する左端と上端の座標っていうイメージだったよね。 | |
そーなんじゃないの? | |
angle プロパティが 0 の時はそうなんだけど、 angle プロパティに 0 以外の値を指定すると、 こんなふうに必ずしも左端と上端にはならなくなるんだ。 |
<drawText メソッドの第1引数(x)と第2引数(y)に対応する点>
この図を見るとわかると思うけど、例えば angle が 2700(270°)の時は、 drawText メソッドの第1引数に指定した点は左端じゃなくて右端になるんだ。 | |
ホントだ、右端になってるね… でもなんでこーなるの? |
|
angle プロパティが 0 の時の“あいうえお”を、 ●を中心にして反時計回りに 270°回転させると、 ●の位置が右上にくるでしょ。 | |
えっと…そーなの? | |
じゃあ angle プロパティが 0 の時の“あいうえお”を、 ●を中心にして時計回りに 90°回転させるって考えてみて。 | |
あ、確かにそー考えると●の位置が右上にくるね。 | |
ってワケだから、縦書き表示の時に実行されるスクリプトのここんとこで変数 x に代入してる width - marginR が0行目のメッセージの右端の位置になってるの。 | |
あー、そーゆーコトなんだ。 それじゃあ、メッセージ履歴レイヤに縦書きでメッセージを書き込む時も angle プロパティが 2700 になってるんだ? |
|
うん。メッセージ履歴レイヤ(HistoryLayer)クラスのオブジェクトを作る時に、
Config.tjs に書いてある verticalView の設定をチェックして、
true(縦書き表示)になってたら、
フォントを縦書き用に設定して angle プロパティを
2700 に設定してるんだ。 この辺の処理は自動的に実行されるから、普段は意識することないと思うけどね。 |
|
※上記の処理は HistoryLayer クラス(HistoryLayer.tjs 内で定義されています)のコンストラクタ内で実行されています。 | |
なるほどねぇ。 | |
縦書き表示の時に呼び出される drawText メソッドの引数はまだちゃんと見てなかったから、一応ここで改めて確認しとくね。 | |
はーい。 | |
まず第1引数の x は OK かな? | |
x って0行目だけじゃなくって、1行目以降も右端の位置になるんだよね? | |
そーだよ。 あと、縦書き表示の時はメッセージを右から左に書き込んでいくから、 1回ループするごとに x から lineHeight(メッセージ1行分の幅)を引いてってるわけね。 |
|
そっか。左に行くってことは x 座標の値が小さくなるってことだもんね。 | |
じゃ次は第2引数ね。 | |
今度は第2引数に getLineStart2 メソッドが出てきてるね。 | |
getLineStart2 メソッドの戻り値は縦書きの時もインデントの長さだよ。 横書きの時は インデントの長さ=インデントの幅 だったのが、 縦書きだと インデントの長さ=インデントの高さ になるけどね。 あと、インデントがない時の戻り値は横書きの時と同じで 0 ね。 |
|
えっと、じゃあインデントがない時は marginT + controlHeight の位置にメッセージを表示して、 インデントがある時は marginT + controlHeight にインデントの高さをプラスした位置にメッセージを表示するってことかな。 | |
※marginT + controlHeight の位置についてはこちらの図参照。 | |
ん、そういうこと。 じゃこれで drawPage メソッドは一通りチェックできたから、 今回はここまでにしとこっか。 |
|
うん、そーだね。 | |
今回で STEP 3-1 が終わったから、
次回は STEP 3-2 の処理を見てくことにするね。 それじゃ、また次回! |