Section 3.2 レイヤを作る

前回はウィンドウを作ったから、今回はウィンドウの中に表示するレイヤを作ってみるね。
ウィンドウには画像を表示したりとかできないの?
うん、画像を表示したり文字を表示したりするためにはレイヤが必要だよ。
でも、レイヤは単体では作れなくて、必ずウィンドウに所属してなくちゃいけないんだ。
あ、そうなんだ。
というワケで、前回作った SimpleWindow クラスのコンストラクタで、このウィンドウに所属するレイヤを作ることにするね。

<プライマリレイヤを持つウィンドウ>

class SimpleWindow extends Window
{
    // コンストラクタ
    function SimpleWindow()
    {
        super.Window();  // スーパークラスのコンストラクタを呼び出します

        // プライマリレイヤを作ってウィンドウに管理してもらいます
        add(new Layer(thisnull));

        // ※これ以降プライマリレイヤは primaryLayer プロパティで参照できます

        // プライマリレイヤのサイズをウィンドウのクライアント領域のサイズに合わせます
        primaryLayer.setSize(innerWidth, innerHeight);

        visible = true;  // ウィンドウを表示状態にします
    }

    // デストラクタ:スーパークラスのデストラクタを呼び出します
    function finalize()
    {
        super.finalize();
    }
}  // SimpleWindow クラスの定義はここまで

var win = new SimpleWindow();  // ウィンドウを作ります

じゃ、まずは実行してみて。
うん、わかった。

<実行結果>

表示されたウィンドウとレイヤ

