Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2005:
[Freeciv-Dev] (PR#12583) more accurate mapview sliding
Home

[Freeciv-Dev] (PR#12583) more accurate mapview sliding

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12583) more accurate mapview sliding
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 21 Mar 2005 19:36:50 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12583 >

The "animation" of mapview sliding follows a simple algorithm.  The 
position of the window is found by

   pos = origin + vector * (current_time) / (total_time)

where 'pos' is the mapview origin to be used, 'origin', is the original 
mapview origin, and 'vector' is the vector of sliding (the calculation 
is obviously done for both X and Y).

The problem is this calculation must be done before the drawing is done, 
but it *should* use the time from when the drawing completes.  On linux 
this typically means the first frame has a much smaller jump than the 
successive frames.  On windows (where the timer is only accurate to 
10ms) it means the first frame has no movement - meaning no redrawing is 
done, and (in one test) 115 frames were run through in quick succession 
without the origin ever moving (after which 3 "real" frames were run to 
complete the drawing; again the first frame would have a *much* smaller 
jump increment than the others).

The problem is most noticable when the FPS is low.  With 3 frames in a 
slide, it's quite noticable if the first one is "almost" standing still 
and the next two move large distances.

This patch improves the behavior.  Of course we don't know how long the 
drawing is going to take before we do it (draw time is inconsistent) but 
we can approximate based on previous draw times to get a much improved 
effect.

-jason

Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.218
diff -u -r1.218 mapview_common.c
--- client/mapview_common.c     21 Mar 2005 16:37:52 -0000      1.218
+++ client/mapview_common.c     22 Mar 2005 03:34:54 -0000
@@ -588,28 +588,58 @@
   if (can_slide && smooth_center_slide_msec > 0) {
     int start_x = mapview.gui_x0, start_y = mapview.gui_y0;
     int diff_x, diff_y;
-    double timing_sec = (double)smooth_center_slide_msec / 1000.0, mytime;
+    double timing_sec = (double)smooth_center_slide_msec / 1000.0, currtime;
     static struct timer *anim_timer;
     int frames = 0;
 
+    /* We track the average FPS, which is used to predict how long the
+     * next draw will take.  We start with a 100 FPS estimate - this
+     * value will quickly become irrelevant as the correct value is
+     * calculated, but it's needed to give an estimate of the FPS for
+     * the first draw.
+     *
+     * Note that the initial value shouldn't be larger than the sliding
+     * time, or we'll jump straight to the last frame.  The FPS should
+     * therefore be a "high" estimate. */
+    static double total_frames = 0.01;
+    static double total_time = 0.0001;
+
     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);
 
     unqueue_mapview_updates(TRUE);
 
     do {
-      mytime = MIN(read_timer_seconds(anim_timer), timing_sec);
+      double mytime;
 
+      /* Get the current time, and add on the average 1/FPS, which is the
+       * expected time this frame will take.  This is done so that the
+       * frame's position is calculated from the expected time when the
+       * frame will complete, rather than the time when the frame drawing
+       * is started. */
+      currtime = read_timer_seconds(anim_timer);
+      currtime += total_time / total_frames;
+
+      mytime = MIN(currtime, timing_sec);
       base_set_mapview_origin(start_x + diff_x * (mytime / timing_sec),
                              start_y + diff_y * (mytime / timing_sec));
       flush_dirty();
       gui_flush();
       frames++;
-    } while (mytime < timing_sec);
+    } while (currtime < timing_sec);
 
-    mytime = read_timer_seconds(anim_timer);
-    freelog(LOG_DEBUG, "Got %d frames in %f seconds: %f FPS.",
-           frames, mytime, (double)frames / mytime);
+    currtime = read_timer_seconds(anim_timer);
+    total_frames += frames;
+    total_time += currtime;
+    freelog(LOG_DEBUG, "Got %d frames in %f seconds: %f FPS (avg %f).",
+           frames, currtime, (double)frames / currtime,
+           total_frames / total_time);
+
+    /* A very small decay factor to make things more accurate when something
+     * changes (mapview size, tileset change, etc.).  This gives a
+     * half-life of 68 slides. */
+    total_frames *= 0.99;
+    total_time *= 0.99;
   } else {
     base_set_mapview_origin(gui_x0, gui_y0);
   }

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#12583) more accurate mapview sliding, Jason Short <=