きっと、アナログ時計のサンプルがどっかにあるはず…と探してみますと、ありました。
Pebble Developer サイトのBestPracticeページに、Examplesリンクがありまして、その先の GitHub にたくさんのサンプルが!watchfaces – simple_analog とか、まさにこれですね!これ、見てみましょう。こういう Watchfaceです。

ソースもヘッダとCファイル1本だけのシンプルなものです。良いですね。ヘッダでは、短針/長針の形と、各時刻ごとの線の形状を定義しているだけですね。
そしてCファイルのほう。針描画のキモになるのは…これです!
GRect bounds = layer_get_bounds(layer);
GPoint center = grect_center_point(&bounds);
int16_t second_hand_length = bounds.size.w / 2;
time_t now = time(NULL);
struct tm *t = localtime(&now);
int32_t second_angle = TRIG_MAX_ANGLE * t->tm_sec / 60;
GPoint second_hand = {
.x = (int16_t)(sin_lookup(second_angle) * (int32_t)second_hand_length / TRIG_MAX_RATIO) + center.x,
.y = (int16_t)(-cos_lookup(second_angle) * (int32_t)second_hand_length / TRIG_MAX_RATIO) + center.y,
};
// second hand
graphics_context_set_stroke_color(ctx, GColorWhite);
graphics_draw_line(ctx, second_hand, center);
これ完璧ですね!ここを参考にさせてもらいつつ、長針/短針を線で描画するプログラム書きました。
static void drawArrow(Layer *layer, GContext *ctx)
{
GRect bounds = layer_get_bounds(layer);
GPoint center = grect_center_point(&bounds);
int16_t arrow_length = bounds.size.w / 2;
time_t now = time(NULL);
struct tm *t = localtime(&now);
int32_t arrow_angle = 0;
for(int index = 0;index < 2;index++)
{
if( index == 0 ){ //短針
arrow_length = bounds.size.w / 2.5;
arrow_angle = (TRIG_MAX_ANGLE * (((t->tm_hour % 12) * 6) + (t->tm_min / 10))) / (12 * 6);
graphics_context_set_stroke_color(ctx, GColorBlack);
}else{ //長針
arrow_length = bounds.size.w / 2;
arrow_angle = TRIG_MAX_ANGLE * t->tm_min / 60;
graphics_context_set_stroke_color(ctx, GColorBlack);
}
GPoint arrow = {
.x = (int16_t)(sin_lookup(arrow_angle) * (int32_t)arrow_length / TRIG_MAX_RATIO) + center.x,
.y = (int16_t)(-cos_lookup(arrow_angle) * (int32_t)arrow_length / TRIG_MAX_RATIO) + center.y,
};
graphics_draw_line(ctx, arrow, center);
}
}
こいつを layer_update_callback から呼んであげれば…
ただいま、23時35分です!時計っぽくなったよ!
あとは、これ、定期的に更新する仕組みですね。さっきのwatchfaces – simple_analog をもう一度見てみましょう。
むむ、init() のところで、何かやってますね…。
tick_timer_service_subscribe(SECOND_UNIT, handle_second_tick);
これ、デジタル時計の時にやった定期的に呼び出す処理だ!これで何を呼んでいるかというと…
static void handle_second_tick(struct tm *tick_time, TimeUnits units_changed) {
layer_mark_dirty(window_get_root_layer(window));
}
ん?これだけ?なんだこれは。 layer_mark_dirtyとは…
void layer_mark_dirty(Layer * layer)
Layerを”dirty”にマークするものらしい。dirtyにマークされたレイヤーは、システムが再描画(update_proc呼び出し)してくれるそうだ。layer_mark_dirtyを呼んだ瞬間に再描画されるわけではなく、非同期で短時間後に再描画されるとのこと。
サンプルプログラムでは1秒に1回これを呼ぶことで、1秒ごとの再描画をしていたのだな。僕の作っているやつは秒針は無いので、1分に1回の再描画でよいってことだ。
tick_timer_service_subscribe(MINUTE_UNIT, handle_minute_tick);
こうか。(関数名も合わせたよ!)
そして、時は動き出す…!

