Section 5.4 ボタン用レイヤ(その2)

今回はボタン画像の更新処理について見ていくね。
それって、ボタンを押した時とかにボタン画像を切り替える処理のことなんだよね?
ん、そうだよ。
で、それをやってるのが drawState っていうメソッド。
drawState メソッド…
あ、これかな。

drawState メソッド(57行目付近)>

function drawState(s)
{
    // 状態 s に対応する画像を描画
    // s :  0 : 普通の状態
    //      1 : ボタンが押された状態
    //      2 : ボタンの上にマウスカーソルがある状態
    //     (3): フォーカスがある場合
    if(!enabled)
    {
        s = 0; // 無効状態
    }

    if(Butt_imageLoaded)
    {
        // ボタンイメージが読み込まれている
        // TODO: keyboard focus
        imageLeft = -s * width;
    }
    else
    {
        if(Butt_keyPressed) s = 1; // 押されている

      :
      :
    (以下略)

な、なんかすごい長いし複雑なんだけど…
あぁ、それなら大丈夫。
前回 Butt_imageLoaded はずっと true になってるって言ったでしょ。
う、うん。
スクリプトをよく見てみて。
長くて複雑な部分は else ブロックの中なわけでしょ。
あ、確かにそうだね。
じゃあ、その else ブロックの中身が実行される条件は?
え? え〜っと、if ブロックの中身が実行される条件が Butt_imageLoaded が真になってるってことだよね。
else ブロックの中身が実行される条件はその逆で Butt_imageLoaded が偽になってるってことだから…
あ!
わかった?
Butt_imageLoaded がずっと true になってるってことは、 else ブロックの中身は実行されないってことだよね?
そういうこと。
つまり、グラフィカルボタンの場合は、drawState メソッドはこうなってるって考えても OK ってワケ。

function drawState(s)
{
    // 状態 s に対応する画像を描画
    // s :  0 : 普通の状態
    //      1 : ボタンが押された状態
    //      2 : ボタンの上にマウスカーソルがある状態
    //     (3): フォーカスがある場合
    if(!enabled)
    {
        s = 0; // 無効状態
    }

    // ボタンイメージが読み込まれている
    // TODO: keyboard focus
    imageLeft = -s * width;
}

これなら簡単そうだね。
じゃ、スクリプトを見ていこっか。
うん!
まず、最初の if なんだけど…
enabled ってプロパティだよね?
§3.9 とかで、タイマーの enabled プロパティを設定したもんね。
うん、そう。Layer クラスにも enabled プロパティがあるんだ。
タイマーの時は enabled プロパティでタイマーをセットしたり止めたりしたけど、 レイヤの enabled を設定するとどうなるの?
レイヤの場合は、enabled プロパティでレイヤに対する操作ができるかどうかが設定できるんだ。
それってどういうこと?
ん〜、ボタンの場合で説明した方がわかりやすいかな。
要するに enabledtrue だとボタンを押せるけど、 false だとボタンを押せなくなるの。
へぇ、そうなんだ。
ま、enabled プロパティについてはまた後で出てくるから、 その時に詳しく説明するね。
りょーかい。
じゃ if ブロックの話に戻るけど、ここで何やってるか解る?
えーっと、まず if ブロックの中身が実行される条件は !enabled だから、 enabledfalse ってことだよね。
うん、つまりボタンが使えない状態のときってことだね。
そのときは、s = 0; が実行されるから…引数がどんな値になってても s0 にしちゃうってことだよね?
そ。この sコメントの部分に書いてある通りボタンの状態を表してて、 s の値によって表示する画像が決まるんだ。
s0 だと『普通の状態』って書いてあるね。
ボタンが使えない時用の画像は元々用意してないから、普通の状態の画像を使うってことだね。
なるほどね。
で、その後 imageLeft = -s * width;s の値に応じてボタンの画像を設定してるの。
imageLeft って今までに見たことないよね?
名前からすると imageWidth とか imageHeight と関係がありそうだけど…。
うん。imageLeft もレイヤが持ってる画像に関するプロパティで、 レイヤの表示オフセットの左端を表すんだ。
ちなみに imageTop っていうプロパティもあって、 これはレイヤの表示オフセットの上端を表すんだ。
レイヤの表示オフセット…?
レイヤの表示オフセットっていうのは、レイヤが持ってる画像のどの部分が表示されてるかを表す値だよ。
例えば、表示サイズが 50×50 ピクセルのレイヤに、サイズが 100×100 ピクセルのこの画像を読み込んだとするね。

<レイヤに読み込まれている画像(100×100ピクセル)>

レイヤに読み込まれている画像
※赤・緑・青・黄の正方形はすべて同じサイズ(50×50ピクセル)です。

この画像を読み込んだ後、このレイヤの width, height, imageWidth, imageHeight がそれぞれいくつになってるか解る?
えっと、レイヤの表示サイズは 50×50 ピクセルだから、 widthheight はどっちも 50 だよね。
ん、そうだね。
あと、読み込んだ画像のサイズは 100×100 ピクセルだから、 imageWidthimageHeight はどっちも 100 かな。
うん、正解。
じゃあ、画像を読み込んだ直後は、レイヤはどんなふうに表示されてると思う?
え? え〜っと…レイヤが持ってる画像のサイズは 100×100 ピクセルだけど、 レイヤの表示サイズは 50×50 ピクセルしかないから…画像全体は表示できないよね。
うん、もちろん画像の一部しか表示されないんだけど、どの部分が表示されると思う?
う〜ん、なんとなくだけど…左上の赤い四角形、かな?
そ、正解。
実際やってみるとこんな感じに表示されるよ。

<実際の表示>

実際に表示されたレイヤ

あ、勘で答えたんだけど、合ってたんだ。
うん。ただ、赤い四角形が表示されるのはデフォルトの状態、 つまり imageLeftimageTop がどっちも 0 の時なんだ。
じゃあ、imageLeftimageTop の値を変えると、 表示される部分も変わるってこと?
うん、そういうこと。
例えば、imageLeft-50imageTop0 に設定すると、こんなふうに表示されるよ。

imageLeft-50imageTop0 の時の表示>

表示されたレイヤ

あ、今度は緑色の四角形が表示されたね。
でもなんでこうなるの?
imageLeft は、レイヤの左端から見たときの、 レイヤが持ってる画像の左端の位置を表すんだ。
だから、imageLeft-50 になってるってことは、 レイヤが持ってる画像の左端が、レイヤの左端よりもさらに左に 50 ピクセルの位置にあるってことになるの。
図にするとこんな感じだよ。

imageLeft-50 の時のレイヤと画像の位置関係>

レイヤと画像の位置関係
※表示されない部分(レイヤの表示領域の外側にある部分)は薄く表示しています。

えっと、imageLeft って -50 なの?
50 になるんじゃないの?
imageLeft はレイヤの左端の位置が基準点になるからね。
レイヤが持ってる画像の左端はレイヤの左端よりも左側にあるでしょ?
うん。
それと、座標は左に行くほど値が小さくなるでしょ?
そうだね。
だから、こんなふうにレイヤの左端を (0,0) とすると、 レイヤが持ってる画像の左端の位置は (-50,0) になるんだ。

<レイヤの左端を基準とした時の座標系>

レイヤの左端とレイヤ画像の左端の位置関係

う〜ん…確かにそう言われればそうだけど、なんかややこしいね。
ん〜、じゃあ、画像の表示したい部分の左上の座標にマイナスをつけた値が imageLeftimageTop になる、って覚えたらどうかな?

imageLeftimageTop の指定法>

表示したい領域の左上の座標とimageLeft,imageTopの関係

緑色の四角形の左上の座標は (50,0) だから、left50 で、 top0 でしょ。
うん、そうだね。
だから、レイヤに緑色の四角形を表示したい時は、imageLeft-left-50 になって、 imageTop-top-0、つまり 0 になるワケ。
あ、それだとちょっとわかりやすいかも。
じゃあ、レイヤに青い四角形を表示したい時は、imageLeftimageTop はどう指定したらいい?
えっと、青い四角形の左上の座標は (0,50) だから、 imageLeft0 で、 imageTop-50 だよね。
そうそう。
じゃあ、黄色い四角形をレイヤに表示したい時は?
黄色い四角形の左上の座標は (50,50) だから、 imageLeft-50 で、 imageTop-50 だね!
ん、正解。
これで imageLeftimageTop の指定の仕方は解ったよね?
うん、ばっちり!
んじゃ、drawState メソッド の話に戻るね。
imageLeft = -s * width; っていう所だったよね。
うん。じゃあまず、s0, 1, 2 の時に、 imageLeftimageTop の値がそれぞれどうなるか考えてみて。
imageTop の値って変えてないよね?
うん、だからずっとデフォルトの値のまま。
ってことは…ずっと 0
そ。
じゃあ…こんな感じになるよね。

s の値と imageLeft, imageTop の値の関係>
 s imageLeftimageTop
000
1-width0
2-2 * width0

ん、そうだね。
じゃあ、s0, 1, 2 の時にボタン用レイヤに表示されるのは、 それぞれボタン用画像のどの部分になる?
さっきみたいに lefttop で考えてみて。
leftimageLeft にマイナスをつけた値で、 topimageTop にマイナスをつけた値になるんだから…こうだよね。

s の値とレイヤに表示される画像の位置(left, top)の関係>
 s left top 
000
1width0
22 * width0

そう。だから、こんなふうに表示されるわけ。

s0, 1, 2 の時の表示>

sが0〜2の時の表示

そっか〜、こうやってボタンの画像を切り替えてたんだね。
どう? drawState メソッド でやってることは解った?
うんっ!
それじゃ、今回はここまで。
次回は ButtonLayer クラスのイベントハンドラを見ていくね。
イベントハンドラって、マウスのボタンをクリックした時とかに呼び出されるメソッドだよね?
そ。§3.7 とかで作ったよね。
今回の場合は、例えばマウスのボタンが押されたら、s1 にして drawState メソッドを呼び出す必要があるでしょ。
あ、次回はそういう処理について、ってことなんだね。
そういうこと。
それじゃ、また次回ね!


前へ | TOP | 次へ