static float jump_p[3]; /* Jump destination */
static float fade_k = 0.0; /* Fade in/out level */
static float fade_d = 0.0; /* Fade in/out direction */
-static int drawball = 1; /* Should the ball be drawn? */
-static int ball_b = 0; /* Is the ball a bonus ball? */
static int grow = 0; /* Should the ball be changing size? */
static float grow_orig = 0; /* the original ball size */
static float grow_goal = 0; /* how big or small to get! */
-const float grow_time = 0.5f; /* sec for the ball to get to size. */
static float grow_t = 0.0; /* timer for the ball to grow... */
static float grow_strt = 0; /* starting value for growth */
+static int got_orig = 0; /* Do we know original ball size? */
-
+#define GROW_TIME 0.5f /* sec for the ball to get to size. */
+#define GROW_BIG 1.5f /* large factor */
+#define GROW_SMALL 0.5f /* small factor */
/*---------------------------------------------------------------------------*/
-static void grow_set(const struct s_file *fp, int size)
+static void grow_set(const struct s_file *fp, int type)
{
- static int got_orig = 0;
- if (!got_orig)
+ if (!got_orig)
{
grow_orig = fp->uv->r;
grow_goal = grow_orig;
got_orig = 1;
}
- if (size == 50)
+ switch (type)
{
- if (grow_goal == grow_orig * 0.5f) return; //already small!
- else if (grow_goal == grow_orig * 1.5f) // big, let's set it to normal.
+ case ITEM_SHRINK:
+ audio_play(AUD_SHRINK, 1.f);
+
+ if (grow_goal == grow_orig * GROW_SMALL)
+ return;
+ else if (grow_goal == grow_orig * GROW_BIG)
{
- grow = 1;
grow_goal = grow_orig;
+ grow = 1;
}
- else //must be normal sized.
+ else
{
- grow_goal = grow_orig * 0.5f;
+ grow_goal = grow_orig * GROW_SMALL;
grow = 1;
- }
- }// done with 50% size coin
- if (size == 150)
- {
- if (grow_goal == grow_orig * 1.5f) return; //already big!
- else if (grow_goal == grow_orig * 0.5f) // small, let's set it to normal.
+ }
+
+ break;
+
+ case ITEM_GROW:
+ audio_play(AUD_GROW, 1.f);
+
+ if (grow_goal == grow_orig * GROW_BIG)
+ return;
+ else if (grow_goal == grow_orig * GROW_SMALL)
{
grow = 1;
grow_goal = grow_orig;
}
- else //must be normal sized.
+ else
{
- grow_goal = grow_orig * 1.5f;
+ grow_goal = grow_orig * GROW_BIG;
grow = 1;
}
- }// done with 150% size coin
+
+ break;
+
+ default:
+ break;
+ }
if (grow)
{
grow_t = 0.0;
grow_strt = fp->uv->r;
- }
+ }
}
static void grow_ball(const struct s_file *fp, float dt)
-{
+{
float dr;
-
- //calculate new size based on how long since you touched the coin...
+
+ /* Calculate new size based on how long since you touched the coin... */
+
grow_t += dt;
- if (grow_t >= grow_time)
+
+ if (grow_t >= GROW_TIME)
{
grow = 0;
- grow_t = grow_time;
- }
+ grow_t = GROW_TIME;
+ }
- dr = grow_strt + ((grow_goal-grow_strt) * (1.0f / (grow_time / grow_t)));
+ dr = grow_strt + ((grow_goal-grow_strt) * (1.0f / (GROW_TIME / grow_t)));
- fp->uv->p[1] += (dr - fp->uv->r); //No sinking through the floor! keeps ball's bottom constant.
+ /* No sinking through the floor! Keeps ball's bottom constant. */
+ fp->uv->p[1] += (dr - fp->uv->r);
fp->uv->r = dr;
}
static void view_init(void)
{
- /* Get the initial orientation angle */
- if (file.uc > 0)
- view_a = file.uv->a - 90.f; /* angle is in the sol */
- else
- view_a = 0.f; /* default is north :) */
-
+ view_a = 0.f;
view_ry = 0.f;
view_fov = (float) config_get_d(CONFIG_VIEW_FOV);
if (game_state)
game_free();
- if (!sol_load_gl(&file, level->file, config_get_d(CONFIG_TEXTURES),
+ if (!sol_load_gl(&file, config_data(level->file),
+ config_get_d(CONFIG_TEXTURES),
config_get_d(CONFIG_SHADOW)))
return (game_state = 0);
game_rx = 0.f;
game_rz = 0.f;
- drawball = 1;
-
/* Initialize jump and goal states. */
jump_e = 1;
goal_c = g;
goal_k = (g == 0) ? 1.0f : 0.0f;
- ball_b = level->is_bonus;
-
/* Initialise the level, background, particles, fade, and view. */
fade_k = 1.0f;
sol_load_gl(&back, config_data(level->back),
config_get_d(CONFIG_TEXTURES), 0);
+ /* Initialize ball size tracking... */
+
+ got_orig = 0;
+ grow = 0;
+
return game_state;
}
fp->uv[0].r);
glColor4fv(c);
-
- ball_draw(ball_b);
+ ball_draw();
}
glPopMatrix();
}
-static void game_draw_coins(const struct s_file *fp)
+static void game_draw_items(const struct s_file *fp)
{
float r = 360.f * SDL_GetTicks() / 1000.f;
- int ci;
+ int hi;
- coin_push();
- coin_push_text(0); //regular coins
+ /* FIXME: Draw items of different types in one pass? */
+
+ item_push(ITEM_COIN);
{
- for (ci = 0; ci < fp->cc; ci++)
-
- if (fp->cv[ci].n > 0 && fp->cv[ci].n < 50)
+ for (hi = 0; hi < fp->hc; hi++)
+
+ if (fp->hv[hi].t == ITEM_COIN && fp->hv[hi].n > 0)
{
glPushMatrix();
{
- glTranslatef(fp->cv[ci].p[0],
- fp->cv[ci].p[1],
- fp->cv[ci].p[2]);
+ glTranslatef(fp->hv[hi].p[0],
+ fp->hv[hi].p[1],
+ fp->hv[hi].p[2]);
glRotatef(r, 0.0f, 1.0f, 0.0f);
- coin_draw(fp->cv[ci].n, r);
+ item_draw(&fp->hv[hi], r);
}
glPopMatrix();
}
}
- coin_pull();
+ item_pull();
- //there has got to be a better way than three seperate loops,
- //once for each texture, but someone else is going to have to do it!
- coin_push();
- coin_push_text(50); //any shrink coins?
+ item_push(ITEM_SHRINK);
{
- for (ci = 0; ci < fp->cc; ci++)
-
- if (fp->cv[ci].n == 50)
+ for (hi = 0; hi < fp->hc; hi++)
+
+ if (fp->hv[hi].t == ITEM_SHRINK)
{
glPushMatrix();
{
- glTranslatef(fp->cv[ci].p[0],
- fp->cv[ci].p[1],
- fp->cv[ci].p[2]);
+ glTranslatef(fp->hv[hi].p[0],
+ fp->hv[hi].p[1],
+ fp->hv[hi].p[2]);
glRotatef(r, 0.0f, 1.0f, 0.0f);
- coin_draw(fp->cv[ci].n, r);
+ item_draw(&fp->hv[hi], r);
}
glPopMatrix();
}
}
- coin_pull();
+ item_pull();
- coin_push();
- coin_push_text(150); //any grow coins?
+ item_push(ITEM_GROW);
{
- for (ci = 0; ci < fp->cc; ci++)
-
- if (fp->cv[ci].n == 150)
+ for (hi = 0; hi < fp->hc; hi++)
+
+ if (fp->hv[hi].t == ITEM_GROW)
{
glPushMatrix();
{
- glTranslatef(fp->cv[ci].p[0],
- fp->cv[ci].p[1],
- fp->cv[ci].p[2]);
+ glTranslatef(fp->hv[hi].p[0],
+ fp->hv[hi].p[1],
+ fp->hv[hi].p[2]);
glRotatef(r, 0.0f, 1.0f, 0.0f);
- coin_draw(fp->cv[ci].n, r);
+ item_draw(&fp->hv[hi], r);
}
glPopMatrix();
}
}
- coin_pull();
+ item_pull();
}
static void game_draw_goals(const struct s_file *fp, float rx, float ry)
fp->zv[zi].p[1],
fp->zv[zi].p[2]);
- part_draw_goal(rx, ry, fp->zv[zi].r, goal_k, fp->zv[zi].c);
+ part_draw_goal(rx, ry, fp->zv[zi].r, goal_k);
glScalef(fp->zv[zi].r, goal_k, fp->zv[zi].r);
goal_draw();
{
if (fp->xv[xi].i)
continue;
+
glPushMatrix();
{
glTranslatef(fp->xv[xi].p[0],
static void game_draw_light(void)
{
const float light_p[2][4] = {
- { -8.0f, +32.0f, -8.0f, 1.0f },
- { +8.0f, +32.0f, +8.0f, 1.0f },
+ { -8.0f, +32.0f, -8.0f, 0.0f },
+ { +8.0f, +32.0f, +8.0f, 0.0f },
};
const float light_c[2][4] = {
{ 1.0f, 0.8f, 0.8f, 1.0f },
sol_draw(&file);
- if (config_get_d(CONFIG_SHADOW) && drawball)
+ if (config_get_d(CONFIG_SHADOW))
{
shad_draw_set(ball_p, ball_r);
sol_shad(&file);
if (pose == 0)
{
part_draw_coin(-rx * d, -ry);
- game_draw_coins(&file);
- if (drawball)
- game_draw_balls(&file);
+ game_draw_items(&file);
+ game_draw_balls(&file);
}
game_draw_goals(&file, -rx * d, -ry);
game_draw_jumps(&file);
}
}
-static int game_update_state(int *state_value)
+static int game_update_state(int bt)
{
struct s_file *fp = &file;
+ struct s_goal *zp;
+ struct s_item *hp;
+
float p[3];
float c[3];
- int bt = state_value != NULL;
- int n;
- struct s_goal *g;
- /* Test for a coin grab. */
-
- if (bt && (n = sol_coin_test(fp, p, COIN_RADIUS)) > 0)
+ /* Test for an item. */
+ if (bt && (hp = sol_item_test(fp, p, COIN_RADIUS)))
{
- coin_color(c, n);
+ int sound = AUD_COIN;
+
+ item_color(hp, c);
part_burst(p, c);
- //add coins if regular, change radius if not.
- if (n <= 10)
- coins += n;
- else
- {
- grow_set(fp, n); //only 50 and 150 will produce results.
- n = 0;
- }
+ grow_set(fp, hp->t);
- /* Check for goal open. */
- if (goal_c > 0)
+ if (hp->t == ITEM_COIN)
{
- goal_c = goal_c - n;
- if (goal_c <= 0)
+ coins += hp->n;
+
+ /* Check for goal open. */
+ if (goal_c > 0)
{
- audio_play(AUD_SWITCH, 1.f);
- goal_c = 0;
+ goal_c -= hp->n;
+ if (goal_c <= 0)
+ {
+ sound = AUD_SWITCH;
+ goal_c = 0;
+ }
}
- else
- audio_play(AUD_COIN, 1.f);
}
- else
- audio_play(AUD_COIN, 1.f);
+ audio_play(sound, 1.f);
+
+ /* Reset item type. */
+ hp->t = ITEM_NONE;
}
/* Test for a switch. */
/* Test for a goal. */
- if (bt && goal_c == 0 && (g = sol_goal_test(fp, p, 0)))
+ if (bt && goal_c == 0 && (zp = sol_goal_test(fp, p, 0)))
{
- *state_value = g->s;
audio_play(AUD_GOAL, 1.0f);
- return g->c ? GAME_SPEC : GAME_GOAL;
+ return GAME_GOAL;
}
/* Test for time-out. */
if (bt && clock_down && clock <= 0.f)
{
- const GLfloat *p = fp->uv->p;
- const GLfloat c[5] = {1.0f, 1.0f, 0.0f, 0.0f, 1.0f};
- part_burst(p, c);
- part_burst(p, c+1);
- part_burst(p, c+2);
- part_burst(p, c);
- part_burst(p, c+1);
- part_burst(p, c+2);
- drawball = 0;
audio_play(AUD_TIME, 1.0f);
return GAME_TIME;
}
* the measured frame time exceeds this maximum, we cut the time step in
* half, and do two updates. If THIS time step exceeds the maximum, we do
* four updates. And so on. In this way, the physics system is allowed to
- * seek an optimal update rate independant of, yet in integral sync with, the
+ * seek an optimal update rate independent of, yet in integral sync with, the
* graphics frame rate.
*/
-int game_step(const float g[3], float dt, int *state_value)
+int game_step(const float g[3], float dt, int bt)
{
struct s_file *fp = &file;
game_rz = game_iz;
}
- //might need to put the call to grow_ball here.
-
- if (grow) grow_ball(fp,dt);
+ if (grow)
+ grow_ball(fp, dt);
game_update_grav(h, g);
part_step(h, t);
- if (!drawball)
- /* nothing */;
- else if (jump_b)
+ if (jump_b)
{
jump_dt += t;
/* Mix the sound of a ball bounce. */
if (b > 0.5)
- audio_play(AUD_BUMP, (b - 0.5f) * 2.0f);
+ {
+ float k = (b - 0.5f) * 2.0f;
+
+ if (got_orig)
+ {
+ if (fp->uv->r > grow_orig) audio_play(AUD_BUMPL, k);
+ else if (fp->uv->r < grow_orig) audio_play(AUD_BUMPS, k);
+ else audio_play(AUD_BUMPM, k);
+ }
+ else audio_play(AUD_BUMPM, k);
+ }
}
game_step_fade(dt);
game_update_view(dt);
- game_update_time(dt, state_value != NULL);
+ game_update_time(dt, bt);
- return game_update_state(state_value);
+ return game_update_state(bt);
}
return GAME_NONE;
}