Section 3.10 時計を動かす

今回でやっと時計を動かせるようになるんだよね。
うん。じゃあ早速スクリプトを書いていこっか。
うん!
§3.6のスクリプトをベースにしてスクリプトを書いていくね。
は〜い。
まずはコンストラクタからね。
時計を動かすためには、§3.6のスクリプトのコンストラクタをどう書き換えたらいいと思う?
えっと、表示を更新するためにタイマーが必要だから、タイマーオブジェクトを追加すればいいんだよね?
ん、そだね。
じゃあ、コンストラクタを書いてみて。
あ、タイマーオブジェクトを作る時には timer っていう名前のメンバ変数を使ってね。
うん、わかった。

<時計を動かすために書き換えたコンストラクタ>

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

    add(new Layer(thisnull));  // プライマリレイヤを作ります

    // プライマリレイヤに画像を読み込みます
    with(primaryLayer)
    {
        .loadImages("frame.png");   // プライマリレイヤに frame.png を読み込みます
        .setSizeToImageSize();      // プライマリレイヤのサイズを画像サイズに合わせます

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

    // 日時を書くためのレイヤを作ります
    messageLayer = new Layer(this, primaryLayer);
    add(messageLayer);
    with(messageLayer)
    {
        .setPos(22, 22, 114, 68);        // サイズを 114×68、位置を (22, 22) にします
        .font.face = "MS Pゴシック";  // フォントを「MS Pゴシック」にします
        .font.height = 24;               // フォントの高さを 24 ピクセルに設定します
        .visible = true;
    }

    // タイマーオブジェクトを作ります
    timer = new Timer(this);
    add(timer);  // タイマーオブジェクトをウィンドウに管理してもらいます
    timer.interval = 1000;  // イベントの発生周期を1秒(1000ミリ秒)に設定します
    timer.enabled = true;   // タイマーをオンにします

    drawTime();  // 日時を表示するメソッドを呼び出します

    visible = true;
}

これでいいよね?
ん、これでいいよ。
じゃあ、次は action メソッドを書いてみて。
おっけー。

action メソッド>

function action(ev)
{
    if(ev.target == timer)
    {
        if(ev.type == "onTimer")
            drawTime();  // タイマーイベントが発生するたびに、現在の日時表示を更新します
    }
}

日時を表示する drawTime メソッドがあるから、これを呼び出せばいいだけだよね?
そだね。
じゃあ後は drawTime メソッド。
え? drawTime メソッドはそのままでいいんじゃないの?
ん〜…それじゃとりあえず実行してみよっか。
うん!

<実行結果>

実行の結果表示されたウィンドウ

あれっ!? 表示がおかしくなっちゃったよ!?
drawText メソッドはレイヤに文字を書き込むだけで、 元々書いてある文字列を消してくれるわけじゃないから、 drawTime メソッドを実行するたびに文字が上書きされちゃって、こんなふうになるんだ。
それじゃあ、drawText メソッドで文字を書き込む前に、元々書いてある文字を消さなくちゃいけないってこと?
うん、そういうこと。
でもどうやったら文字を消せるの?
fillRect メソッドって覚えてる?
え? え〜っと…レイヤの内部を塗りつぶすメソッド、だったっけ?
そう。§3.2 で使ったよね。
このメソッドを使うと、元々書いてある文字を消せるんだ。
えっ、そうなの? どうやって?
レイヤを透明色で塗りつぶすの。
? それってどういうこと?
fillRect メソッドの第5引数には、 AARRGGBB 形式で塗りつぶす色を指定するんだったよね。
うん。
例えば 0xFFFF0000 にすると赤色で塗りつぶせるんだよね。
そうそう。
で、透明色で塗りつぶすっていうのは、第5引数に 0x00000000 を指定するってこと。
全部ゼロ?
注目して欲しいのは、AA の部分がゼロになってるってとこ。
AA って不透明度だったよね?
そ。だから、不透明度がゼロってことは、完全に透明ってこと。
あ、もしかして、不透明度ゼロで塗りつぶすとレイヤが透明になるの?
ん、そのとーり。
レイヤ全体を不透明度ゼロで塗りつぶせば、元々書いてあった文字は全部消えて、レイヤ全体が透明になるってワケ。
なるほどねぇ〜。
んじゃ、drawTime メソッドを書き換えてみて。
うん、やってみるね。

<修正版 drawTime メソッド>

function drawTime()
{
    var d = new Date();
    var day_of_week = ["日""月""火""水""木""金""土"];

    // 日付と曜日の文字列を作ります
    var date = (d.getMonth() + 1) + "/" + d.getDate() + "(" + day_of_week[d.getDay()] + ")";

    // 指定の書式で時刻の文字列を作ります
    var time = "%d:%02d:%02d".sprintf(d.getHours(), d.getMinutes(), d.getSeconds());

    with(messageLayer)
    {
        // 上段の文字列の幅と高さを取得します
        var dateWidth = .font.getTextWidth(date);
        var dateHeight = .font.getTextHeight(date);
        // 下段の文字列の幅と高さを取得します
        var timeWidth = .font.getTextWidth(time);
        var timeHeight = .font.getTextHeight(time);
        // 上段の文字列の y 座標(=赤い矢印の高さ)を計算します
        var dateTop = (.height - dateHeight - timeHeight) \ 3;

        // レイヤに書いてある文字を消すために、透明色で塗りつぶします
        .fillRect(0, 0, .width, .height, 0x00000000);
        // 余白の幅、高さをそろえて上段の文字列を書き込みます
        .drawText((.width - dateWidth) \ 2, dateTop, date, 0x000000);
        // 余白の幅、高さをそろえて下段の文字列を書き込みます
        .drawText((.width - timeWidth) \ 2, dateHeight + 2 * dateTop, time, 0x000000);
    }
}

これでレイヤに書いてある文字を消してから文字を書き込めるよね。
うん。それじゃ改めて実行してみよっか。
うん!

<実行結果> ※実際にはちゃんと時計として動作します。

実行の結果表示されたウィンドウ

やったぁ! ちゃんと動いたよっ!
これで時計の部分は完成だね!
やっとここまで来れた〜って感じだね。
確かに、時計を作るって目標を立ててからもう結構経つよね。
だよね〜。
それじゃ、今回はここまでだね。
今回のスクリプトはちょっと長いから、ファイルにしとくね。
次回はサウンドの再生をやるよ。
それってアラームを鳴らすのに使うの?
ん、そだよ。
それじゃ、また次回ね!


前へ | TOP | 次へ