mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-20 23:51:29 -07:00
Add a completion flash when you get down to a single peg.
[originally from svn r6061]
This commit is contained in:
50
pegs.c
50
pegs.c
@ -42,6 +42,8 @@ static char const *const pegs_titletypes[] = { TYPELIST(TITLE) };
|
|||||||
static char const *const pegs_lowertypes[] = { TYPELIST(LOWER) };
|
static char const *const pegs_lowertypes[] = { TYPELIST(LOWER) };
|
||||||
#define TYPECONFIG TYPELIST(CONFIG)
|
#define TYPECONFIG TYPELIST(CONFIG)
|
||||||
|
|
||||||
|
#define FLASH_FRAME 0.13F
|
||||||
|
|
||||||
struct game_params {
|
struct game_params {
|
||||||
int w, h;
|
int w, h;
|
||||||
int type;
|
int type;
|
||||||
@ -49,6 +51,7 @@ struct game_params {
|
|||||||
|
|
||||||
struct game_state {
|
struct game_state {
|
||||||
int w, h;
|
int w, h;
|
||||||
|
int completed;
|
||||||
unsigned char *grid;
|
unsigned char *grid;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -574,6 +577,7 @@ static game_state *new_game(midend_data *me, game_params *params, char *desc)
|
|||||||
|
|
||||||
state->w = w;
|
state->w = w;
|
||||||
state->h = h;
|
state->h = h;
|
||||||
|
state->completed = 0;
|
||||||
state->grid = snewn(w*h, unsigned char);
|
state->grid = snewn(w*h, unsigned char);
|
||||||
for (i = 0; i < w*h; i++)
|
for (i = 0; i < w*h; i++)
|
||||||
state->grid[i] = (desc[i] == 'P' ? GRID_PEG :
|
state->grid[i] = (desc[i] == 'P' ? GRID_PEG :
|
||||||
@ -589,6 +593,7 @@ static game_state *dup_game(game_state *state)
|
|||||||
|
|
||||||
ret->w = state->w;
|
ret->w = state->w;
|
||||||
ret->h = state->h;
|
ret->h = state->h;
|
||||||
|
ret->completed = state->completed;
|
||||||
ret->grid = snewn(w*h, unsigned char);
|
ret->grid = snewn(w*h, unsigned char);
|
||||||
memcpy(ret->grid, state->grid, w*h);
|
memcpy(ret->grid, state->grid, w*h);
|
||||||
|
|
||||||
@ -682,6 +687,7 @@ struct game_drawstate {
|
|||||||
int w, h;
|
int w, h;
|
||||||
unsigned char *grid;
|
unsigned char *grid;
|
||||||
int started;
|
int started;
|
||||||
|
int bgcolour;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
|
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
|
||||||
@ -789,6 +795,21 @@ static game_state *execute_move(game_state *state, char *move)
|
|||||||
ret->grid[my*w+mx] = GRID_HOLE;
|
ret->grid[my*w+mx] = GRID_HOLE;
|
||||||
ret->grid[ty*w+tx] = GRID_PEG;
|
ret->grid[ty*w+tx] = GRID_PEG;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Opinion varies on whether getting to a single peg counts as
|
||||||
|
* completing the game, or whether that peg has to be at a
|
||||||
|
* specific location (central in the classic cross game, for
|
||||||
|
* instance). For now we take the former, rather lax position.
|
||||||
|
*/
|
||||||
|
if (!ret->completed) {
|
||||||
|
int count = 0, i;
|
||||||
|
for (i = 0; i < w*h; i++)
|
||||||
|
if (ret->grid[i] == GRID_PEG)
|
||||||
|
count++;
|
||||||
|
if (count == 1)
|
||||||
|
ret->completed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -873,6 +894,7 @@ static game_drawstate *game_new_drawstate(game_state *state)
|
|||||||
memset(ds->grid, 255, w*h);
|
memset(ds->grid, 255, w*h);
|
||||||
|
|
||||||
ds->started = FALSE;
|
ds->started = FALSE;
|
||||||
|
ds->bgcolour = -1;
|
||||||
|
|
||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
@ -886,10 +908,10 @@ static void game_free_drawstate(game_drawstate *ds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void draw_tile(frontend *fe, game_drawstate *ds,
|
static void draw_tile(frontend *fe, game_drawstate *ds,
|
||||||
int x, int y, int v, int erasebg)
|
int x, int y, int v, int bgcolour)
|
||||||
{
|
{
|
||||||
if (erasebg) {
|
if (bgcolour >= 0) {
|
||||||
draw_rect(fe, x, y, TILESIZE, TILESIZE, COL_BACKGROUND);
|
draw_rect(fe, x, y, TILESIZE, TILESIZE, bgcolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v == GRID_HOLE) {
|
if (v == GRID_HOLE) {
|
||||||
@ -909,6 +931,13 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
|||||||
{
|
{
|
||||||
int w = state->w, h = state->h;
|
int w = state->w, h = state->h;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
int bgcolour;
|
||||||
|
|
||||||
|
if (flashtime > 0) {
|
||||||
|
int frame = (int)(flashtime / FLASH_FRAME);
|
||||||
|
bgcolour = (frame % 2 ? COL_LOWLIGHT : COL_HIGHLIGHT);
|
||||||
|
} else
|
||||||
|
bgcolour = COL_BACKGROUND;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Erase the sprite currently being dragged, if any.
|
* Erase the sprite currently being dragged, if any.
|
||||||
@ -1025,8 +1054,10 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
|||||||
*/
|
*/
|
||||||
if (ui->dragging && ui->sx == x && ui->sy == y && v == GRID_PEG)
|
if (ui->dragging && ui->sx == x && ui->sy == y && v == GRID_PEG)
|
||||||
v = GRID_HOLE;
|
v = GRID_HOLE;
|
||||||
if (v != ds->grid[y*w+x] && v != GRID_OBST) {
|
if (v != GRID_OBST &&
|
||||||
draw_tile(fe, ds, COORD(x), COORD(y), v, TRUE);
|
(bgcolour != ds->bgcolour || /* always redraw when flashing */
|
||||||
|
v != ds->grid[y*w+x])) {
|
||||||
|
draw_tile(fe, ds, COORD(x), COORD(y), v, bgcolour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,8 +1069,10 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
|||||||
ds->dragx = ui->dx - TILESIZE/2;
|
ds->dragx = ui->dx - TILESIZE/2;
|
||||||
ds->dragy = ui->dy - TILESIZE/2;
|
ds->dragy = ui->dy - TILESIZE/2;
|
||||||
blitter_save(fe, ds->drag_background, ds->dragx, ds->dragy);
|
blitter_save(fe, ds->drag_background, ds->dragx, ds->dragy);
|
||||||
draw_tile(fe, ds, ds->dragx, ds->dragy, GRID_PEG, FALSE);
|
draw_tile(fe, ds, ds->dragx, ds->dragy, GRID_PEG, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ds->bgcolour = bgcolour;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float game_anim_length(game_state *oldstate, game_state *newstate,
|
static float game_anim_length(game_state *oldstate, game_state *newstate,
|
||||||
@ -1051,7 +1084,10 @@ static float game_anim_length(game_state *oldstate, game_state *newstate,
|
|||||||
static float game_flash_length(game_state *oldstate, game_state *newstate,
|
static float game_flash_length(game_state *oldstate, game_state *newstate,
|
||||||
int dir, game_ui *ui)
|
int dir, game_ui *ui)
|
||||||
{
|
{
|
||||||
return 0.0F;
|
if (!oldstate->completed && newstate->completed)
|
||||||
|
return 2 * FLASH_FRAME;
|
||||||
|
else
|
||||||
|
return 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int game_wants_statusbar(void)
|
static int game_wants_statusbar(void)
|
||||||
|
Reference in New Issue
Block a user