Starting header clean-up.
[neverball] / ball / game.c
index 3346660..f5f807b 100644 (file)
@@ -1,4 +1,4 @@
-/*   
+/*
  * Copyright (C) 2003 Robert Kooima
  *
  * NEVERBALL is  free software; you can redistribute  it and/or modify
@@ -65,12 +65,95 @@ 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!          */
+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         */
+const  float grow_big  = 1.5f;          /* large factor                      */
+const  float grow_small= 0.5f;          /* small factor                      */
+
+
 
 /*---------------------------------------------------------------------------*/
 
+static void grow_set(const struct s_file *fp, int size)
+{
+    static int got_orig = 0;
+    if (!got_orig)
+    {
+        grow_orig = fp->uv->r;
+        grow_goal = grow_orig;
+        grow_strt = grow_orig;
+        got_orig  = 1;
+    }
+
+    if (size == 50)
+    {
+        if (grow_goal == grow_orig * grow_small) return; /*already small!*/
+        else if (grow_goal == grow_orig * grow_big) /* big, let's set it to normal.*/
+        {
+            grow = 1;
+            grow_goal = grow_orig;
+        }
+        else /*must be normal sized.*/
+        {
+            grow_goal = grow_orig * grow_small;
+            grow = 1;
+        }
+    }/* done with 50% size coin */
+    if (size == 150)
+    {
+        if (grow_goal == grow_orig * grow_big) return; /*already big!*/
+        else if (grow_goal == grow_orig * grow_small) /* small, let's set it to normal.*/
+        {
+            grow = 1;
+            grow_goal = grow_orig;
+        }
+        else /*must be normal sized.*/
+        {
+            grow_goal = grow_orig * grow_big;
+            grow = 1;
+        }
+    }/* done with 150% size coin */
+
+    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)));
+
+    fp->uv->p[1] += (dr - fp->uv->r); /*No sinking through the floor! keeps ball's bottom constant.*/
+    fp->uv->r = dr;
+}
+
 static void view_init(void)
 {
-    view_a  = 0.f;
+    /* 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_ry = 0.f;
 
     view_fov = (float) config_get_d(CONFIG_VIEW_FOV);
@@ -98,7 +181,7 @@ static void view_init(void)
     view_e[2][2] = 1.f;
 }
 
-int game_init(const struct level * level, int t, int g)
+int game_init(const struct level *level, int t, int g)
 {
     clock      = (float) t / 100.f;
     clock_down = (t > 0);
@@ -107,11 +190,19 @@ int game_init(const struct level * level, int t, int g)
     if (game_state)
         game_free();
 
+    if (!sol_load_gl(&file, 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;
@@ -120,6 +211,8 @@ int game_init(const struct level * level, int t, int g)
     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;
@@ -130,13 +223,9 @@ int game_init(const struct level * level, int t, int g)
     back_init(level->grad, config_get_d(CONFIG_GEOMETRY));
 
     sol_load_gl(&back, config_data(level->back),
-                   config_get_d(CONFIG_TEXTURES), 0);
+                config_get_d(CONFIG_TEXTURES), 0);
 
-    if (sol_load_gl(&file, level->file,
-                 config_get_d(CONFIG_TEXTURES), config_get_d(CONFIG_SHADOW)))
-        return (game_state = 1);
-    else
-        return (game_state = 0);
+    return game_state;
 }
 
 void game_free(void)
@@ -188,7 +277,7 @@ static void game_draw_balls(const struct s_file *fp)
 
         glColor4fv(c);
 
-        ball_draw();
+        ball_draw(ball_b);
     }
     glPopMatrix();
 }
@@ -199,9 +288,53 @@ static void game_draw_coins(const struct s_file *fp)
     int ci;
 
     coin_push();
+    coin_push_text(0); /*regular coins*/
+    {
+        for (ci = 0; ci < fp->cc; ci++)
+
+            if (fp->cv[ci].n > 0 && fp->cv[ci].n < 50)
+            {
+                glPushMatrix();
+                {
+                    glTranslatef(fp->cv[ci].p[0],
+                                 fp->cv[ci].p[1],
+                                 fp->cv[ci].p[2]);
+                    glRotatef(r, 0.0f, 1.0f, 0.0f);
+                    coin_draw(fp->cv[ci].n, r);
+                }
+                glPopMatrix();
+            }
+    }
+    coin_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?*/
     {
         for (ci = 0; ci < fp->cc; ci++)
-            if (fp->cv[ci].n > 0)
+
+            if (fp->cv[ci].n == 50)
+            {
+                glPushMatrix();
+                {
+                    glTranslatef(fp->cv[ci].p[0],
+                                 fp->cv[ci].p[1],
+                                 fp->cv[ci].p[2]);
+                    glRotatef(r, 0.0f, 1.0f, 0.0f);
+                    coin_draw(fp->cv[ci].n, r);
+                }
+                glPopMatrix();
+            }
+    }
+    coin_pull();
+
+    coin_push();
+    coin_push_text(150); /*any grow coins?*/
+    {
+        for (ci = 0; ci < fp->cc; ci++)
+
+            if (fp->cv[ci].n == 150)
             {
                 glPushMatrix();
                 {
@@ -264,8 +397,8 @@ static void game_draw_swchs(const struct s_file *fp)
 
     for (xi = 0; xi < fp->xc; xi++)
     {
-       if (fp->xv[xi].i)
-           continue;
+        if (fp->xv[xi].i)
+            continue;
         glPushMatrix();
         {
             glTranslatef(fp->xv[xi].p[0],
@@ -364,7 +497,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();
@@ -393,7 +526,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);
@@ -409,7 +542,8 @@ static void game_draw_fore(int pose, float rx, float ry, int d, const float p[3]
             {
                 part_draw_coin(-rx * d, -ry);
                 game_draw_coins(&file);
-                game_draw_balls(&file);
+                if (drawball)
+                    game_draw_balls(&file);
             }
             game_draw_goals(&file, -rx * d, -ry);
             game_draw_jumps(&file);
@@ -627,29 +761,38 @@ static int game_update_state(int *state_value)
     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)
     {
         coin_color(c, n);
         part_burst(p, c);
 
-       coins += n;
-       /* Check for goal open. */
-       if (goal_c > 0)
-       {
-           goal_c = goal_c - n;
-           if (goal_c <= 0)
-           {
-               audio_play(AUD_SWITCH, 1.f);
-               goal_c = 0;
-           }
-           else
-               audio_play(AUD_COIN, 1.f);
-       } 
-       else
-           audio_play(AUD_COIN, 1.f);
+        /*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;
+        }
+
+        /* Check for goal open. */
+        if (goal_c > 0)
+        {
+            goal_c = goal_c - n;
+            if (goal_c <= 0)
+            {
+                audio_play(AUD_SWITCH, 1.f);
+                goal_c = 0;
+            }
+            else
+                audio_play(AUD_COIN, 1.f);
+        }
+        else
+            audio_play(AUD_COIN, 1.f);
     }
 
     /* Test for a switch. */
@@ -663,7 +806,7 @@ static int game_update_state(int *state_value)
         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)
@@ -671,22 +814,40 @@ static int game_update_state(int *state_value)
 
     /* Test for a goal. */
 
-    if (bt && goal_c == 0 && (n = sol_goal_test(fp, p, 0)))
+    if (bt && goal_c == 0 && (g = sol_goal_test(fp, p, 0)))
     {
-       *state_value = n - 1;
-       audio_play(AUD_GOAL, 1.0f);
-        return GAME_GOAL;
+        *state_value = g->s;
+        audio_play(AUD_GOAL, 1.0f);
+        grow_goal = grow_orig;
+        return g->c ? GAME_SPEC : 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;
+        grow_goal = grow_orig;
+        audio_play(AUD_TIME, 1.0f);
         return GAME_TIME;
+    }
 
     /* Test for fall-out. */
 
     if (bt && fp->uv[0].p[1] < fp->vv[0].p[1])
+    {
+        audio_play(AUD_FALL, 1.0f);
+        grow_goal = grow_orig;
         return GAME_FALL;
+    }
 
     return GAME_NONE;
 }
@@ -733,10 +894,14 @@ int game_step(const float g[3], float dt, int *state_value)
             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;
 
@@ -787,9 +952,9 @@ 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;
+        max = ANGLE_BOUND / sqrt(max);
+        game_ix *= max;
+        game_iz *= max;
     }
 }
 
@@ -813,7 +978,7 @@ void game_set_pos(int x, int y)
 {
     game_ix += 40.f * y / config_get_d(CONFIG_MOUSE_SENSE);
     game_iz += 40.f * x / config_get_d(CONFIG_MOUSE_SENSE);
-    
+
 #if NO_AA
     game_no_aa();
 #else
@@ -844,6 +1009,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);