ref: 425942c852f22d7d94f7643696522d32c0b02067
parent: 99d3c31e12ac5bb7c12d2b7a59c702cb671e9b62
author: Ben Harris <bjh21@bjh21.me.uk>
date: Tue Dec 27 12:26:42 EST 2022
Fancier completion flash for Tracks It now runs along the track from A to B, spending the first half of FLASH_TIME lighting all the segments and the second half extinguishing them.
--- a/tracks.c
+++ b/tracks.c
@@ -242,6 +242,7 @@
#define S_CLUE 8
#define S_MARK 16
+#define S_FLASH_SHIFT 8 /* Position of tile in solved track, 8 bits */
#define S_TRACK_SHIFT 16 /* U/D/L/R flags for edge track indicators */
#define S_NOTRACK_SHIFT 20 /* U/D/L/R flags for edge no-track indicators */
@@ -1820,6 +1821,29 @@
return -1;
}
+/*
+ * The completion flash moves along the track, so we want to label
+ * each tile with how far along the track it is. This is represented
+ * as an eight-bit field, which is more than enough when the
+ * completion flash is only 0.5 s long.
+ */
+static void set_flash_data(game_state *state)
+{
+ int ntrack = 0, x, y, n, d;
+ const int w = state->p.w;
+
+ for (x = 0; x < w; x++)
+ ntrack += state->numbers->numbers[x];
+ n = 0; x = 0; y = state->numbers->row_s; d = R;
+ do {
+ /* Don't bother clearing; this only runs at completion. */
+ state->sflags[y*w + x] |= (n++ * 255 / (ntrack - 1)) << S_FLASH_SHIFT;
+ d = F(d); /* Find the direction we just arrived from. */
+ d = S_E_DIRS(state, x, y, E_TRACK) & ~d; /* Other track from here. */
+ x += DX(d); y += DY(d); /* Move to the next tile. */
+ } while (INGRID(state, x, y));
+}
+
static bool check_completion(game_state *state, bool mark)
{
int w = state->p.w, h = state->p.h, x, y, i, target;
@@ -1961,8 +1985,10 @@
ret = false;
}
- if (mark)
+ if (mark) {
state->completed = ret;
+ if (ret) set_flash_data(state);
+ }
sfree(dsf);
return ret;
}
@@ -2829,7 +2855,7 @@
const game_state *state, int dir, const game_ui *ui,
float animtime, float flashtime)
{
- int i, x, y, flashing = 0, w = ds->w, h = ds->h;
+ int i, x, y, flashing, w = ds->w, h = ds->h;
bool force = false;
game_state *drag_state = NULL;
@@ -2855,11 +2881,6 @@
}
}
- if (flashtime > 0 &&
- (flashtime <= FLASH_TIME/3 ||
- flashtime >= FLASH_TIME*2/3))
- flashing = DS_FLASH;
-
if (ui->dragging)
drag_state = copy_and_apply_drag(state, ui);
@@ -2866,6 +2887,15 @@
for (x = 0; x < w; x++) {
for (y = 0; y < h; y++) {
unsigned int f, f_d;
+
+ flashing = 0;
+ if (flashtime > 0) {
+ float flashpos =
+ (state->sflags[y*w+x] >> S_FLASH_SHIFT & 0xff) / 255.0F;
+ if (flashtime > FLASH_TIME / 2 * flashpos &&
+ flashtime <= FLASH_TIME / 2 * (flashpos + 1.0F))
+ flashing = DS_FLASH;
+ }
f = s2d_flags(state, x, y, ui) | flashing;
f_d = drag_state ? s2d_flags(drag_state, x, y, ui) : f;