10.14 メッセージ履歴のカスタマイズ 〜背景画像の表示〜(その1)

やっとメッセージ履歴のカスタマイズ基本編が終わったから、今回からメッセージ履歴画面をさらに拡張する話に入るね。
ホント基本編って長かったよねぇ…
まぁメッセージ履歴画面をカスタマイズしようと思うと色々やらなきゃいけないしね。
で、今回からやっていくのは、メッセージ履歴画面に背景画像を表示する機能の追加だよ。
前にメッセージ履歴画面に背景画像を表示するのは結構タイヘンって言ってたと思うけど、 フツーにメッセージ履歴レイヤに画像を表示するだけじゃダメなの?
メッセージ履歴レイヤもレイヤの一種だから、もちろん画像を表示することはできるけど、 単純にメッセージ履歴レイヤに背景画像を読み込むだけじゃうまくいかないんだ。
そーなの? なんで?
ま、これは実際にやってみるとどうなるかってのを見た方がいいかな。
メッセージ履歴レイヤに直接背景画像を読み込んでメッセージ履歴画面を表示すると、こんな感じになるの。

<メッセージ履歴レイヤに直接背景画像を読み込んで表示したメッセージ履歴画面>

ちゃんと表示されてるじゃない?
メッセージ履歴画面を表示した直後はね。
どーゆーコト?
履歴メッセージをスクロールすると…

<履歴メッセージをスクロールした後の状態>

あれ、背景がなんかヘンだね?
スクロールしてきた履歴メッセージの部分の背景画像が消えちゃってるからこんなふうに見えるんだ。
え、なんで背景画像が消えちゃうの?
なんでだかわかんない?
うん。だって今までメッセージ履歴レイヤに背景画像なかったし。
じゃメッセージ履歴レイヤにメッセージを書き込む時にどんなことやってたか覚えてる?
えっと、ふつうに drawText メソッドでメッセージを書き込んでるんじゃなかったっけ?
その前にやってることがあったでしょ?
§10.11 の scrollUp メソッドとかで出てきたよね。
あ、そーいえば copyRect メソッドで元々表示されてたメッセージを移動したり、 clearBack メソッドで画面の外に出るメッセージを消したりしてたね。
だからメッセージ履歴レイヤに背景画像を直接表示すると、スクロールした時に背景画像が消えちゃうの。
えっ、なんで?
clearBack メソッドでメッセージ履歴レイヤを塗りつぶしてたでしょ。
その時に背景画像も塗りつぶされちゃうからだよ。
あ、なるほどね。
あと、copyRect メソッドでメッセージを移動すると、その部分の背景画像がずれちゃうしね。
さっきの画像の場合は履歴メッセージを表示する部分の背景が一色だから見た目にはわかんないんだけど。
そっか。だからメッセージ履歴レイヤに背景画像は表示できないんだね。
まぁできないわけじゃないんだけどね。
えっ、そうなの?
履歴メッセージをスクロールするたびにメッセージ履歴レイヤに背景画像を読み込み直して、 それから履歴メッセージを全部書き直せば、メッセージ履歴レイヤに直接背景画像を表示することはできるんだけど、 あんまりスマートなやり方じゃないと思うから、背景画像用のレイヤとメッセージ履歴表示用のレイヤを分けることにしたんだ。
ふぅん、そーなんだ。
さて、前置きが長くなっちゃったけど、これからスクリプトを見ていくことにするね。
はーい。
メッセージ履歴画面に背景を表示する機能を追加したスクリプトはこれね。
それじゃまずは ExtendedHistoryLayer クラスに追加するメンバ変数から見てくね。

ExtendedHistoryLayer クラスに追加したメンバ変数>

class ExtendedHistoryLayer extends HistoryLayer
{
    // 追加したメンバ変数
    var hasBackgroundImage = false// メッセージ履歴に背景画像を表示するか
    var messageLayer; // メッセージ履歴を表示するためのレイヤ(背景画像表示時のみ使用)

    (以下略)
}

