Almost completely separate coins and items in share/geom.c. Items still
[neverball] / ball / game.c
index fbd1231..bc69202 100644 (file)
@@ -68,16 +68,91 @@ 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 view_init(void)
+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)
 {
-    /* 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 :) */
+    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;
     view_ry = 0.f;
 
     view_fov = (float) config_get_d(CONFIG_VIEW_FOV);
@@ -114,7 +189,8 @@ 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),
+    if (!sol_load_gl(&file, config_data(level->file),
+                     config_get_d(CONFIG_TEXTURES),
                      config_get_d(CONFIG_SHADOW)))
         return (game_state = 0);
 
@@ -149,6 +225,10 @@ int game_init(const struct level *level, int t, int g)
     sol_load_gl(&back, config_data(level->back),
                 config_get_d(CONFIG_TEXTURES), 0);
 
+    /* Initialize ball size tracking... */
+
+    got_orig = 0;
+
     return game_state;
 }
 
@@ -214,6 +294,7 @@ static void game_draw_coins(const struct s_file *fp)
     coin_push();
     {
         for (ci = 0; ci < fp->cc; ci++)
+
             if (fp->cv[ci].n > 0)
             {
                 glPushMatrix();
@@ -228,6 +309,57 @@ static void game_draw_coins(const struct s_file *fp)
             }
     }
     coin_pull();
+
+}
+
+static void game_draw_items(const struct s_file *fp)
+{
+    float r = 360.f * SDL_GetTicks() / 1000.f;
+    int hi;
+
+    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].t, r);
+                }
+                glPopMatrix();
+            }
+    }
+    item_pull();
+
+    /* FIXME: there has got to be a better way than two seperate loops,
+     * once for each texture, but someone else is going to have to do
+     * it! */
+
+    item_push();
+    item_push_text(ITEM_GROW);
+    {
+        for (hi = 0; hi < fp->hc; hi++)
+
+            if (fp->hv[hi].t == ITEM_GROW)
+            {
+                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].t, r);
+                }
+                glPopMatrix();
+            }
+    }
+    item_pull();
 }
 
 static void game_draw_goals(const struct s_file *fp, float rx, float ry)
@@ -422,6 +554,7 @@ 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_items(&file);
                 if (drawball)
                     game_draw_balls(&file);
             }
@@ -640,7 +773,7 @@ static int game_update_state(int *state_value)
     float p[3];
     float c[3];
     int bt = state_value != NULL;
-    int n;
+    int n, t;
     struct s_goal *g;
 
     /* Test for a coin grab. */
@@ -650,7 +783,16 @@ static int game_update_state(int *state_value)
         coin_color(c, n);
         part_burst(p, c);
 
-        coins += n;
+        /* Add coins if regular, change radius if not. */
+
+        if (n <= 10)
+            coins += n;
+        else
+        {
+            grow_set(fp, n);
+            n = 0;
+        }
+
         /* Check for goal open. */
         if (goal_c > 0)
         {
@@ -667,6 +809,17 @@ static int game_update_state(int *state_value)
             audio_play(AUD_COIN, 1.f);
     }
 
+    /* Test for an item. */
+    if (bt && (t = sol_item_test(fp, p, COIN_RADIUS)) != ITEM_NONE)
+    {
+        item_color(c, t);
+        part_burst(p, c);
+
+        grow_set(fp, t);
+
+        audio_play(AUD_COIN, 1.f);
+    }
+
     /* Test for a switch. */
     if (sol_swch_test(fp, 0))
         audio_play(AUD_SWITCH, 1.f);
@@ -763,6 +916,9 @@ 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);