[Freeciv-Dev] (PR#8210) WISHLIST: a sliding mapview
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<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();
}
/****************************************************************************
|
|