まず hasBackgroundImage は、背景画像を表示するかどうかを表わすメンバ変数で、 背景画像を表示する場合は true、 背景画像を表示しない場合(普通のメッセージ履歴画面の背景にする場合)は false になるんだ。
えっと、そのメンバ変数って何のためにあるの?
これからメッセージ履歴画面に背景を表示しようって言ってるんだから、 false になんてならないと思うんだけど?
メッセージ履歴画面はカスタマイズしたいけど、背景画像は表示する必要ないっていう場合もあるでしょ。
そういう時のことも考えて、背景画像を表示するかしないかを選べるようにするの。
あっ、そーなんだ。
じゃあ背景画像を表示しない設定にした時に false になるんだね。
そう。
で、もう一つのメンバ変数 messageLayer は、履歴メッセージを表示するためのレイヤだよ。
え? 履歴メッセージってメッセージ履歴レイヤに表示するんじゃないの?
メッセージ履歴レイヤには背景画像だけを表示するようにして、 履歴メッセージを表示するために新しくレイヤを作るんだよ。
でも、メッセージ履歴レイヤって元々履歴メッセージを表示するレイヤでしょ?
だったら、背景画像を表示するレイヤを新しく作るのが普通じゃない?
えっとね、まず新しく作るレイヤはメッセージ履歴レイヤの子レイヤにするんだ。
新しく作るレイヤも履歴レイヤの一部なわけだし、 あと子レイヤにすれば、メッセージ履歴レイヤの visible を変えるだけで子レイヤも一緒に表示したり非表示にしたりできて便利だからね。
そーなんだ。
でもそれが新しく作る方のレイヤに履歴メッセージを表示するのと関係あるの?
子レイヤって親レイヤの範囲内にしか表示できないよね。
§3.2 参照。
そだね。
あと、子レイヤは必ず親レイヤよりも手前に表示されるよね。
うん。
だから、メッセージ履歴レイヤに履歴メッセージを表示して子レイヤに背景画像を表示すると、 背景画像の方が履歴メッセージより手前に来るから、履歴メッセージが見えなくなっちゃうの。
あっ、そーか。
だから新しく作るレイヤの方に履歴メッセージを表示する必要があるわけ。
なるほどね。
それじゃ次は ExtendedHistoryLayer クラスのコンストラクタを見てくね。

ExtendedHistoryLayer クラスのコンストラクタ>

function ExtendedHistoryLayer(window, parent)
{
    // スーパークラスのコンストラクタを呼び出します
    super.HistoryLayer(window, parent);
    // Override.tjs で定義されている設定を適用します
    (ExtendedHistoryLayer_config incontextof this)();
    // 背景画像が指定されていれば読み込みます
    loadBackgroundImage(backgroundStorage) if backgroundStorage != "";
}

追加してるのは最後の行だけだよ。
それって loadBackgroundImage ってメソッドを呼び出してるとこ?
そ。で、loadBackgroundImage メソッドは新しく作ったメソッドで、スクリプトはこうなってるよ。

loadBackgroundImage メソッド>

function loadBackgroundImage(storage)
{
    loadImages(storage); // 本来のメッセージ履歴レイヤに背景画像を読み込みます
    hasBackgroundImage = true;
}

loadImages メソッドを呼び出して、 hasBackgroundImagetrue にしてるんだね。
loadImages メソッドってレイヤに画像を読み込むメソッドだったよね?
ん。だからここでメッセージ履歴レイヤに背景画像を読み込んでるわけね。
で、メッセージ履歴レイヤに背景画像を表示してるってことがわかるように、 hasBackgroundImagetrue を代入してるの。
ちょっとコンストラクタに戻るけど、この backgroundStorage っていう変数の中身が背景に表示する画像のファイル名になってるの?
ん、そうだよ。
Override.tjs の中でこんなふうに設定できるようになってるよ。

<Override.tjs 内のメッセージ履歴レイヤの背景画像の設定部>

function ExtendedHistoryLayer_config()
{
    // ◆ 履歴レイヤの背景に表示する画像
    // 履歴レイヤ背景用の画像ファイル名を指定します
    // 空文字列("")を指定すると背景に画像を表示せず
    // デフォルトの背景(黒色で半透明の背景)を表示します
    ;backgroundStorage = "history_bg";

    (以下略)
}
ExtendedHistoryLayer_config メソッドについては §10.2§10.3 参照。

