Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2004:
[Freeciv-Dev] (PR#8210) WISHLIST: a sliding mapview
Home

[Freeciv-Dev] (PR#8210) WISHLIST: a sliding mapview

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#8210) WISHLIST: a sliding mapview
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 22 Mar 2004 13:19:11 -0800
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8210 >

> [jdorje - Fri Mar 19 20:56:54 2004]:

> One such thing is a sliding mapview.  Currently when the mapview 
> recenters itself, it jumps all in one move.  It would be nice if smooth 
> "sliding" would be possible.  I think this would greatly improve the 
> feel of the game for new users (advanced users would probably just find 
> it slowing them down).

Here's a better version of the patch.  This solves the wrapping problem
with the use of a gui_distance_vector function.  It is still far from
complete.

jason

Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.94
diff -u -r1.94 mapview_common.c
--- client/mapview_common.c     19 Mar 2004 20:22:07 -0000      1.94
+++ client/mapview_common.c     22 Mar 2004 21:18:13 -0000
@@ -324,11 +324,114 @@
 }
 
 /****************************************************************************
+  A "gui" "native" coordinate system is oriented the same way as the map,
+  but preserves pixel granularity for the canvas. Each tile is of size
+  NORMAL_TILE_WIDTH * NORMAL_TILE_HEIGHT in each direction.
+****************************************************************************/
+static void gui_to_guinat_pos(int *guinat_x, int *guinat_y,
+                             int gui_x, int gui_y)
+{
+  const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
+  int guimap_x, guimap_y;
+
+  /* This echoes the conversion in gui_to_map_pos, except we don't lose
+   * pixel granularity.  We transorm GUI tiles into square tiles with
+   * side W * H. */
+  if (is_isometric) {
+    guimap_x = gui_x * H + gui_y * W;
+    guimap_y = gui_y * W - gui_x * H;
+  } else {
+    guimap_x = gui_x * H;
+    guimap_y = gui_y * W;
+  }
+
+  /* Now convert into a "gui" native position.  This echoes the conversion
+   * in map_to_native_pos, except again we keep pixel granularity. */
+  if (topo_has_flag(TF_ISO)) {
+    *guinat_y = guimap_x + guimap_y - map.xsize * W * H;
+    *guinat_x = (2 * guimap_x - *guinat_y - (*guinat_y & 1)) / 2;
+  } else {
+    *guinat_x = guimap_x;
+    *guinat_y = guimap_y;
+  }
+}
+
+/****************************************************************************
+  A "gui" "native" coordinate system is oriented the same way as the map,
+  but preserves pixel granularity for the canvas. Each tile is of size
+  NORMAL_TILE_WIDTH * NORMAL_TILE_HEIGHT in each direction.
+****************************************************************************/
+static void guinat_to_gui_pos(int *gui_x, int *gui_y,
+                             int guinat_x, int guinat_y)
+{
+  const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
+  int guimap_x, guimap_y;
+
+  /* Convert the "gui-native" position into a "gui-map" position.  This
+   * echoes the conversion in native_to_map_pos, except the scale is
+   * larger. */;
+  if (topo_has_flag(TF_ISO)) {
+    guimap_x = (guinat_y + (guinat_y & 1)) / 2 + guinat_x;
+    guimap_y = guinat_y - guimap_x + map.xsize * W * H;
+  } else {
+    guimap_x = guinat_x;
+    guimap_y = guinat_y;
+  }
+
+  /* Now convert directly into a GUI position.  This echoes the conversion
+   * in map_to_gui_pos, except the scale is larger. */
+  if (is_isometric) {
+    *gui_x = (guimap_x - guimap_y) / (H * 2);
+    *gui_y = (guimap_x + guimap_y) / (W * 2);
+  } else {
+    *gui_x = guimap_x / H;
+    *gui_y = guimap_y / W;
+  }
+}
+
+/****************************************************************************
+  Find the vector with minimum "real" distance between two GUI positions.
+
+  See also map_distance_vector().
+****************************************************************************/
+static void gui_distance_vector(int *dx, int *dy, int gui_x0, int gui_y0,
+                               int gui_x1, int gui_y1)
+{
+  const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
+  const int xsize = map.xsize * W * H, ysize = map.ysize * W * H;
+
+  gui_to_guinat_pos(&gui_x0, &gui_y0, gui_x0, gui_y0);
+  gui_to_guinat_pos(&gui_x1, &gui_y1, gui_x1, gui_y1);
+
+  /* Find the native distance vector. */
+  *dx = gui_x1 - gui_x0;
+  *dy = gui_y1 - gui_y0;
+  if (topo_has_flag(TF_WRAPX)) {
+    *dx = FC_WRAP(*dx + xsize / 2, xsize) - xsize / 2;
+  }
+  if (topo_has_flag(TF_WRAPY)) {
+    *dy = FC_WRAP(*dy + ysize / 2, ysize) - ysize / 2;
+  }
+
+  gui_x1 = gui_x0 + *dx;
+  gui_y1 = gui_y0 + *dy;
+  guinat_to_gui_pos(&gui_x0, &gui_y0, gui_x0, gui_y0);
+  guinat_to_gui_pos(&gui_x1, &gui_y1, gui_x1, gui_y1);
+
+  *dx = gui_x1 - gui_x0;
+  *dy = gui_y1 - gui_y0;
+}
+
+/****************************************************************************
   Change the mapview origin, clip it, and update everything.
 ****************************************************************************/
 static void set_mapview_origin(int gui_x0, int gui_y0)
 {
   int xmin, xmax, ymin, ymax, xsize, ysize;
+  int start_x = mapview_canvas.gui_x0, start_y = mapview_canvas.gui_y0;
+  int diff_x, diff_y;
+  double timing_sec = 1.0, mytime;
+  static struct timer *anim_timer;
 
   /* First wrap/clip the position.  Wrapping is done in native positions
    * while clipping is done in scroll (native) positions. */
@@ -342,24 +445,36 @@
     gui_y0 = CLIP(ymin, gui_y0, ymax - ysize);
   }
 
+  if (mapview_canvas.gui_x0 == gui_x0 && mapview_canvas.gui_y0 == gui_y0) {
+    return;
+  }
+
+  gui_distance_vector(&diff_x, &diff_y, start_x, start_y, gui_x0, gui_y0);
+  anim_timer = renew_timer_start(anim_timer, TIMER_USER, TIMER_ACTIVE);
+
   /* Then update everything. */
-  if (mapview_canvas.gui_x0 != gui_x0 || mapview_canvas.gui_y0 != gui_y0) {
+  do {
     int map_center_x, map_center_y;
 
-    mapview_canvas.gui_x0 = gui_x0;
-    mapview_canvas.gui_y0 = gui_y0;
+    mytime = MIN(read_timer_seconds(anim_timer), timing_sec);
+
+    mapview_canvas.gui_x0 = start_x + diff_x * (mytime / timing_sec);
+    mapview_canvas.gui_y0 = start_y + diff_y * (mytime / timing_sec);
 
     get_center_tile_mapcanvas(&map_center_x, &map_center_y);
     center_tile_overviewcanvas(map_center_x, map_center_y);
     update_map_canvas_visible();
-    update_map_canvas_scrollbars();
     if (hover_state == HOVER_GOTO || hover_state == HOVER_PATROL) {
       create_line_at_mouse_pos();
     }
-  }
-  if (rectangle_active) {
-    update_rect_at_mouse_pos();
-  }
+    if (rectangle_active) {
+      update_rect_at_mouse_pos();
+    }
+    flush_dirty();
+    gui_flush();
+  } while (mytime < timing_sec);
+  
+  update_map_canvas_scrollbars();
 }
 
 /****************************************************************************

[Prev in Thread] Current Thread [Next in Thread]