static int status = GAME_NONE; /* Outcome of the game */
static struct game_tilt tilt; /* Floor rotation */
-
-static float view_c[3]; /* Current view center */
-static float view_p[3]; /* Current view position */
-static float view_e[3][3]; /* Current view reference frame */
+static struct game_view view; /* Current view */
static int coins = 0; /* Collected coins */
static int goal_e = 0; /* Goal enabled flag */
case CMD_TILT_ANGLES:
if (!got_tilt_axes)
- game_tilt_axes(&tilt, view_e);
+ game_tilt_axes(&tilt, view.e);
tilt.rx = cmd->tiltangles.x;
tilt.rz = cmd->tiltangles.z;
break;
case CMD_VIEW_POSITION:
- v_cpy(view_p, cmd->viewpos.p);
+ v_cpy(view.p, cmd->viewpos.p);
break;
case CMD_VIEW_CENTER:
- v_cpy(view_c, cmd->viewcenter.c);
+ v_cpy(view.c, cmd->viewcenter.c);
break;
case CMD_VIEW_BASIS:
- v_cpy(view_e[0], cmd->viewbasis.e[0]);
- v_cpy(view_e[1], cmd->viewbasis.e[1]);
+ v_cpy(view.e[0], cmd->viewbasis.e[0]);
+ v_cpy(view.e[1], cmd->viewbasis.e[1]);
- v_crs(view_e[2], view_e[0], view_e[1]);
+ v_crs(view.e[2], view.e[0], view.e[1]);
break;
glRotatef(tilt.rx * 2, tilt.x[0], tilt.x[1], tilt.x[2]);
}
- glTranslatef(view_p[0], view_p[1] * d, view_p[2]);
+ glTranslatef(view.p[0], view.p[1] * d, view.p[2]);
if (config_get_d(CONFIG_BACKGROUND))
{
{
GLdouble r, c[3], pz[4], nz[4];
- /* Compute the plane giving the front of the ball, as seen from view_p. */
+ /* Compute the plane giving the front of the ball, as seen from view.p. */
c[0] = p[0];
c[1] = p[1] * d;
c[2] = p[2];
- pz[0] = view_p[0] - c[0];
- pz[1] = view_p[1] - c[1];
- pz[2] = view_p[2] - c[2];
+ pz[0] = view.p[0] - c[0];
+ pz[1] = view.p[1] - c[1];
+ pz[2] = view.p[2] - c[2];
r = sqrt(pz[0] * pz[0] + pz[1] * pz[1] + pz[2] * pz[2]);
pz[1] * c[1] +
pz[2] * c[2]);
- /* Find the plane giving the back of the ball, as seen from view_p. */
+ /* Find the plane giving the back of the ball, as seen from view.p. */
nz[0] = -pz[0];
nz[1] = -pz[1];
/* Compute direct and reflected view bases. */
- v[0] = +view_p[0];
- v[1] = -view_p[1];
- v[2] = +view_p[2];
+ v[0] = +view.p[0];
+ v[1] = -view.p[1];
+ v[2] = +view.p[2];
- m_view(T, view_c, view_p, view_e[1]);
- m_view(U, view_c, v, view_e[1]);
+ m_view(T, view.c, view.p, view.e[1]);
+ m_view(U, view.c, v, view.e[1]);
m_xps(M, T);
/* Apply the current view. */
- v_sub(v, view_c, view_p);
+ v_sub(v, view.c, view.p);
glTranslatef(0.f, 0.f, -v_len(v));
glMultMatrixf(M);
- glTranslatef(-view_c[0], -view_c[1], -view_c[2]);
+ glTranslatef(-view.c[0], -view.c[1], -view.c[2]);
if (reflective && config_get_d(CONFIG_REFLECTION))
{
void game_look(float phi, float theta)
{
- view_c[0] = view_p[0] + fsinf(V_RAD(theta)) * fcosf(V_RAD(phi));
- view_c[1] = view_p[1] + fsinf(V_RAD(phi));
- view_c[2] = view_p[2] - fcosf(V_RAD(theta)) * fcosf(V_RAD(phi));
+ view.c[0] = view.p[0] + fsinf(V_RAD(theta)) * fcosf(V_RAD(phi));
+ view.c[1] = view.p[1] + fsinf(V_RAD(phi));
+ view.c[2] = view.p[2] - fcosf(V_RAD(theta)) * fcosf(V_RAD(phi));
}
/*---------------------------------------------------------------------------*/
fade_d = d;
}
-/*---------------------------------------------------------------------------*/
-
-const struct s_file *game_client_file(void)
+void game_client_fly(float k)
{
- return &file;
+ game_view_fly(&view, &file, k);
}
/*---------------------------------------------------------------------------*/
void game_step_fade(float);
void game_fade(float);
+void game_client_fly(float);
+
/*---------------------------------------------------------------------------*/
-extern int game_compat_map;
-const struct s_file *game_client_file(void);
+extern int game_compat_map;
/*---------------------------------------------------------------------------*/
#include "game_common.h"
#include "vec3.h"
+#include "config.h"
+#include "solid.h"
+
+/*---------------------------------------------------------------------------*/
const char *status_to_str(int s)
{
}
/*---------------------------------------------------------------------------*/
+
+void game_view_init(struct game_view *view)
+{
+ view->dp = config_get_d(CONFIG_VIEW_DP) / 100.0f;
+ view->dc = config_get_d(CONFIG_VIEW_DC) / 100.0f;
+ view->dz = config_get_d(CONFIG_VIEW_DZ) / 100.0f;
+ view->a = 0.0f;
+
+ view->c[0] = 0.0f;
+ view->c[1] = view->dc;
+ view->c[2] = 0.0f;
+
+ view->p[0] = 0.0f;
+ view->p[1] = view->dp;
+ view->p[2] = view->dz;
+
+ view->e[0][0] = 1.0f;
+ view->e[0][1] = 0.0f;
+ view->e[0][2] = 0.0f;
+ view->e[1][0] = 0.0f;
+ view->e[1][1] = 1.0f;
+ view->e[1][2] = 0.0f;
+ view->e[2][0] = 0.0f;
+ view->e[2][1] = 0.0f;
+ view->e[2][2] = 1.0f;
+}
+
+void game_view_fly(struct game_view *view, const struct s_file *fp, float k)
+{
+ /* float x[3] = { 1.f, 0.f, 0.f }; */
+ float y[3] = { 0.f, 1.f, 0.f };
+ float z[3] = { 0.f, 0.f, 1.f };
+ float c0[3] = { 0.f, 0.f, 0.f };
+ float p0[3] = { 0.f, 0.f, 0.f };
+ float c1[3] = { 0.f, 0.f, 0.f };
+ float p1[3] = { 0.f, 0.f, 0.f };
+ float v[3];
+
+ game_view_init(view);
+
+ /* k = 0.0 view is at the ball. */
+
+ if (fp->uc > 0)
+ {
+ v_cpy(c0, fp->uv[0].p);
+ v_cpy(p0, fp->uv[0].p);
+ }
+
+ v_mad(p0, p0, y, view->dp);
+ v_mad(p0, p0, z, view->dz);
+ v_mad(c0, c0, y, view->dc);
+
+ /* k = +1.0 view is s_view 0 */
+
+ if (k >= 0 && fp->wc > 0)
+ {
+ v_cpy(p1, fp->wv[0].p);
+ v_cpy(c1, fp->wv[0].q);
+ }
+
+ /* k = -1.0 view is s_view 1 */
+
+ if (k <= 0 && fp->wc > 1)
+ {
+ v_cpy(p1, fp->wv[1].p);
+ v_cpy(c1, fp->wv[1].q);
+ }
+
+ /* Interpolate the views. */
+
+ v_sub(v, p1, p0);
+ v_mad(view->p, p0, v, k * k);
+
+ v_sub(v, c1, c0);
+ v_mad(view->c, c0, v, k * k);
+
+ /* Orthonormalize the view basis. */
+
+ v_sub(view->e[2], view->p, view->c);
+ v_crs(view->e[0], view->e[1], view->e[2]);
+ v_crs(view->e[2], view->e[0], view->e[1]);
+ v_nrm(view->e[0], view->e[0]);
+ v_nrm(view->e[2], view->e[2]);
+}
+
+/*---------------------------------------------------------------------------*/
#define GAME_COMMON_H
#include "lang.h"
+#include "solid.h"
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
+struct game_view
+{
+ float dc; /* Ideal view distance above ball */
+ float dp; /* Ideal view distance above ball */
+ float dz; /* Ideal view distance behind ball */
+
+ float c[3]; /* Current view center */
+ float p[3]; /* Current view position */
+ float e[3][3]; /* Current view reference frame */
+
+ float a; /* Ideal view rotation about Y axis */
+};
+
+void game_view_init(struct game_view *);
+void game_view_fly(struct game_view *, const struct s_file *, float);
+
+/*---------------------------------------------------------------------------*/
+
#endif
static int status = GAME_NONE; /* Outcome of the game */
static struct game_tilt tilt; /* Floor rotation */
+static struct game_view view; /* Current view */
-static float view_a; /* Ideal view rotation about Y axis */
-static float view_dc; /* Ideal view distance above ball */
-static float view_dp; /* Ideal view distance above ball */
-static float view_dz; /* Ideal view distance behind ball */
-
-static float view_c[3]; /* Current view center */
-static float view_v[3]; /* Current view vector */
-static float view_p[3]; /* Current view position */
-static float view_e[3][3]; /* Current view reference frame */
static float view_k;
static int coins = 0; /* Collected coins */
static void game_cmd_updview(void)
{
cmd.type = CMD_VIEW_POSITION;
- memcpy(cmd.viewpos.p, view_p, sizeof (float) * 3);
+ memcpy(cmd.viewpos.p, view.p, sizeof (float) * 3);
game_proxy_enq(&cmd);
cmd.type = CMD_VIEW_CENTER;
- memcpy(cmd.viewcenter.c, view_c, sizeof (float) * 3);
+ memcpy(cmd.viewcenter.c, view.c, sizeof (float) * 3);
game_proxy_enq(&cmd);
cmd.type = CMD_VIEW_BASIS;
- v_cpy(cmd.viewbasis.e[0], view_e[0]);
- v_cpy(cmd.viewbasis.e[1], view_e[1]);
+ v_cpy(cmd.viewbasis.e[0], view.e[0]);
+ v_cpy(cmd.viewbasis.e[1], view.e[1]);
game_proxy_enq(&cmd);
}
/*---------------------------------------------------------------------------*/
-static void view_init(void)
-{
- view_dp = (float) config_get_d(CONFIG_VIEW_DP) / 100.0f;
- view_dc = (float) config_get_d(CONFIG_VIEW_DC) / 100.0f;
- view_dz = (float) config_get_d(CONFIG_VIEW_DZ) / 100.0f;
- view_k = 1.0f;
- view_a = 0.0f;
-
- view_c[0] = 0.f;
- view_c[1] = view_dc;
- view_c[2] = 0.f;
-
- view_p[0] = 0.f;
- view_p[1] = view_dp;
- view_p[2] = view_dz;
-
- view_e[0][0] = 1.f;
- view_e[0][1] = 0.f;
- view_e[0][2] = 0.f;
- view_e[1][0] = 0.f;
- view_e[1][1] = 1.f;
- view_e[1][2] = 0.f;
- view_e[2][0] = 0.f;
- view_e[2][1] = 0.f;
- view_e[2][2] = 1.f;
-}
-
int game_server_init(const char *file_name, int t, int e)
{
struct
/* Initialize the view. */
- view_init();
+ game_view_init(&view);
+
+ view_k = 1.0f;
/* Initialize ball size tracking... */
static void game_update_view(float dt)
{
- float dc = view_dc * (jump_b ? 2.0f * fabsf(jump_dt - 0.5f) : 1.0f);
+ float dc = view.dc * (jump_b ? 2.0f * fabsf(jump_dt - 0.5f) : 1.0f);
float da = input_get_r() * dt * 90.0f;
float k;
float M[16], v[3], Y[3] = { 0.0f, 1.0f, 0.0f };
+ float view_v[3];
/* Center the view about the ball. */
- v_cpy(view_c, file.uv->p);
+ v_cpy(view.c, file.uv->p);
view_v[0] = -file.uv->v[0];
view_v[1] = 0.0f;
{
case VIEW_LAZY: /* Viewpoint chases the ball position. */
- v_sub(view_e[2], view_p, view_c);
+ v_sub(view.e[2], view.p, view.c);
break;
case VIEW_MANUAL: /* View vector is given by view angle. */
- view_e[2][0] = fsinf(V_RAD(view_a));
- view_e[2][1] = 0.0;
- view_e[2][2] = fcosf(V_RAD(view_a));
+ view.e[2][0] = fsinf(V_RAD(view.a));
+ view.e[2][1] = 0.0;
+ view.e[2][2] = fcosf(V_RAD(view.a));
break;
case VIEW_CHASE: /* View vector approaches the ball velocity vector. */
- v_sub(view_e[2], view_p, view_c);
- v_nrm(view_e[2], view_e[2]);
- v_mad(view_e[2], view_e[2], view_v, v_dot(view_v, view_v) * dt / 4);
+ v_sub(view.e[2], view.p, view.c);
+ v_nrm(view.e[2], view.e[2]);
+ v_mad(view.e[2], view.e[2], view_v, v_dot(view_v, view_v) * dt / 4);
break;
}
/* Apply manual rotation. */
m_rot(M, Y, V_RAD(da));
- m_vxfm(v, M, view_e[2]);
- v_cpy(view_e[2], v);
+ m_vxfm(v, M, view.e[2]);
+ v_cpy(view.e[2], v);
/* Orthonormalize the new view reference frame. */
- v_crs(view_e[0], view_e[1], view_e[2]);
- v_crs(view_e[2], view_e[0], view_e[1]);
- v_nrm(view_e[0], view_e[0]);
- v_nrm(view_e[2], view_e[2]);
+ v_crs(view.e[0], view.e[1], view.e[2]);
+ v_crs(view.e[2], view.e[0], view.e[1]);
+ v_nrm(view.e[0], view.e[0]);
+ v_nrm(view.e[2], view.e[2]);
/* Compute the new view position. */
- k = 1.0f + v_dot(view_e[2], view_v) / 10.0f;
+ k = 1.0f + v_dot(view.e[2], view_v) / 10.0f;
view_k = view_k + (k - view_k) * dt;
if (view_k < 0.5) view_k = 0.5;
- v_scl(v, view_e[1], view_dp * view_k);
- v_mad(v, v, view_e[2], view_dz * view_k);
- v_add(view_p, v, file.uv->p);
+ v_scl(v, view.e[1], view.dp * view_k);
+ v_mad(v, v, view.e[2], view.dz * view_k);
+ v_add(view.p, v, file.uv->p);
/* Compute the new view center. */
- v_cpy(view_c, file.uv->p);
- v_mad(view_c, view_c, view_e[1], dc);
+ v_cpy(view.c, file.uv->p);
+ v_mad(view.c, view.c, view.e[1], dc);
/* Note the current view angle. */
- view_a = V_DEG(fatan2f(view_e[2][0], view_e[2][2]));
+ view.a = V_DEG(fatan2f(view.e[2][0], view.e[2][2]));
game_cmd_updview();
}
jump_dt = 0.f;
v_sub(jump_w, jump_p, fp->uv->p);
- v_add(jump_w, view_p, jump_w);
+ v_add(jump_w, view.p, jump_w);
audio_play(AUD_JUMP, 1.f);
tilt.rx += (input_get_x() - tilt.rx) * dt / RESPONSE;
tilt.rz += (input_get_z() - tilt.rz) * dt / RESPONSE;
- game_tilt_axes(&tilt, view_e);
+ game_tilt_axes(&tilt, view.e);
game_cmd_tiltaxes();
game_cmd_tiltangles();
if (0.5f < jump_dt)
{
v_cpy(fp->uv->p, jump_p);
- v_cpy(view_p, jump_w);
+ v_cpy(view.p, jump_w);
}
if (1.0f < jump_dt)
jump_b = 0;
input_set_r(r);
}
-void game_set_fly(float k, const struct s_file *fp)
+void game_server_fly(float k)
{
- float x[3] = { 1.f, 0.f, 0.f };
- float y[3] = { 0.f, 1.f, 0.f };
- float z[3] = { 0.f, 0.f, 1.f };
- float c0[3] = { 0.f, 0.f, 0.f };
- float p0[3] = { 0.f, 0.f, 0.f };
- float c1[3] = { 0.f, 0.f, 0.f };
- float p1[3] = { 0.f, 0.f, 0.f };
- float v[3];
-
- if (!fp) fp = &file;
-
- view_init();
-
- z[0] = fsinf(V_RAD(view_a));
- z[2] = fcosf(V_RAD(view_a));
-
- v_cpy(view_e[0], x);
- v_cpy(view_e[1], y);
- v_cpy(view_e[2], z);
-
- /* k = 0.0 view is at the ball. */
-
- if (fp->uc > 0)
- {
- v_cpy(c0, fp->uv[0].p);
- v_cpy(p0, fp->uv[0].p);
- }
-
- v_mad(p0, p0, y, view_dp);
- v_mad(p0, p0, z, view_dz);
- v_mad(c0, c0, y, view_dc);
-
- /* k = +1.0 view is s_view 0 */
-
- if (k >= 0 && fp->wc > 0)
- {
- v_cpy(p1, fp->wv[0].p);
- v_cpy(c1, fp->wv[0].q);
- }
-
- /* k = -1.0 view is s_view 1 */
-
- if (k <= 0 && fp->wc > 1)
- {
- v_cpy(p1, fp->wv[1].p);
- v_cpy(c1, fp->wv[1].q);
- }
-
- /* Interpolate the views. */
-
- v_sub(v, p1, p0);
- v_mad(view_p, p0, v, k * k);
-
- v_sub(v, c1, c0);
- v_mad(view_c, c0, v, k * k);
-
- /* Orthonormalize the view basis. */
-
- v_sub(view_e[2], view_p, view_c);
- v_crs(view_e[0], view_e[1], view_e[2]);
- v_crs(view_e[2], view_e[0], view_e[1]);
- v_nrm(view_e[0], view_e[0]);
- v_nrm(view_e[2], view_e[2]);
-
+ game_view_fly(&view, &file, k);
game_cmd_updview();
}
void game_set_z (int);
void game_set_cam(int);
void game_set_rot(float);
-void game_set_fly(float, const struct s_file *);
+
+void game_server_fly(float);
/*---------------------------------------------------------------------------*/
if (game_client_init(level_v[i].file))
{
union cmd cmd;
-
cmd.type = CMD_GOAL_OPEN;
game_proxy_enq(&cmd);
+ game_client_step(NULL);
/* Render the level and grab the screen. */
video_clear();
- game_set_fly(1.f, game_client_file());
+ game_client_fly(1.0f);
game_kill_fade();
- game_client_step(NULL);
game_draw(1, 0);
SDL_GL_SwapBuffers();
demo_replay_init("gui/ball.nbr", &g, NULL, NULL, NULL, NULL);
audio_music_fade_to(0.0f, "bgm/inter.ogg");
- game_set_fly(0, game_client_file());
- game_client_step(NULL);
+ game_client_fly(0);
game_kill_fade();
back_init("back/gui.png", config_get_d(CONFIG_GEOMETRY));
}
/*
- * Post-1.5.1 replays include view data in the first update, these
- * two lines are currently left in for compatibility with older
- * replays.
+ * Post-1.5.1 replays include view data in the first update, this
+ * line is currently left in for compatibility with older replays.
*/
-
- game_set_fly(0.f, game_client_file());
- game_client_step(NULL);
+ game_client_fly(0.0f);
if (check_compat && !game_compat_map)
{
static int help_demo_enter(void)
{
- game_set_fly(0.f, game_client_file());
- game_client_step(NULL);
+ game_client_fly(0.0f);
return 0;
}
gui_layout(id, 0, 0);
}
- game_set_fly(1.f, NULL);
+ game_server_fly(1.0f);
game_client_step(NULL);
return id;
{
float t = time_state();
- game_set_fly(1.0f - 0.5f * t, NULL);
- game_client_step(NULL);
+ game_client_fly(1.0f - 0.5f * t);
if (dt > 0.0f && t > 1.0f)
goto_state(&st_play_set);
{
float t = time_state();
- game_set_fly(0.5f - 0.5f * t, NULL);
- game_client_step(NULL);
+ game_client_fly(0.5f - 0.5f * t);
if (dt > 0.0f && t > 1.0f)
goto_state(&st_play_loop);
audio_play(AUD_GO, 1.f);
- game_set_fly(0.f, NULL);
+ game_server_fly(0.0f);
/* End first update. */
cmd.type = CMD_END_OF_UPDATE;
game_proxy_enq(&cmd);
-
- /* Sync client. */
-
game_client_step(demo_file());
view_rotate = 0;
if (real_time <= 20.0f)
{
- game_set_fly(fcosf(V_PI * real_time / 20.0f),
- game_client_file());
- game_client_step(NULL);
+ game_client_fly(fcosf(V_PI * real_time / 20.0f));
}
else
{
if ((demo = pick_demo(items)))
{
demo_replay_init(demo, NULL, NULL, NULL, NULL, NULL);
- game_set_fly(0.0f, game_client_file());
- game_client_step(NULL);
+ game_client_fly(0.0f);
real_time = 0.0f;
mode = 2;
}