From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / sproingies.c
index d79ffe579d10a660cc3858465d84f66c8f4e4563..41a31a1590ff070af9f4b1af3b31705fa994d25f 100644 (file)
@@ -1,9 +1,8 @@
 /* -*- Mode: C; tab-width: 4 -*- */
 /* sproingies.c - 3D sproingies */
 
-#if !defined( lint ) && !defined( SABER )
+#if 0
 static const char sccsid[] = "@(#)sproingies.c 4.04 97/07/28 xlockmore";
-
 #endif
 
 /*-
@@ -22,9 +21,13 @@ static const char sccsid[] = "@(#)sproingies.c       4.04 97/07/28 xlockmore";
  * other special, indirect and consequential damages.
  *
  * Revision History:
- * 07-Dec-96: Written.
+ * See sproingiewrap.c
  */
 
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
 #ifdef STANDALONE
 # include "xlockmoreI.h"               /* from the xscreensaver distribution */
 #else /* !STANDALONE */
@@ -33,34 +36,39 @@ static const char sccsid[] = "@(#)sproingies.c      4.04 97/07/28 xlockmore";
 
 #ifdef USE_GL
 
-#include <GL/gl.h>
-#include <GL/glu.h>
-#include "buildlwo.h"
-
-#define MAXSPROING 100
-#define T_COUNT 40
-#define BOOM_FRAME 50
-
-struct sPosColor {
-       int         x, y, z, frame, life;
-       GLfloat     r, g, b;
-};
+#if !defined(HAVE_JWZGLES) && !defined(HAVE_COCOA)
+# include <GL/glu.h>
+#endif
 
-typedef struct {
-       int         rotx, roty, dist, wireframe, flatshade, groundlevel,
-                   maxsproingies, mono;
-       int         sframe, target_rx, target_ry, target_dist, target_count;
-       GLuint      sproingies[6], TopsSides, SproingieBoom;
-       struct sPosColor *positions;
-} sp_instance;
+#include "gllist.h"
+#include "sproingies.h"
 
-static sp_instance *si_list = NULL;
-static int  active_screens = 0;
+#define MAXSPROING           100
+#define TARGET_COUNT         40
+#define BOOM_FRAME           50
+#define NO_FRAME             (-10)
+#define RESET_SPROINGIE_LIFE (-30 + myrand(28))
+#define NEW_SPROINGIE_LIFE   (40 + myrand(200))
+#define JUMP_LEFT            0
+#define JUMP_RIGHT           1
 
-void        SproingieSwap(void);
+#define FIRST_FRAME          0
+#define LAST_FRAME           5 
+/*-
+ * The sproingies have six "real" frames, (s1_1 to s1_6) that show a
+ * sproingie jumping off a block, headed down and to the right. 
+ * The frames are numbered from 0 (FIRST_FRAME) to 5 (LAST_FRAME). 
+ * 
+ * There are other frame numbers for special cases (e.g. BOOM_FRAME).
+ */
 
-extern struct lwo LWO_s1_1, LWO_s1_2, LWO_s1_3, LWO_s1_4;
-extern struct lwo LWO_s1_5, LWO_s1_6, LWO_s1_b;
+extern const struct gllist *s1_1;
+extern const struct gllist *s1_2;
+extern const struct gllist *s1_3;
+extern const struct gllist *s1_4;
+extern const struct gllist *s1_5;
+extern const struct gllist *s1_6;
+extern const struct gllist *s1_b;
 
 static int
 myrand(int range)
@@ -68,6 +76,8 @@ myrand(int range)
        return ((int) (((float) range) * LRAND() / (MAXRAND)));
 }
 
+static int smart_sproingies = 0;
+
 static      GLuint
 build_TopsSides(int wireframe)
 {
@@ -93,12 +103,13 @@ build_TopsSides(int wireframe)
 
        /* Surface: Sides */
        glNewList(dl_num + 1, GL_COMPILE);
-       mat_color[0] = 0.156863;
-       mat_color[1] = 0.156863;
-       mat_color[2] = 0.392157;
        if (wireframe)
                glColor3fv(mat_color);
        else {
+      /* jwz: in wireframe mode, color tops and sides the same. */
+      mat_color[0] = 0.156863;
+      mat_color[1] = 0.156863;
+      mat_color[2] = 0.392157;
                glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
        }
        glEndList();
@@ -227,8 +238,6 @@ LayGround(int sx, int sy, int sz, int width, int height, sp_instance * si)
        }
 }
 