ウィンドウの中の白い部分がレイヤ?
うん、そうだよ。
レイヤを作った後、何も書き込んでないし画像も読み込んでないから、こんなふうに真っ白になってるんだ。
じゃあこれがレイヤの初期状態なんだね。
ん〜、最初に作られるレイヤの初期状態はこうなんだけど、 2番目以降に作られるレイヤは、初期状態では見えないんだ。
えっ、そうなの? なんで?
最初に作るレイヤはちょっと特別なレイヤだから。
詳しいことはもうちょっと後で説明するね。
うん、わかった。
じゃあ、スクリプトの方を見ていくね。
うん。
コンストラクタ以外は前と同じだから、コンストラクタだけ説明するね。
えっと、コンストラクタの中にある add(new Layer(this, null)); っていうのがよくわからないんだけど…これってレイヤを作ってるんだよね?
うん、そだよ。
レイヤを作るためのクラスは Layer クラスって言うんだ。
これもそのままの名前だね。
だからわかりやすいでしょ。
Layer クラスのコンストラクタには引数が2つあるんだ。
1つ目はこのレイヤが所属するウィンドウで、2つ目はこのレイヤの親レイヤ。
第1引数が『this』で、第2引数は『null』ってなってるけど、これってどういう意味なの?
第1引数の this は『このクラスのオブジェクト』っていう意味。
つまり、このレイヤは SimpleWindow クラスのウィンドウに所属してるってこと。
なるほど、そういうことね。
で、第2引数には親レイヤのオブジェクトを指定してるんだ。
親レイヤって?
レイヤには親子関係があって、子レイヤは色々親レイヤの影響を受けるんだ。
例えば、子レイヤは必ず親レイヤよりも手前に表示されるとかね。
ちなみに、KAG だと背景レイヤが親レイヤで、前景レイヤとかメッセージレイヤが子レイヤっていう関係があるよ。
そっか、確かに背景レイヤは奥の方にあって、前景レイヤは手前にくるもんね。
で、null っていうのは「何のオブジェクトでもない」っていう意味。
つまり、このレイヤには親レイヤは無いよって言ってるわけ。
親レイヤってなくてもいいの?
普通のレイヤには必ず親レイヤがあるんだけど、一番最初に作るレイヤは プライマリレイヤ っていう特別なレイヤで、 このレイヤだけは親レイヤを持たないんだ。
プライマリレイヤ?
プライマリレイヤは同じウィンドウに所属する他の全部のレイヤの親になるレイヤで、 1つのウィンドウに対して1つだけ作る必要があるんだ。
ふぅん、そうなんだ。
じゃあ、add っていうのは?
addWindow クラスのメソッドで、ウィンドウが管理するオブジェクトを追加するメソッド。
ウィンドウが管理するオブジェクトってどういうこと?
ウィンドウが管理してるオブジェクトは、ウィンドウが無効化される時に自動的に無効化されるから、無効化するためのスクリプトを書かなくてもいいんだ。
へー、それって便利だね。
うん。
あと、プライマリレイヤを作った後は、primaryLayer っていうプロパティでプライマリレイヤのオブジェクトを参照できるようになるんだ。
ってことは、その次の行の primaryLayer.setSize(innerWidth, innerHeight); っていうのは、プライマリレイヤのサイズを設定してるの?
ん、そう。
レイヤにもウィンドウと同じようにサイズを設定する setSize メソッドがあるから、 これを使ってプライマリレイヤをウィンドウのクライアント領域と同じ大きさにしてるの。
じゃあ、第1引数がレイヤの幅で、第2引数がレイヤの高さってことだよね。
そ。あと位置を設定する setPos メソッドもあるんだけど、 これはレイヤによって基準点、つまり座標が (0, 0) の点が違うから気をつけてね。
えっ、それってどういうこと?
プライマリレイヤの場合はウィンドウのクライアント領域の左上が基準点になるんだけど、 それ以外のレイヤの場合は親レイヤの左上が基準点になるんだ。
そっか、じゃあプライマリレイヤ以外はウィンドウじゃなくて親レイヤを基準にしなくちゃいけないんだね。
そう。それと、Window クラスの setPos メソッドは引数が2個だったけど、 Layer クラスの setPos メソッドは引数が4個あるんだ。
第1引数と第2引数は左端の位置と上端の位置だよね。
第3引数と第4引数って何なの?
第3引数はレイヤの幅で、第4引数はレイヤの高さ。
つまり Layer クラスの setPos メソッドは setSize メソッドの機能も持ってるってことだね。
ちなみに位置だけ変えたい時は第3、第4引数は省略しても OK だよ。
へぇ、そうなんだ。
レイヤのメソッドやプロパティはまだまだいっぱいあるから、今回説明したの以外は追々説明していくことにするね。
詳しくは、吉里吉里2リファレンスの『Layer クラス』の項目を参照してね。
うわ、ほんとにいっぱいあるね〜。
でしょ。これも全部とはいかないけど、必要になったら説明してくね。
は〜い!
じゃあ、次はレイヤの親子関係についてもうちょっと詳しく説明するね。
子レイヤは必ず親レイヤより手前に表示されるんでしょ?
うん、そう。でも他にも色んな性質があるんだよ。
例えば、子レイヤは親レイヤの範囲外には表示できないんだ。
それってどういうこと?
んー、例えば…

<兄弟関係のレイヤを作るスクリプト>

class SimpleWindow extends Window
{
    var layer1, layer2;  // メンバ変数:2つともレイヤです

    // コンストラクタ
    function SimpleWindow()
    {
        super.Window();  // スーパークラスのコンストラクタを呼び出します

        setInnerSize(200, 150);  // innerWidth を 200, innerHeight を 150 に設定します

        add(new Layer(thisnull));
        primaryLayer.setSize(innerWidth, innerHeight);

        // layer1 を作ります
        layer1 = new Layer(this, primaryLayer);
        add(layer1);
        // 親レイヤ(プライマリレイヤ)の左上の位置に表示します。サイズは 120×90 です
        layer1.setPos(0, 0, 120, 90);
        // 薄い青色(不透明度=255, R=192, G=192, B=255)でレイヤ全体を塗りつぶします
        layer1.fillRect(0, 0, layer1.width, layer1.height, 0xFFC0C0FF);
        layer1.visible = true;

        // layer2 を作ります
        layer2 = new Layer(this, primaryLayer);
        add(layer2);
        // 親レイヤ(プライマリレイヤ)の左上から右に 60 ピクセル、下に 45 ピクセルの位置に表示します。サイズは 120×90 です
        layer2.setPos(60, 45, 120, 90);
        // 薄い赤色(不透明度=255, R=255, G=192, B=192)でレイヤ全体を塗りつぶします
        layer2.fillRect(0, 0, layer2.width, layer2.height, 0xFFFFC0C0);
        layer2.visible = true;

        caption = "赤と青は兄弟です";
        visible = true;
    }