で、コンストラクタで loadBackgroundImage メソッドを呼び出すのは、 backgroundStorage が空文字列じゃない時、 つまり背景画像ファイル名が指定されてる時だけだから、 要するに、背景画像を表示する設定になってたら、 コンストラクタで背景画像をメッセージ履歴レイヤに読み込むわけだね。
コンストラクタでやってることってそれだけみたいだけど、 履歴メッセージを表示するレイヤは作らないの?
そっちは必要になってから作ればいいから、コンストラクタじゃなくて dispInit メソッドの方で作るようにしてるんだ。
じゃあメッセージ履歴画面が表示される時に作るってこと?
ん、そういうこと。
じゃ次は dispInit メソッドを見てみよっか。

ExtendedHistoryLayer クラスの dispInit メソッド>

function dispInit()
{
    if(hasBackgroundImage)
    {
        // 背景画像を表示する場合は
        // 本来のメッセージ履歴レイヤ(this)には
        // 背景画像だけを表示する(メッセージ履歴は表示しない)ので
        // メッセージ履歴表示用にレイヤを作成します
        if(messageLayer === void)
        {
            // メッセージ履歴表示用レイヤがまだ作られていなければ
            // 本来のメッセージ履歴レイヤの子レイヤとして作成します
            messageLayer = new global.Layer(window, this);
            // 表示位置とサイズは本来のメッセージ履歴レイヤに合わせます
            messageLayer.setPos(0, 0);
            messageLayer.setSize(width, height);
            messageLayer.hitThreshold = 256; // マウスメッセージは受け取りません
            messageLayer.absolute = 1000;
            messageLayer.visible = true;

            // 本来のメッセージ履歴レイヤと同じフォント設定にします
            var mFont = messageLayer.font;
            mFont.angle = font.angle;
            mFont.bold = font.bold;
            mFont.face = font.face;
            mFont.height = font.height;
            mFont.italic = font.italic;
            mFont.strikeout = font.strikeout;
            mFont.underline = font.underline;
        }
    }

    (これ以降は前と変わっていないので省略)
}