-#define RESET_SPROINGIE (-30 + myrand(28))
-
 static void
 AdvanceSproingie(int t, sp_instance * si)
 {
@@ -237,7 +246,7 @@ AdvanceSproingie(int t, sp_instance * si)
        struct sPosColor *S2 = &(si->positions[0]);
 
        if (thisSproingie->life > 0) {
-               if ((++(thisSproingie->frame)) > 11) {
+               if ((++(thisSproingie->frame)) > LAST_FRAME) {
                        if (thisSproingie->frame >= BOOM_FRAME) {
                                if ((thisSproingie->r -= 0.08) < 0.0)
                                        thisSproingie->r = 0.0;
@@ -246,19 +255,17 @@ AdvanceSproingie(int t, sp_instance * si)
                                if ((thisSproingie->b -= 0.08) < 0.0)
                                        thisSproingie->b = 0.0;
                                if ((--(thisSproingie->life)) < 1) {
-                                       thisSproingie->life = RESET_SPROINGIE;
+                                       thisSproingie->life = RESET_SPROINGIE_LIFE;
                                }
                                return;
                        }
-                       thisSproingie->x += 1;
-                       thisSproingie->y -= 2;
-                       thisSproingie->z += 1;
-                       thisSproingie->frame = 0;
+                       thisSproingie->frame = FIRST_FRAME;
 
+                       /* Check for collisions */
                        for (t2 = 0; t2 < si->maxsproingies; ++t2) {
                                if ((t2 != t) && (thisSproingie->x == S2->x) &&
                                    (thisSproingie->y == S2->y) && (thisSproingie->z == S2->z) &&
-                                   (S2->life > 10) && (S2->frame < 6)) {
+                                   (S2->life > 10) && (S2->frame < LAST_FRAME + 1)) {
 #if 0
                                        if (thisSproingie->life > S2->life) {
                                                S2->life = 10;
@@ -281,17 +288,18 @@ AdvanceSproingie(int t, sp_instance * si)
                                ++S2;
                        }
                }
+               /* Time to disappear... */
                if (!((thisSproingie->life == 10) &&
-                     (thisSproingie->frame > 0) &&
+                     (thisSproingie->frame > FIRST_FRAME) &&
                      (thisSproingie->frame < BOOM_FRAME))) {
                        if ((--(thisSproingie->life)) < 1) {
-                               thisSproingie->life = RESET_SPROINGIE;
+                               thisSproingie->life = RESET_SPROINGIE_LIFE;
                        } else if (thisSproingie->life < 9) {
                                thisSproingie->frame -= 2;
-                       }
-               }               /* else wait here for frame 0 to come about. */
+                       } 
+               }               /* ... else wait here for frame FIRST_FRAME to come about. */
        } else if (++(thisSproingie->life) >= 0) {
-               if (t > 1) {
+               if (1 || t > 1) {
                        g_higher = -3 + myrand(5);
                        g_back = -2 + myrand(5);
                } else if (t == 1) {
@@ -302,20 +310,20 @@ AdvanceSproingie(int t, sp_instance * si)
                        g_back = 0;
                }
 
-               thisSproingie->x = (-g_higher - g_back);
-               thisSproingie->y = (g_higher << 1);
-               thisSproingie->z = (g_back - g_higher);
-               thisSproingie->life = 40 + myrand(200);
-               thisSproingie->frame = -10;
-               thisSproingie->r = (GLfloat) (40 + myrand(200)) / 255.0;
-               thisSproingie->g = (GLfloat) (40 + myrand(200)) / 255.0;
-               thisSproingie->b = (GLfloat) (40 + myrand(200)) / 255.0;
+               thisSproingie->x     = (-g_higher - g_back);
+               thisSproingie->y     = (g_higher << 1);
+               thisSproingie->z     = (g_back - g_higher);
+               thisSproingie->life  = NEW_SPROINGIE_LIFE;
+               thisSproingie->frame = NO_FRAME;
+               thisSproingie->r     = (GLfloat) (40 + myrand(200)) / 255.0;
+               thisSproingie->g     = (GLfloat) (40 + myrand(200)) / 255.0;
+               thisSproingie->b     = (GLfloat) (40 + myrand(200)) / 255.0;
 
                for (t2 = 0; t2 < si->maxsproingies; ++t2) {
                        if ((t2 != t) && (thisSproingie->x == S2->x) &&
                            (thisSproingie->y == S2->y) && (thisSproingie->z == S2->z) &&
-                           (S2->life > 10) && (S2->frame < 0)) {
-                               /* If one is already being born, just wait. */
+                           (S2->life > 10) && (S2->frame < FIRST_FRAME)) {
+                               /* If another is already on this place, wait. */
                                thisSproingie->life = -1;
                        }
                        ++S2;
@@ -324,14 +332,16 @@ AdvanceSproingie(int t, sp_instance * si)
 }
 
 static void
-NextSproingie(int screen)
+NextSproingie(sp_instance *si)
 {
-       sp_instance *si = &si_list[screen];
        int         ddx, t;
        struct sPosColor *thisSproingie = &(si->positions[0]);
 
+       /* Although the sproingies cycle has six frames, the blocks cycle  */
+       /* has twelve. After a full cycle (12 frames), re-center positions */
+       /* of sproingies                                                   */
        if (++si->sframe > 11) {
-               si->sframe = 0;
+               si->sframe = FIRST_FRAME;
                for (t = 0; t < si->maxsproingies; ++t) {
                        thisSproingie->x -= 1;
                        thisSproingie->y += 2;
@@ -339,6 +349,7 @@ NextSproingie(int screen)
                        ++thisSproingie;
                }
        }
+
        for (t = 0; t < si->maxsproingies; ++t) {
                AdvanceSproingie(t, si);
        }
@@ -364,7 +375,7 @@ NextSproingie(int screen)
 
                if ((si->target_rx == si->rotx) && (si->target_ry == si->roty) &&
                    (si->target_dist == si->dist)) {
-                       si->target_count = T_COUNT;
+                       si->target_count = TARGET_COUNT;
                        if (si->target_dist <= 32)
                                si->target_count >>= 2;
                }
@@ -403,7 +414,7 @@ ResetEm(void)
                positions[t].y = 0;
                positions[t].z = 0;
                positions[t].life = -2;
-               positions[t].frame = 0;
+               positions[t].frame = FIRST_FRAME;
        }
 }
 
@@ -469,15 +480,17 @@ rotyBSubtract(void)
        roty = (roty - 45) % 360;
 }
 
-#endif
+#endif /* __AUXFUNCS__ */
 
 static void
 RenderSproingie(int t, sp_instance * si)
 {
        GLfloat     scale, pointsize, mat_color[4] =
        {0.0, 0.0, 0.0, 1.0};
+#ifndef HAVE_JWZGLES
        GLdouble    clipplane[4] =
        {0.0, 1.0, 0.0, 0.0};
+#endif
        struct sPosColor *thisSproingie = &(si->positions[t]);
 
        if (thisSproingie->life < 1)
@@ -495,22 +508,33 @@ RenderSproingie(int t, sp_instance * si)
                        glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
                }
        }
-       if (thisSproingie->frame < 0) {
+
+       if (thisSproingie->frame < FIRST_FRAME) {
                glEnable(GL_CLIP_PLANE0);
                glTranslatef((GLfloat) (thisSproingie->x),
                             (GLfloat) (thisSproingie->y) +
                             ((GLfloat) (thisSproingie->frame) / 9.0),
                             (GLfloat) (thisSproingie->z));
+
+#ifndef HAVE_JWZGLES
+        /* OpenGLES doesn't have this but it doesn't seem to matter */
                clipplane[3] = ((GLdouble) (thisSproingie->frame) / 9.0) +
                        (si->wireframe ? 0.0 : 0.1);
                glClipPlane(GL_CLIP_PLANE0, clipplane);
-               glCallList(si->sproingies[0]);
+#endif
+
+/**            glCallList(si->sproingies[0]);*/
+/**/   renderList(si->sproingies[0], si->wireframe);
                glDisable(GL_CLIP_PLANE0);
        } else if (thisSproingie->frame >= BOOM_FRAME) {
                glTranslatef((GLfloat) (thisSproingie->x) + 0.5,
                             (GLfloat) (thisSproingie->y) + 0.5,
                             (GLfloat) (thisSproingie->z) - 0.5);
-               scale = (GLfloat) (1 << (thisSproingie->frame - BOOM_FRAME));
+               {
+                       int boom_scale = thisSproingie->frame - BOOM_FRAME;
+                       if (boom_scale >= 31) boom_scale = 31;
+                       scale = (GLfloat) (1 << boom_scale);
+               }
                glScalef(scale, scale, scale);
                if (!si->wireframe) {
                        if (!si->mono)
@@ -523,20 +547,68 @@ RenderSproingie(int t, sp_instance * si)
 /*-
  * PURIFY 4.0.1 reports an unitialized memory read on the next line when using
  * MesaGL 2.2.  This has been tracked to MesaGL 2.2 src/points.c line 313. */
-               glCallList(si->SproingieBoom);
+/**            glCallList(si->SproingieBoom);*/
+/**/   renderList(si->SproingieBoom, si->wireframe);
                glPointSize(1.0);
                if (!si->wireframe) {
                        glEnable(GL_LIGHTING);
                }
-       } else if (thisSproingie->frame > 5) {
-               glTranslatef((GLfloat) (thisSproingie->x + 1),
-                            (GLfloat) (thisSproingie->y - 1), (GLfloat) (thisSproingie->z - 1));
-               glRotatef((GLfloat) - 90.0, 0.0, 1.0, 0.0);
-               glCallList(si->sproingies[thisSproingie->frame - 6]);
        } else {
-               glTranslatef((GLfloat) (thisSproingie->x), (GLfloat) (thisSproingie->y),
-                            (GLfloat) (thisSproingie->z));
-               glCallList(si->sproingies[thisSproingie->frame]);
+               if (thisSproingie->direction == JUMP_LEFT) {
+                       /* When the sproingie jumps to the left, the frames must be */
+                       /* rotated and translated */
+                       glTranslatef((GLfloat) (thisSproingie->x    ),
+                                                (GLfloat) (thisSproingie->y    ), 
+                                                (GLfloat) (thisSproingie->z - 1));
+                       glRotatef((GLfloat) - 90.0, 0.0, 1.0, 0.0);
+                       if (thisSproingie->frame == LAST_FRAME) {
+                               thisSproingie->x -= 0;
+                               thisSproingie->y -= 1;
+                               thisSproingie->z += 1;
+                       } 
+               } else {
+                       glTranslatef((GLfloat) (thisSproingie->x),
+                                                (GLfloat) (thisSproingie->y), 
+                                                (GLfloat) (thisSproingie->z));
+                       glRotatef((GLfloat) - 0.0, 0.0, 1.0, 0.0);
+                       if (thisSproingie->frame == LAST_FRAME) {
+                               thisSproingie->x += 1;
+                               thisSproingie->y -= 1;
+                               thisSproingie->z -= 0;
+                       }
+               }
+/*     } */
+/**            glCallList(si->sproingies[thisSproingie->frame]);*/
+/**/   renderList(si->sproingies[thisSproingie->frame], si->wireframe);
+
+               /* Every 6 frame cycle... */
+               if (thisSproingie->frame == LAST_FRAME) {
+                       /* ...check if the sproingies have gone out of the bricks */
+                       if (((thisSproingie->x - thisSproingie->z == 6) &&
+                                (2*thisSproingie->x + thisSproingie->y == 6)) ||
+                               ((thisSproingie->z - thisSproingie->x == 5) &&
+                                (2*thisSproingie->x + thisSproingie->y == -5))) {
+                               /* If they have, then they die */
+                               if (thisSproingie->life > 0 && thisSproingie->frame < BOOM_FRAME && thisSproingie->frame > FIRST_FRAME) {
+                                       thisSproingie->frame = BOOM_FRAME;
+                               }
+                       } else {
+                               /* If not, they choose a direction for the next hop */
+                               if (smart_sproingies) {
+                                       if ((thisSproingie->x - thisSproingie->z == 5) &&   
+                                               (2*thisSproingie->x + thisSproingie->y == 5)) {
+                                               thisSproingie->direction = JUMP_LEFT;
+                                       } else if ((thisSproingie->z - thisSproingie->x == 4) &&   
+                                                (2*thisSproingie->x + thisSproingie->y == -4)) {
+                                               thisSproingie->direction = JUMP_RIGHT;
+                                       } else {
+                                               thisSproingie->direction = myrand(2);
+                                       }
+                               } else {
+                                       thisSproingie->direction = myrand(2);
+                               }
+                       }
+               }
        }
 
        glPopMatrix();
@@ -596,9 +668,8 @@ ComputeGround(sp_instance * si)
 }
 
 void
-DisplaySproingies(int screen,int pause)
+DisplaySproingies(sp_instance *si)
 {
-       sp_instance *si = &si_list[screen];
        int         t;
        GLfloat     position[] =
        {8.0, 5.0, -2.0, 0.1};
@@ -646,16 +717,14 @@ DisplaySproingies(int screen,int pause)
 
        glPopMatrix();
        glFlush();
-
-       SproingieSwap();
 }
 
 void
-NextSproingieDisplay(int screen,int pause)
+NextSproingieDisplay(sp_instance *si)
 {
-       NextSproingie(screen);
-        if (pause) usleep(pause);
-       DisplaySproingies(screen,pause);
+       NextSproingie(si);
+/*        if (pause) usleep(pause);  don't do this! -jwz */
+       DisplaySproingies(si);
 }
 
 void
@@ -670,11 +739,12 @@ ReshapeSproingies(int w, int h)
 }
 
 void
-CleanupSproingies(int screen)
+CleanupSproingies(sp_instance *si)
 {
-       sp_instance *si = &si_list[screen];
-       int         t;
+    if (! si) return;
 
+/*
+       int         t;
        if (si->SproingieBoom) {
                for (t = 0; t < 6; ++t)
                        glDeleteLists(si->sproingies[t], 1);
@@ -682,22 +752,21 @@ CleanupSproingies(int screen)
                glDeleteLists(si->TopsSides, 2);
                glDeleteLists(si->SproingieBoom, 1);
 
-               --active_screens;
                si->SproingieBoom = 0;
        }
+*/
+       if (si->TopsSides) {
+               glDeleteLists(si->TopsSides, 2);
+       }
        if (si->positions) {
                (void) free((void *) (si->positions));
                si->positions = NULL;
        }
-       if ((active_screens == 0) && si_list) {
-               (void) free((void *) (si_list));
-               si_list = NULL;
-       }
 }
 
 void
-InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
-              int mono)
+InitSproingies(sp_instance *si, int wfmode, int grnd, int mspr, int smrtspr,
+                          int mono)
 {
        GLfloat     ambient[] =
        {0.2, 0.2, 0.2, 1.0};
@@ -710,24 +779,17 @@ InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
        GLfloat     mat_shininess[] =
        {50.0};
 
-       sp_instance *si;
        int         t;
 
-       if (si_list == NULL) {
-               if ((si_list = (sp_instance *) calloc(numscreens,
-                                             sizeof (sp_instance))) == NULL)
-                       return;
-       }
-       si = &si_list[screen];
-
-       active_screens++;
-       CleanupSproingies(screen);
+       memset (si, 0, sizeof(*si));
 
        if (mspr < 0)
                mspr = 0;
        if (mspr >= MAXSPROING)
                mspr = MAXSPROING - 1;
 
+       smart_sproingies = smrtspr; 
+
        si->rotx = 0;
        si->roty = -45;
        si->dist = (16 << 2);
@@ -757,7 +819,8 @@ InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
                si->positions[t].y = 0;
                si->positions[t].z = 0;
                si->positions[t].life = (-t * ((si->maxsproingies > 19) ? 1 : 4)) - 2;
-               si->positions[t].frame = 0;
+               si->positions[t].frame = FIRST_FRAME;
+               si->positions[t].direction = myrand(2);
        }
 
 #if 0                          /* Test boom */
@@ -773,7 +836,7 @@ InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
 
        if (!(si->TopsSides = build_TopsSides(si->wireframe)))
                (void) fprintf(stderr, "build_TopsSides\n");
-
+/*
        if (!(si->sproingies[0] = BuildLWO(si->wireframe, &LWO_s1_1)))
                (void) fprintf(stderr, "BuildLWO - 1\n");
        if (!(si->sproingies[1] = BuildLWO(si->wireframe, &LWO_s1_2)))
@@ -789,6 +852,14 @@ InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
 
        if (!(si->SproingieBoom = BuildLWO(si->wireframe, &LWO_s1_b)))
                (void) fprintf(stderr, "BuildLWO - b\n");
+*/
+       si->sproingies[0]=s1_1;
+       si->sproingies[1]=s1_2;
+       si->sproingies[2]=s1_3;
+       si->sproingies[3]=s1_4;
+       si->sproingies[4]=s1_5;
+       si->sproingies[5]=s1_6;
+       si->SproingieBoom=s1_b;
 
        if (si->wireframe) {
                glShadeModel(GL_FLAT);
@@ -820,6 +891,7 @@ InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
        }
 }
 
-#endif
+#endif /* USE_GL */
 
 /* End of sproingies.c */
+