X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=ball%2Fgame.c;h=be79fa00a4ed96f2601b24e3420a3ebdb9bac376;hb=afcca7618054cd6c5e900cb32f71466c45edb0cd;hp=aa829dd5b87ac4604a2d13ecd20567d9c83c4a64;hpb=c6d6c9e34bdbdc6e4d9e922130f8a8b0f3a0d20a;p=neverball diff --git a/ball/game.c b/ball/game.c index aa829dd..be79fa0 100644 --- a/ball/game.c +++ b/ball/game.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2003 Robert Kooima * * NEVERBALL is free software; you can redistribute it and/or modify @@ -21,13 +21,12 @@ #include "geom.h" #include "back.h" #include "part.h" -#include "hud.h" #include "image.h" #include "audio.h" -#include "solid.h" -#include "level.h" +#include "solid_gl.h" #include "config.h" #include "binary.h" +#include "level.h" /*---------------------------------------------------------------------------*/ @@ -36,7 +35,8 @@ static int game_state = 0; static struct s_file file; static struct s_file back; -static float clock = 0.f; /* Clock time */ +static float clock = 0.f; /* Clock time */ +static int clock_down = 1; /* Clock go up or down? */ static float game_ix; /* Input rotation about X axis */ static float game_iz; /* Input rotation about Z axis */ @@ -56,18 +56,100 @@ static float view_p[3]; /* Current view position */ static float view_e[3][3]; /* Current view orientation */ static float view_k; -static int goal_e = 0; /* Goal enabled flag */ +static int coins = 0; /* Collected coins */ +static int goal_c = 0; /* Goal coins remaining (0 = open) */ static float goal_k = 0; /* Goal animation */ -static int swch_e = 1; /* Switching enabled flag */ static int jump_e = 1; /* Jumping enabled flag */ static int jump_b = 0; /* Jump-in-progress flag */ static float jump_dt; /* Jump duration */ 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! */ +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 type) +{ + if (!got_orig) + { + grow_orig = fp->uv->r; + grow_goal = grow_orig; + grow_strt = grow_orig; + got_orig = 1; + } + + if (type == ITEM_SHRINK) + { + if (grow_goal == grow_orig * GROW_SMALL) + return; + else if (grow_goal == grow_orig * GROW_BIG) + { + grow = 1; + grow_goal = grow_orig; + } + else + { + grow_goal = grow_orig * GROW_SMALL; + grow = 1; + } + } + if (type == ITEM_GROW) + { + if (grow_goal == grow_orig * GROW_BIG) + return; + else if (grow_goal == grow_orig * GROW_SMALL) + { + grow = 1; + grow_goal = grow_orig; + } + else + { + grow_goal = grow_orig * GROW_BIG; + grow = 1; + } + } + + 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... */ + + grow_t += dt; + + if (grow_t >= GROW_TIME) + { + grow = 0; + grow_t = GROW_TIME; + } + + dr = grow_strt + ((grow_goal-grow_strt) * (1.0f / (GROW_TIME / grow_t))); + + /* 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) { view_a = 0.f; @@ -98,33 +180,38 @@ static void view_init(void) view_e[2][2] = 1.f; } -int game_init(const char *file_name, - const char *back_name, - const char *grad_name, int t, int e) +int game_init(const struct level *level, int t, int g) { - clock = (float) t / 100.f; + clock = (float) t / 100.f; + clock_down = (t > 0); + coins = 0; if (game_state) game_free(); + if (!sol_load_gl(&file, config_data(level->file), + config_get_d(CONFIG_TEXTURES), + config_get_d(CONFIG_SHADOW))) + return (game_state = 0); + + game_state = 1; + game_ix = 0.f; game_iz = 0.f; game_rx = 0.f; game_rz = 0.f; + drawball = 1; + /* Initialize jump and goal states. */ jump_e = 1; jump_b = 0; - goal_e = e ? 1 : 0; - goal_k = e ? 1.0f : 0.0f; - - /* Reset the hud. */ + goal_c = g; + goal_k = (g == 0) ? 1.0f : 0.0f; - hud_ball_pulse(0.f); - hud_time_pulse(0.f); - hud_coin_pulse(0.f); + ball_b = level->is_bonus; /* Initialise the level, background, particles, fade, and view. */ @@ -133,23 +220,24 @@ int game_init(const char *file_name, part_reset(GOAL_HEIGHT); view_init(); - back_init(grad_name, config_get_d(CONFIG_GEOMETRY)); - - if (sol_load(&back, config_data(back_name), - config_get_d(CONFIG_TEXTURES), 0) && - sol_load(&file, config_data(file_name), - config_get_d(CONFIG_TEXTURES), config_get_d(CONFIG_SHADOW))) - return (game_state = 1); - else - return (game_state = 0); + back_init(level->grad, config_get_d(CONFIG_GEOMETRY)); + + sol_load_gl(&back, config_data(level->back), + config_get_d(CONFIG_TEXTURES), 0); + + /* Initialize ball size tracking... */ + + got_orig = 0; + + return game_state; } void game_free(void) { if (game_state) { - sol_free(&file); - sol_free(&back); + sol_free_gl(&file); + sol_free_gl(&back); back_free(); } game_state = 0; @@ -162,9 +250,14 @@ int curr_clock(void) return (int) (clock * 100.f); } -char *curr_intro(void) +int curr_coins(void) +{ + return coins; +} + +int curr_goal(void) { - return (file.ac > 0) ? file.av : NULL; + return goal_c; } /*---------------------------------------------------------------------------*/ @@ -188,40 +281,84 @@ static void game_draw_balls(const struct s_file *fp) glColor4fv(c); - ball_draw(); + ball_draw(ball_b); } 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; + + /* FIXME: Draw items of different types in one pass. */ + + item_push(); + item_push_text(ITEM_COIN); + { + for (hi = 0; hi < fp->hc; hi++) + + if (fp->hv[hi].t == ITEM_COIN && fp->hv[hi].n > 0) + { + glPushMatrix(); + { + glTranslatef(fp->hv[hi].p[0], + fp->hv[hi].p[1], + fp->hv[hi].p[2]); + glRotatef(r, 0.0f, 1.0f, 0.0f); + item_draw(&fp->hv[hi], r); + } + glPopMatrix(); + } + } + item_pull(); + + item_push(); + item_push_text(ITEM_SHRINK); + { + for (hi = 0; hi < fp->hc; hi++) + + if (fp->hv[hi].t == ITEM_SHRINK) + { + glPushMatrix(); + { + glTranslatef(fp->hv[hi].p[0], + fp->hv[hi].p[1], + fp->hv[hi].p[2]); + glRotatef(r, 0.0f, 1.0f, 0.0f); + item_draw(&fp->hv[hi], r); + } + glPopMatrix(); + } + } + item_pull(); - coin_push(); + item_push(); + item_push_text(ITEM_GROW); { - for (ci = 0; ci < fp->cc; ci++) - if (fp->cv[ci].n > 0) + 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) { int zi; - if (goal_e) + if (goal_c == 0) for (zi = 0; zi < fp->zc; zi++) { glPushMatrix(); @@ -230,7 +367,7 @@ 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); + part_draw_goal(rx, ry, fp->zv[zi].r, goal_k, fp->zv[zi].c); glScalef(fp->zv[zi].r, goal_k, fp->zv[zi].r); goal_draw(); @@ -252,7 +389,7 @@ static void game_draw_jumps(const struct s_file *fp) fp->jv[ji].p[2]); glScalef(fp->jv[ji].r, 1.f, fp->jv[ji].r); - jump_draw(); + jump_draw(!jump_e); } glPopMatrix(); } @@ -264,6 +401,8 @@ static void game_draw_swchs(const struct s_file *fp) for (xi = 0; xi < fp->xc; xi++) { + if (fp->xv[xi].i) + continue; glPushMatrix(); { glTranslatef(fp->xv[xi].p[0], @@ -271,7 +410,7 @@ static void game_draw_swchs(const struct s_file *fp) fp->xv[xi].p[2]); glScalef(fp->xv[xi].r, 1.f, fp->xv[xi].r); - swch_draw(fp->xv[xi].f); + swch_draw(fp->xv[xi].f, fp->xv[xi].e); } glPopMatrix(); } @@ -362,7 +501,7 @@ static void game_draw_fore(int pose, float rx, float ry, int d, const float p[3] { const float *ball_p = file.uv->p; const float ball_r = file.uv->r; - + glPushAttrib(GL_LIGHTING_BIT | GL_COLOR_BUFFER_BIT); { glPushMatrix(); @@ -391,7 +530,7 @@ static void game_draw_fore(int pose, float rx, float ry, int d, const float p[3] sol_draw(&file); - if (config_get_d(CONFIG_SHADOW)) + if (config_get_d(CONFIG_SHADOW) && drawball) { shad_draw_set(ball_p, ball_r); sol_shad(&file); @@ -406,8 +545,9 @@ static void game_draw_fore(int pose, float rx, float ry, int d, const float p[3] if (pose == 0) { part_draw_coin(-rx * d, -ry); - game_draw_coins(&file); - game_draw_balls(&file); + game_draw_items(&file); + if (drawball) + game_draw_balls(&file); } game_draw_goals(&file, -rx * d, -ry); game_draw_jumps(&file); @@ -600,55 +740,68 @@ static void game_update_view(float dt) static void game_update_time(float dt, int b) { - int tick = (int) floor(clock); - int tock = (int) floor(clock * 2); - - if (goal_e && goal_k < 1.0f) + if (goal_c == 0 && goal_k < 1.0f) goal_k += dt; /* The ticking clock. */ - if (b) + if (b && clock_down) { if (clock < 600.f) clock -= dt; if (clock < 0.f) clock = 0.f; - - if (0 < tick && tick <= 10 && tick == (int) ceil(clock)) - { - audio_play(AUD_TICK, 1.f); - hud_time_pulse(1.50); - } - else if (0 < tock && tock <= 10 && tock == (int) ceil(clock * 2)) - { - audio_play(AUD_TOCK, 1.f); - hud_time_pulse(1.25); - } + } + else if (b) + { + clock += dt; } } -static int game_update_state(void) +static int game_update_state(int *state_value) { struct s_file *fp = &file; + struct s_goal *zp; + struct s_item *hp; + float p[3]; float c[3]; - int n, e = swch_e; - /* Test for a coin grab and a possible 1UP. */ + int bt = state_value != NULL; - if ((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); - if (level_score(n)) - goal_e = 1; + grow_set(fp, hp->t); + + if (hp->t == ITEM_COIN) + { + coins += hp->n; + + /* Check for goal open. */ + if (goal_c > 0) + { + goal_c -= hp->n; + if (goal_c <= 0) + { + sound = AUD_SWITCH; + goal_c = 0; + } + } + } + audio_play(sound, 1.f); + + /* Reset item type. */ + hp->t = ITEM_NONE; } /* Test for a switch. */ - - if ((swch_e = sol_swch_test(fp, swch_e, 0)) != e && e) + if (sol_swch_test(fp, 0)) audio_play(AUD_SWITCH, 1.f); /* Test for a jump. */ @@ -658,7 +811,7 @@ static int game_update_state(void) jump_b = 1; jump_e = 0; jump_dt = 0.f; - + audio_play(AUD_JUMP, 1.f); } if (jump_e == 0 && jump_b == 0 && sol_jump_test(fp, jump_p, 0) == 0) @@ -666,18 +819,37 @@ static int game_update_state(void) /* Test for a goal. */ - if (goal_e && sol_goal_test(fp, p, 0)) - return GAME_GOAL; + if (bt && goal_c == 0 && (zp = sol_goal_test(fp, p, 0))) + { + *state_value = zp->s; + audio_play(AUD_GOAL, 1.0f); + return zp->c ? GAME_SPEC : GAME_GOAL; + } /* Test for time-out. */ - if (clock <= 0.f) + 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; + } /* Test for fall-out. */ - if (fp->uv[0].p[1] < fp->vv[0].p[1]) + if (bt && fp->uv[0].p[1] < fp->vv[0].p[1]) + { + audio_play(AUD_FALL, 1.0f); return GAME_FALL; + } return GAME_NONE; } @@ -697,7 +869,7 @@ static int game_update_state(void) * graphics frame rate. */ -int game_step(const float g[3], float dt, int bt) +int game_step(const float g[3], float dt, int *state_value) { struct s_file *fp = &file; @@ -724,10 +896,15 @@ int game_step(const float g[3], float dt, int bt) game_rz = game_iz; } + if (grow) + grow_ball(fp, dt); + game_update_grav(h, g); part_step(h, t); - if (jump_b) + if (!drawball) + /* nothing */; + else if (jump_b) { jump_dt += t; @@ -764,36 +941,55 @@ int game_step(const float g[3], float dt, int bt) game_step_fade(dt); game_update_view(dt); - game_update_time(dt, bt); + game_update_time(dt, state_value != NULL); - return game_update_state(); + return game_update_state(state_value); } return GAME_NONE; } /*---------------------------------------------------------------------------*/ +void game_no_aa(void) +{ + float max = game_ix * game_ix + game_iz * game_iz; + if (max > ANGLE_BOUND * ANGLE_BOUND) + { + max = ANGLE_BOUND / sqrt(max); + game_ix *= max; + game_iz *= max; + } +} + void game_set_x(int k) { - game_ix = -20.f * k / JOY_MAX; + game_ix = -(ANGLE_BOUND) * k / JOY_MAX; +#if NO_AA + game_no_aa(); +#endif } void game_set_z(int k) { - game_iz = +20.f * k / JOY_MAX; + game_iz = +ANGLE_BOUND * k / JOY_MAX; +#if NO_AA + game_no_aa(); +#endif } void game_set_pos(int x, int y) { - float bound = 20.f; - game_ix += 40.f * y / config_get_d(CONFIG_MOUSE_SENSE); game_iz += 40.f * x / config_get_d(CONFIG_MOUSE_SENSE); - if (game_ix > +bound) game_ix = +bound; - if (game_ix < -bound) game_ix = -bound; - if (game_iz > +bound) game_iz = +bound; - if (game_iz < -bound) game_iz = -bound; +#if NO_AA + game_no_aa(); +#else + if (game_ix > +ANGLE_BOUND) game_ix = +ANGLE_BOUND; + if (game_ix < -ANGLE_BOUND) game_ix = -ANGLE_BOUND; + if (game_iz > +ANGLE_BOUND) game_iz = +ANGLE_BOUND; + if (game_iz < -ANGLE_BOUND) game_iz = -ANGLE_BOUND; +#endif } void game_set_rot(float r) @@ -816,6 +1012,9 @@ void game_set_fly(float k) float p1[3] = { 0.f, 0.f, 0.f }; float v[3]; + 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);