最初の if ブロックを追加してるだけで、 他の部分のスクリプトは前と変わってないから、後半は省略してるよ。
最初の if ブロックって、 “if(hasBackgroundImage)” のブロックのことだよね?
そ。つまり背景画像を表示する設定にした時に実行されるスクリプトを追加したってこと。
じゃこの if ブロックの中身を見てくね。
if ブロックの中にもう一つ if ブロックがあって…
条件は “messageLayer === void” だから、履歴メッセージを表示するレイヤが void だったら if ブロックの中身が実行されるってことだよね?
つまり 2番目の if ブロックは、 履歴メッセージを表示するレイヤがまだ作られてない時に実行されるってことね。
えっと、それで2番目の if ブロックの中で、 最初に履歴メッセージを表示するレイヤを作ってるんだよね。
ExtendedHistoryLayer クラスの中でレイヤを作る時は “new Layer” じゃなくて “new global.Layer” になるとこに注意してね。
あ、ホントだ。“global” がついてるね。
これってなんで必要なんだっけ?
Layer クラスのサブクラスの中でレイヤ(Layer クラスのオブジェクト)を作る時は、 “global.Layer” にする必要があったよね。
§7.2 参照。
ExtendedHistoryLayer クラスは Layer クラスのサブクラスだから、global がいるんだね。
直接のサブクラスじゃないんだけど、まず HistoryLayer クラスが Layer クラスのサブクラスになってて、 さらに ExtendedHistoryLayer クラスが HistoryLayer クラスのサブクラスになってるの。
そういう場合も global を付けないといけなんだ。
そーなんだ。
じゃコンストラクタの引数はわかる?
えっと、第1引数が window で、第2引数が this だね。
第1引数にはこのレイヤが所属するウィンドウを指定するから、 messageLayer(履歴メッセージを表示するレイヤ)は window っていうウィンドウに所属してるってことだよね。
あと、第2引数には親レイヤを指定するから、messageLayer の親レイヤが this、つまりメッセージ履歴レイヤになるってことだね。
ん。ちなみに windowLayer クラスのプロパティだよ。
それと、この場合は windowkag になるね。
あ、そーいえば前にも windowkag オブジェクトになってたね。
§9.18 参照。
じゃ次いくね。
setPos メソッドとか setSize メソッドはよく出てくるからわかるよね。
setPos メソッドで messageLayer の位置を (0, 0) に設定してて、setSize メソッドでレイヤのサイズを width×height ピクセルにしてるんだよね。
widthheight ってメッセージ履歴レイヤの幅と高さだっけ?
そうだよ。だから messageLayer の位置とサイズをメッセージ履歴レイヤに合わせてるわけね。
んじゃ次は hitThreshold プロパティの設定ね。
確か、hitThreshold256 にすると、 レイヤをクリックしたとかのマウス関係のイベントが起こらなくなるんだったよね?
hitThreshold プロパティについては §7.2 参照。
ん。メッセージ履歴レイヤの方に、右クリックしたらメッセージ履歴画面を閉じるとかのマウス関係の機能があるから、 messageLayer 側でマウス関係のイベントを受け取る必要がないんだ。
なるほどね。
じゃ次は absolute プロパティの設定ね。
absolute プロパティはレイヤの重ね合わせ順序を設定するプロパティで、 KAG の image タグとかの index 属性とおんなじ意味なんだよね。
そうそう。
これってなんで 1000 にしてるの?
あー、これは適当に設定してるの。
えっ、テキトーって…
あ、適当って言うと語弊があるね。
えっとね、makeButtons メソッドでスクロールバーとかメッセージ履歴画面を閉じるボタンを作った時に、 absolute プロパティの値をそれぞれ 20003000 にしてたよね。
で、スクロールバーと閉じるボタンより奥に messageLayer が表示されるように 1000 にしてるの。
§10.5 参照。
えっと、それってつまり messageLayerabsolute の値は 2000 より小さければいいってこと?
そ。だから別に 1000 にこだわらなくても、 1 とか 1999 とかでも OK。
そういう意味で適当に設定してるって言ったの。
そっか。わかった。
後は visible プロパティの設定だけど、これは問題ないよね。
visibletrue にして、messageLayer が表示されるようにしてるんだよね。
そう。
じゃ次はフォント関係の設定ね。
messageLayer.font” ってのがフォントクラスのオブジェクト?
そ。んで、messageLayer のフォントオブジェクトの参照を mFont に代入してるの。
mFont っていう変数を使ってるのは、この先のスクリプトをすっきりさせるためだよ。
あと、“font” の方はメッセージ履歴レイヤのフォントオブジェクトね。
なんか色んなプロパティを設定してるね。
この中で知ってるプロパティってどれだけある?
えっとね…angle が文字の角度で、 boldtrue にすると文字が太字になって、 face はフォント名で、height は文字の高さで、 italictrue にすると文字が斜体になるんだったかな。
bold, face, height, italic プロパティについては §3.5angle プロパティについては §10.7 参照。
ん、そうだね。
strikeoutunderline っていうのは初めて見るプロパティだと思うよ。
strikeout プロパティは true にすると文字に取り消し線(こういう線)が入って、 underline プロパティは true にすると文字に下線(こういう線)が入るってことになってるんだけど、 この2つのプロパティは今のところ実際には使えないみたいだね。
※吉里吉里 2 version 2.30 Rev.2/KAG 3 version 3.30 Rev.2 現在。
え、どういうコト?
要するに、true にしても線が表示されないってこと。
へぇ、そーなんだ。
で、ここのスクリプトで、messageLayer のフォントの設定をメッセージ履歴レイヤのフォントの設定に合わせてるの。
strikeout とか underline も合わせる必要あるの?
まぁ faceheight 以外は普通変えないから、 合わせてもあんまり意味ないんだけど、一応ね。
ふぅん。そっか。
これで messageLayer は完成だね。
この後 dispInit メソッドでやってることは前と同じだから、 dispInit メソッドはここまでにするね。
りょーかい。
じゃ今回はこれくらいにしとこっか。
それじゃ、また次回ね!


前へ | TOP | 次へ