    // デストラクタ:スーパークラスのデストラクタを呼び出します
    function finalize()
    {
        super.finalize();
    }
}  // SimpleWindow クラスの定義はここまで

var win = new SimpleWindow();  // ウィンドウを作ります

これはプライマリレイヤの他に2つのレイヤを追加したスクリプトなんだけど、ちょっと実行してみて。
うん。

<実行結果>

実行の結果表示されたウィンドウと兄弟関係のレイヤ

2つのレイヤが重なって表示されてるね。
スクリプトの中の layer1layer2 を作ってるところを見るとわかると思うけど、 この2つのレイヤはどっちもプライマリレイヤが親レイヤになってるんだ。
ちなみに青い方が layer1 で赤い方が layer2 ね。
確かにどっちのレイヤもコンストラクタの第2引数が primaryLayer になってるね。
この2つのレイヤみたいに、同じ親レイヤを持ってるレイヤの関係を兄弟関係っていうんだ。
なるほど、親が同じだから兄弟なんだね。
うん。
で、兄弟関係のレイヤはこんなふうに普通に表示されるんだ。
重なってる部分は、特に順序を指定しない限り、後に作られたレイヤの方が手前にくるよ。
あ、だから赤いレイヤが手前に表示されてるんだね。
じゃあ今度は layer2 のコンストラクタの第2引数を変えて、 layer2layer1 の子レイヤになるようにしてみるね。

<親子関係のレイヤを作るスクリプト>

class SimpleWindow extends Window
{
    var layer1, layer2;  // メンバ変数:2つともレイヤです

    // コンストラクタ
    function SimpleWindow()
    {
        super.Window();  // スーパークラスのコンストラクタを呼び出します

        setInnerSize(200, 150);  // innerWidth を 200, innerHeight を 150 に設定します

        add(new Layer(thisnull));
        primaryLayer.setSize(innerWidth, innerHeight);

        // layer1 を作ります
        layer1 = new Layer(this, primaryLayer);
        add(layer1);
        // 親レイヤ(プライマリレイヤ)の左上の位置に表示します。サイズは 120×90 です
        layer1.setPos(0, 0, 120, 90);
        // 薄い青色(不透明度=255, R=192, G=192, B=255)でレイヤ全体を塗りつぶします
        layer1.fillRect(0, 0, layer1.width, layer1.height, 0xFFC0C0FF);
        layer1.visible = true;

        // layer1 の子レイヤとして layer2 を作ります
        layer2 = new Layer(this, layer1);
        add(layer2);
        // 親レイヤ(プライマリレイヤ)の左上から右に 60 ピクセル、下に 45 ピクセルの位置に表示します。サイズは 120×90 です
        layer2.setPos(60, 45, 120, 90);
        // 薄い赤色(不透明度=255, R=255, G=192, B=192)でレイヤ全体を塗りつぶします
        layer2.fillRect(0, 0, layer2.width, layer2.height, 0xFFFFC0C0);
        layer2.visible = true;

        caption = "青は赤の親です";
        visible = true;
    }

    // デストラクタ:スーパークラスのデストラクタを呼び出します
    function finalize()
    {
        super.finalize();
    }
}  // SimpleWindow クラスの定義はここまで

var win = new SimpleWindow();  // ウィンドウを作ります

layer2 のコンストラクタの第2引数が layer1 になってるから、 layer2 の親レイヤが layer1 になるってことだよね?
ん、そう。じゃ実行してみて。
はーい。

<実行結果>

実行の結果表示されたウィンドウと親子関係のレイヤ

あれっ、赤いレイヤがちっちゃくなっちゃったよ?
赤いレイヤ、つまり子レイヤはちっちゃくなったんじゃなくて、親レイヤの範囲外に出てる部分が表示されてないんだよ。

<子レイヤの表示可能範囲>

