chiark / gitweb /
Add a new game concept called a `flash'. This is a graphical effect
authorSimon Tatham <anakin@pobox.com>
Wed, 28 Apr 2004 18:43:50 +0000 (18:43 +0000)
committerSimon Tatham <anakin@pobox.com>
Wed, 28 Apr 2004 18:43:50 +0000 (18:43 +0000)
taking non-zero time, which is triggered by the making of a move and
is _not_ hurried to its conclusion by the start of the next move (so
the game redraw function is expected to be able to draw it in
parallel with continuing moves). The only thing that prematurely
terminates a flash is the start of a fresh flash. In particular,
this concept is used to display the completion flash in Net, because
at least _my_ playing instincts make me lock every piece I've
unambiguously placed, and hence the last turn move is instantly
followed by a lock move which was previously suppressing the
completion flash.

[originally from svn r4168]

cube.c
midend.c
net.c
puzzles.h

diff --git a/cube.c b/cube.c
index e9c6e9aea2b8ee3341d7b561bcaaed271e6c9495..1bc08f62ffec7f19389761a95778ecdd15c31bdf 100644 (file)
--- a/cube.c
+++ b/cube.c
@@ -1206,7 +1206,7 @@ void game_free_drawstate(game_drawstate *ds)
 }
 
 void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
-                 game_state *state, float animtime)
+                 game_state *state, float animtime, float flashtime)
 {
     int i, j;
     struct bbox bb = find_bbox(&state->params);
@@ -1355,3 +1355,8 @@ float game_anim_length(game_state *oldstate, game_state *newstate)
 {
     return ROLLTIME;
 }
+
+float game_flash_length(game_state *oldstate, game_state *newstate)
+{
+    return 0.0F;
+}
index cafc8ea6fa14bcdcce337efea2c21b8578921ab6..3b1a0e45ab03ecc6273d7b3328f2b325ae273060 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -24,6 +24,7 @@ struct midend_data {
     game_drawstate *drawstate;
     game_state *oldstate;
     float anim_time, anim_pos;
+    float flash_time, flash_pos;
 };
 
 #define ensure(me) do { \
@@ -47,6 +48,8 @@ midend_data *midend_new(frontend *frontend)
     me->presets = NULL;
     me->preset_names = NULL;
     me->npresets = me->presetsize = 0;
+    me->anim_time = me->anim_pos = 0.0F;
+    me->flash_time = me->flash_pos = 0.0F;
 
     return me;
 }
@@ -117,17 +120,38 @@ static int midend_redo(midend_data *me)
         return 0;
 }
 
+static void midend_finish_move(midend_data *me)
+{
+    float flashtime;
+
+    if (me->oldstate || me->statepos > 1) {
+       flashtime = game_flash_length(me->oldstate ? me->oldstate :
+                                     me->states[me->statepos-2],
+                                     me->states[me->statepos-1]);
+       if (flashtime > 0) {
+           me->flash_pos = 0.0F;
+           me->flash_time = flashtime;
+       }
+    }
+
+    if (me->oldstate)
+       free_game(me->oldstate);
+    me->oldstate = NULL;
+    me->anim_pos = me->anim_time = 0;
+
+    if (me->flash_time == 0 && me->anim_time == 0)
+       deactivate_timer(me->frontend);
+    else
+       activate_timer(me->frontend);
+}
+
 int midend_process_key(midend_data *me, int x, int y, int button)
 {
     game_state *oldstate = dup_game(me->states[me->statepos - 1]);
     float anim_time;
 
     if (me->oldstate || me->anim_time) {
-        if (me->oldstate)
-            free_game(me->oldstate);
-        me->oldstate = NULL;
-        me->anim_pos = me->anim_time = 0;
-        deactivate_timer(me->frontend);
+       midend_finish_move(me);
         midend_redraw(me);
     }
 
@@ -169,13 +193,12 @@ int midend_process_key(midend_data *me, int x, int y, int button)
      */
     anim_time = game_anim_length(oldstate, me->states[me->statepos-1]);
 
+    me->oldstate = oldstate;
     if (anim_time > 0) {
-        me->oldstate = oldstate;
         me->anim_time = anim_time;
     } else {
-        free_game(oldstate);
-        me->oldstate = NULL;
         me->anim_time = 0.0;
+       midend_finish_move(me);
     }
     me->anim_pos = 0.0;
 
@@ -193,10 +216,11 @@ void midend_redraw(midend_data *me)
         if (me->oldstate && me->anim_time > 0 &&
             me->anim_pos < me->anim_time) {
             game_redraw(me->frontend, me->drawstate, me->oldstate,
-                        me->states[me->statepos-1], me->anim_pos);
+                        me->states[me->statepos-1], me->anim_pos,
+                       me->flash_pos);
         } else {
             game_redraw(me->frontend, me->drawstate, NULL,
-                        me->states[me->statepos-1], 0.0);
+                        me->states[me->statepos-1], 0.0, me->flash_pos);
         }
         end_draw(me->frontend);
     }
@@ -207,12 +231,15 @@ void midend_timer(midend_data *me, float tplus)
     me->anim_pos += tplus;
     if (me->anim_pos >= me->anim_time ||
         me->anim_time == 0 || !me->oldstate) {
-        if (me->oldstate)
-            free_game(me->oldstate);
-        me->oldstate = NULL;
-        me->anim_pos = me->anim_time = 0;
-        deactivate_timer(me->frontend);
+       if (me->anim_time > 0)
+           midend_finish_move(me);
+    }
+    me->flash_pos += tplus;
+    if (me->flash_pos >= me->flash_time || me->flash_time == 0) {
+       me->flash_pos = me->flash_time = 0;
     }
+    if (me->flash_time == 0 && me->anim_time == 0)
+       deactivate_timer(me->frontend);
     midend_redraw(me);
 }
 
diff --git a/net.c b/net.c
index 001eaaebd2371d3a24451b9feacb480856cdd724..268fbcac4638a2c808195e989418760e78f85d58 100644 (file)
--- a/net.c
+++ b/net.c
@@ -1060,7 +1060,7 @@ static void draw_tile(frontend *fe, game_state *state, int x, int y, int tile,
 }
 
 void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
-                 game_state *state, float t)
+                 game_state *state, float t, float ft)
 {
     int x, y, tx, ty, frame;
     unsigned char *active;
@@ -1118,7 +1118,6 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     }
 
     tx = ty = -1;
-    frame = -1;
     if (oldstate && (t < ROTATE_TIME)) {
         /*
          * We're animating a tile rotation. Find the turning tile,
@@ -1140,12 +1139,15 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                 angle = state->last_rotate_dir * -90.0F * (t / ROTATE_TIME);
             state = oldstate;
         }
-    } else if (t > ROTATE_TIME) {
+    }
+    
+    frame = -1;
+    if (ft > 0) {
         /*
          * We're animating a completion flash. Find which frame
          * we're at.
          */
-        frame = (int)((t - ROTATE_TIME) / FLASH_FRAME);
+        frame = (int)(ft / FLASH_FRAME);
     }
 
     /*
@@ -1192,7 +1194,6 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
 
 float game_anim_length(game_state *oldstate, game_state *newstate)
 {
-    float ret = 0.0F;
     int x, y;
 
     /*
@@ -1202,14 +1203,17 @@ float game_anim_length(game_state *oldstate, game_state *newstate)
     for (x = 0; x < oldstate->width; x++)
         for (y = 0; y < oldstate->height; y++)
             if ((tile(oldstate, x, y) ^ tile(newstate, x, y)) & 0xF) {
-                ret = ROTATE_TIME;
-                goto break_label;      /* leave both loops at once */
+                return ROTATE_TIME;
             }
-    break_label:
 
+    return 0.0F;
+}
+
+float game_flash_length(game_state *oldstate, game_state *newstate)
+{
     /*
-     * Also, if the game has just been completed, allow time for a
-     * completion flash.
+     * If the game has just been completed, we display a completion
+     * flash.
      */
     if (!oldstate->completed && newstate->completed) {
         int size;
@@ -1222,8 +1226,8 @@ float game_anim_length(game_state *oldstate, game_state *newstate)
             size = newstate->width - newstate->cx;
         if (size < newstate->height - newstate->cy)
             size = newstate->height - newstate->cy;
-        ret += FLASH_FRAME * (size+4);
+        return FLASH_FRAME * (size+4);
     }
 
-    return ret;
+    return 0.0F;
 }
index ae14848971a37a706f1699f430e228d21dbb39a6..5b756970a5478a0580d0219a657faf0008328d7a 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -108,7 +108,8 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours);
 game_drawstate *game_new_drawstate(game_state *state);
 void game_free_drawstate(game_drawstate *ds);
 void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
-                 game_state *newstate, float t);
+                 game_state *newstate, float anim_time, float flash_time);
 float game_anim_length(game_state *oldstate, game_state *newstate);
+float game_flash_length(game_state *oldstate, game_state *newstate);
 
 #endif /* PUZZLES_PUZZLES_H */