static int status = GAME_NONE; /* Outcome of the game */
static int coins = 0; /* Collected coins */
-static int ups; /* Updates per second */
-static int first_update; /* First update flag */
-static int curr_ball; /* Current ball index */
+static struct cmd_state cs; /* Command state */
struct
{
int x, y;
} version; /* Current map version */
-/*
- * Neverball <= 1.5.1 does not send explicit tilt axes, rotation
- * happens directly around view vectors. So for compatibility if at
- * the time of receiving tilt angles we have not yet received the tilt
- * axes, we use the view vectors.
- */
-
-static int got_tilt_axes;
-
-static int next_update;
-
/*---------------------------------------------------------------------------*/
static void game_run_cmd(const union cmd *cmd)
float v[3];
float dt;
- if (next_update)
+ if (cs.next_update)
{
game_lerp_copy(&gl);
- next_update = 0;
+ cs.next_update = 0;
}
switch (cmd->type)
{
case CMD_END_OF_UPDATE:
- got_tilt_axes = 0;
+ cs.got_tilt_axes = 0;
+ cs.next_update = 1;
- next_update = 1;
-
- if (first_update)
+ if (cs.first_update)
{
game_lerp_copy(&gl);
/* Hack to sync state before the next update. */
game_lerp_apply(&gl, &gd);
- first_update = 0;
+ cs.first_update = 0;
break;
}
/* Step particle, goal and jump effects. */
- if (ups > 0)
+ if (cs.ups > 0)
{
- dt = 1.0f / (float) ups;
+ dt = 1.0f / cs.ups;
if (gd.goal_e && gl.goal_k[CURR] < 1.0f)
gl.goal_k[CURR] += dt;
case CMD_MAKE_BALL:
/* Allocate a new ball and mark it as the current ball. */
- if (sol_lerp_cmd(&gl.lerp, cmd))
- curr_ball = gl.lerp.uc - 1;
+ if (sol_lerp_cmd(&gl.lerp, &cs, cmd))
+ cs.curr_ball = gl.lerp.uc - 1;
break;
break;
case CMD_TILT_ANGLES:
- if (!got_tilt_axes)
+ if (!cs.got_tilt_axes)
+ {
+ /*
+ * Neverball <= 1.5.1 does not send explicit tilt
+ * axes, rotation happens directly around view
+ * vectors. So for compatibility if at the time of
+ * receiving tilt angles we have not yet received the
+ * tilt axes, we use the view vectors.
+ */
+
game_tilt_axes(tilt, view->e);
+ }
tilt->rx = cmd->tiltangles.x;
tilt->rz = cmd->tiltangles.z;
break;
case CMD_BODY_PATH:
- sol_lerp_cmd(&gl.lerp, cmd);
+ sol_lerp_cmd(&gl.lerp, &cs, cmd);
break;
case CMD_BODY_TIME:
- sol_lerp_cmd(&gl.lerp, cmd);
+ sol_lerp_cmd(&gl.lerp, &cs, cmd);
break;
case CMD_GOAL_OPEN:
if (!gd.goal_e)
{
gd.goal_e = 1;
- gl.goal_k[CURR] = first_update ? 1.0f : 0.0f;
+ gl.goal_k[CURR] = cs.first_update ? 1.0f : 0.0f;
}
break;
break;
case CMD_UPDATES_PER_SECOND:
- ups = cmd->ups.n;
+ cs.ups = cmd->ups.n;
break;
case CMD_BALL_RADIUS:
- sol_lerp_cmd(&gl.lerp, cmd);
+ sol_lerp_cmd(&gl.lerp, &cs, cmd);
break;
case CMD_CLEAR_ITEMS:
break;
case CMD_CLEAR_BALLS:
- sol_lerp_cmd(&gl.lerp, cmd);
+ sol_lerp_cmd(&gl.lerp, &cs, cmd);
break;
case CMD_BALL_POSITION:
- sol_lerp_cmd(&gl.lerp, cmd);
+ sol_lerp_cmd(&gl.lerp, &cs, cmd);
break;
case CMD_BALL_BASIS:
- sol_lerp_cmd(&gl.lerp, cmd);
+ sol_lerp_cmd(&gl.lerp, &cs, cmd);
break;
case CMD_BALL_PEND_BASIS:
- sol_lerp_cmd(&gl.lerp, cmd);
+ sol_lerp_cmd(&gl.lerp, &cs, cmd);
break;
case CMD_VIEW_POSITION:
break;
case CMD_CURRENT_BALL:
- sol_lerp_cmd(&gl.lerp, cmd);
- curr_ball = cmd->currball.ui;
+ cs.curr_ball = cmd->currball.ui;
break;
case CMD_PATH_FLAG:
break;
case CMD_STEP_SIMULATION:
- sol_lerp_cmd(&gl.lerp, cmd);
+ sol_lerp_cmd(&gl.lerp, &cs, cmd);
break;
case CMD_MAP:
break;
case CMD_TILT_AXES:
- got_tilt_axes = 1;
+ cs.got_tilt_axes = 1;
v_cpy(tilt->x, cmd->tiltaxes.x);
v_cpy(tilt->z, cmd->tiltaxes.z);
break;
/* Initialize command state. */
- ups = 0;
- first_update = 1;
+ cmd_state_init(&cs);
/* Initialize background. */
#define CURR 0
#define PREV 1
-static int curr_ball;
-
-int sol_lerp_cmd(struct s_lerp *fp, const union cmd *cmd)
+int sol_lerp_cmd(struct s_lerp *fp, struct cmd_state *cs, const union cmd *cmd)
{
struct l_ball (*uv)[2];
struct l_ball *up;
fp->vary->uv = up;
fp->vary->uc = fp->uc;
- curr_ball = fp->uc - 1;
+ cs->curr_ball = fp->uc - 1;
rc = 1;
}
}
break;
case CMD_BALL_RADIUS:
- fp->uv[curr_ball][CURR].r = cmd->ballradius.r;
+ fp->uv[cs->curr_ball][CURR].r = cmd->ballradius.r;
break;
case CMD_CLEAR_BALLS:
break;
case CMD_BALL_POSITION:
- up = &fp->uv[curr_ball][CURR];
+ up = &fp->uv[cs->curr_ball][CURR];
v_cpy(up->p, cmd->ballpos.p);
break;
case CMD_BALL_BASIS:
- up = &fp->uv[curr_ball][CURR];
+ up = &fp->uv[cs->curr_ball][CURR];
v_cpy(up->e[0], cmd->ballbasis.e[0]);
v_cpy(up->e[1], cmd->ballbasis.e[1]);
v_crs(up->e[2], up->e[0], up->e[1]);
break;
case CMD_BALL_PEND_BASIS:
- up = &fp->uv[curr_ball][CURR];
+ up = &fp->uv[cs->curr_ball][CURR];
v_cpy(up->E[0], cmd->ballpendbasis.E[0]);
v_cpy(up->E[1], cmd->ballpendbasis.E[1]);
v_crs(up->E[2], up->E[0], up->E[1]);
break;
- case CMD_CURRENT_BALL:
- curr_ball = cmd->currball.ui;
- break;
-
case CMD_STEP_SIMULATION:
/*
* Simulate body motion.