子レイヤの表示可能範囲の図

子レイヤの点線の部分は親レイヤの範囲の外に出てるから表示されないんだ。
あ〜、そういうことね。
あと、親レイヤが移動すると、それに合わせて子レイヤも移動するんだ。
例えばこのスクリプト。

class SimpleWindow extends Window
{
    var layer1, layer2;  // メンバ変数:2つともレイヤです

    function SimpleWindow()
    {
        // 中略

        layer1.left += 50;  // ←この行を追加
        caption = "青は赤の親です";
        visible = true;
    }

    // 以下略
}

var win = new SimpleWindow();  // ウィンドウを作ります

layer1left50 を足してるってことは、 layer1 を右に 50 ピクセル移動してるってこと?
ん、そういうこと。
じゃあこれ実行してみて。
うん。

<実行結果>

layer1を移動させた結果

あ、ホントだ。子レイヤも右に移動してるね。
つまり、親レイヤが動いても、親レイヤと子レイヤの位置関係は変わらないってこと。
じゃあ、親レイヤが移動した後も layer2 の左上の点は layer1 の左上の点から (60, 45) の位置にあるってこと?
そうそう。
あと、親レイヤが非表示になれば子レイヤも見えなくなるよ。
子レイヤって色々親レイヤの影響を受けるんだねぇ。
うん。
あ、ちなみに子レイヤが移動しても親レイヤは移動しないから、そこんとこ注意してね。
ってことは、子レイヤは親レイヤの影響を受けるけど、親レイヤは子レイヤの影響を受けないってこと?
基本的にはそうだね。
子レイヤが非表示になっても親レイヤは見えなくならないし。
なるほどね〜。
親子関係の性質は他にもあるんだけど、それはまた必要になった時に説明するね。
うん、りょーかい。
…あっ、そーいえば fillRect っていうメソッドの事まだ聞いてないよね?
あー、確かにまだ説明してなかったね。
fillRect メソッドはレイヤを塗りつぶすメソッドだよ。
じゃあ、このメソッドで layer1layer2 に色をつけてたの?
ん、そだよ。
fillRect はレイヤの内部を四角形に塗りつぶすメソッドで、引数はこうなってるよ。

fillRect メソッドの引数>
引数名引数の意味
第1引数left塗りつぶす四角形の左上の点の x 座標
第2引数top塗りつぶす四角形の左上の点の y 座標
第3引数width塗りつぶす四角形の幅
第4引数height塗りつぶす四角形の高さ
第5引数value塗りつぶす色

さっきのスクリプトだと、第1引数と第2引数はどっちも 0 になってるから…塗りつぶす四角形の左上の点はレイヤの左上の点と同じ位置ってこと?
うん。
第3引数と第4引数はそれぞれレイヤの幅と高さになってるから、塗りつぶす四角形はレイヤと同じ大きさになるんだ。
つまり、レイヤ全体を塗りつぶすってことだね。
じゃあ、第5引数の 0xFFC0C0FF とか 0xFFFFC0C0 っていうのは、どうやって色を指定してるの?
第5引数の指定の仕方はレイヤの描画方式によって違うんだけど、描画方式を特に指定してない layer1layer2 の場合は 0xAARRGGBB 形式で色を指定するんだ。
AA の部分には不透明度、RR, GG, BB の部分にはそれぞれ赤、緑、青の値を16進数で指定するの。
不透明度は position タグとかで言うところの opacity 属性のことね。
えっと…layer1 は不透明度が FF で赤と緑の値が C0 で青の値が FF になってて、 layer1 は不透明度が FF で赤の値が FF で緑と青の値が C0 になってるってこと?
うん、そうだよ。
ちなみに16進数の C0192 で、FF は指定できる最大の値で 255 だよ。
じゃあ、layer1 は青の値が最大になってて、layer2 は赤の値が最大になってるから、 layer1 は青い色で、layer2 は赤い色になってるってことだよね?
ん、まぁそういうことだね。
じゃ、今回はこんなところかな。次回はレイヤに画像を読み込んでみるね。
は〜い!
それじゃ、また次回ね。


前へ | TOP | 次へ