+2003-11-10 Carl Worth <cworth@isi.edu>
+
+ * src/grrobot.c (grr_game_read_notices): Call new board_view timer
+ functions on the appropriate state transitions.
+
+ * src/grr_board_view.c (grr_board_view_expose): Add code to draw a
+ cute alpha-blended timer which shows off the use of cairo_arc.
+ (grr_board_view_refresh_timer):
+ (grr_board_view_decrement_timer):
+ (grr_board_view_start_timer):
+ (grr_board_view_stop_timer):
+ (grr_board_view_reset_timer): New functions for managing the timer.
+
2003-09-04 Carl Worth <cworth@isi.edu>
* configure.in (PKG_CHECK_MODULES): Require Cairo 0.1.1 or newer.
view->client = NULL;
view->button = 0;
+
+ view->time = 60.0;
+ view->drift_correct = 0.0;
view->timer = 0;
view->cell_width = 0;
cairo_fill (xrs);
grr_icon_draw (view->target_icon[rr_target_idx (goal_target)], xrs);
cairo_restore (xrs);
+
+ /* Draw clock */
+ if (view->time < 60.0) {
+ cairo_save (xrs);
+ cairo_new_path (xrs);
+ cairo_move_to (xrs,
+ (double) view->board_width / 2 * view->cell_width,
+ (double) view->board_height / 2 * view->cell_height);
+ cairo_arc (xrs,
+ (double) view->board_width / 2 * view->cell_width,
+ (double) view->board_height / 2 * view->cell_height,
+ .9 * view->cell_width,
+ - M_PI_2,
+ 2 * M_PI * (60.0 - view->time) / 60.0 - M_PI_2);
+ cairo_close_path (xrs);
+
+ cairo_set_rgb_color (xrs, 0.0, 0.0, 0.0);
+ cairo_set_alpha (xrs, 0.5);
+ cairo_fill (xrs);
+
+ cairo_restore (xrs);
+ }
}
/* Draw walls */
grr_board_view_transform_cell_to_pixel (view, i, j, &x, &y);
gtk_widget_queue_draw_area (GTK_WIDGET (view), x, y, view->cell_width, view->cell_height);
}
+
+#define TIMER_INTERVAL_MS 100
+
+static void
+grr_board_view_refresh_timer (grr_board_view_t *view)
+{
+ int x, y;
+
+ grr_board_view_transform_cell_to_pixel (view,
+ view->board_width / 2 - 1,
+ view->board_height / 2 -1,
+ &x, &y);
+ gtk_widget_queue_draw_area (GTK_WIDGET (view),
+ x, y,
+ 2 * view->cell_width,
+ 2 * view->cell_height);
+}
+
+static gboolean
+grr_board_view_decrement_timer (void *widget)
+{
+ grr_board_view_t *view = widget;
+
+ view->time -= TIMER_INTERVAL_MS / 1000.0;
+ view->time += view->drift_correct;
+
+ grr_board_view_refresh_timer (view);
+
+ return TRUE;
+}
+
+void
+grr_board_view_start_timer (grr_board_view_t *view, double time)
+{
+ /* XXX: It would be good to adjust the clock for latency somewhere... */
+ /* Correct any drift within the next 10 seconds, or half the
+ remaining time --- whichever is less. */
+ if (view->timer) {
+ double correction_time;
+ if (time >= 20.0)
+ correction_time = 10.0;
+ else
+ correction_time = time / 2.0;
+ view->drift_correct = (time - view->time) / (correction_time * TIMER_INTERVAL_MS);
+ } else {
+ view->time = time;
+
+ view->timer = gtk_timeout_add (TIMER_INTERVAL_MS, grr_board_view_decrement_timer, view);
+ }
+}
+
+void
+grr_board_view_stop_timer (grr_board_view_t *view)
+{
+ if (view->timer == 0)
+ return;
+
+ gtk_timeout_remove (view->timer);
+ view->timer = 0;
+ view->time = 0.0;
+
+ grr_board_view_refresh_timer (view);
+}
+
+void
+grr_board_view_reset_timer (grr_board_view_t *view)
+{
+ grr_board_view_stop_timer (view);
+
+ view->time = 60.0;
+ view->drift_correct = 0.0;
+}
/* Button currently pressed or 0 if none */
guint8 button;
- /* ID of update timer, or 0 if none */
- guint32 timer;
+ double time;
+ double drift_correct;
+ guint timer;
grr_icon_t *cell1_icon;
grr_icon_t *cell2_icon;
void
grr_board_view_mark_damage (grr_board_view_t *view, int i, int j);
+void
+grr_board_view_start_timer (grr_board_view_t *view, double time);
+
+void
+grr_board_view_stop_timer (grr_board_view_t *view);
+
+void
+grr_board_view_reset_timer (grr_board_view_t *view);
+
void
grr_board_view_transform_pixel_to_cell (grr_board_view_t *view,
int pixel_x, int pixel_y,
here. */
game->state = RR_GAMESTATE_NEW;
+ grr_board_view_reset_timer (game->board_view);
grr_game_print (game, "\nNew round!");
rr_board_set_goal_target (board, notice->u.target);
gtk_widget_queue_draw (GTK_WIDGET (game->window));
notice->u.number);
break;
case RR_NOTICE_ACTIVE:
+ grr_board_view_stop_timer (game->board_view);
grr_game_printf (game, "\nUser %s now active to demonstrate solution in %d moves.",
notice->u.bid.username,
notice->u.bid.number);
break;
case RR_NOTICE_TIMER:
- grr_game_printf (game, "\nTime remaining: %d seconds.",
- notice->u.number);
+ grr_board_view_start_timer (game->board_view,
+ notice->u.number);
break;
case RR_NOTICE_POSITION:
{