rendered paste bodyIndex: share/config.c
===================================================================
--- share/config.c (.../trunk) (revision 1922)
+++ share/config.c (.../branches/putt-collisions) (revision 1922)
@@ -115,7 +115,6 @@
config_set_s(CONFIG_PLAYER, DEFAULT_PLAYER);
config_set_s(CONFIG_BALL, DEFAULT_BALL);
config_set_s(CONFIG_WIIMOTE_ADDR, DEFAULT_WIIMOTE_ADDR);
- config_set_d(CONFIG_CHEAT, DEFAULT_CHEAT);
config_set_d(CONFIG_STATS, DEFAULT_STATS);
config_set_d(CONFIG_UNIFORM, DEFAULT_UNIFORM);
config_set_d(CONFIG_KEY_FORWARD, DEFAULT_KEY_FORWARD);
@@ -127,6 +126,9 @@
config_set_d(CONFIG_KEY_SCORE_NEXT, DEFAULT_KEY_SCORE_NEXT);
config_set_d(CONFIG_SCREENSHOT, DEFAULT_SCREENSHOT);
config_set_d(CONFIG_LOCK_GOALS, DEFAULT_LOCK_GOALS);
+ config_set_s(CONFIG_BALL_GAMMA, DEFAULT_BALL_GAMMA);
+ config_set_d(CONFIG_BALL_COLLISIONS, DEFAULT_BALL_COLLISIONS);
+ config_set_d(CONFIG_CHEAT, DEFAULT_CHEAT);
}
void config_load(void)
@@ -256,16 +258,22 @@
else if (strcmp(key, "wiimote_addr") == 0)
config_set_s(CONFIG_WIIMOTE_ADDR, val);
- else if (strcmp(key, "cheat") == 0)
- config_set_d(CONFIG_CHEAT, atoi(val));
- else if (strcmp(key, "stats") == 0)
- config_set_d(CONFIG_STATS, atoi(val));
- else if (strcmp(key, "uniform") == 0)
+ else if (strcmp(key, "stats") == 0)
+ config_set_d(CONFIG_STATS, atoi(val));
+ else if (strcmp(key, "uniform") == 0)
config_set_d(CONFIG_UNIFORM, atoi(val));
else if (strcmp(key, "screenshot") == 0)
config_set_d(CONFIG_SCREENSHOT, atoi(val));
else if (strcmp(key, "lock_goals") == 0)
config_set_d(CONFIG_LOCK_GOALS, atoi(val));
+
+ else if (strcmp(key, "gamma") == 0)
+ config_set_s(CONFIG_BALL_GAMMA, val);
+ else if (strcmp(key, "ball_collisions") == 0)
+ config_set_d(CONFIG_BALL_COLLISIONS, atoi(val));
+
+ else if (strcmp(key, "cheat") == 0)
+ config_set_d(CONFIG_CHEAT, atoi(val));
}
fclose(fp);
@@ -388,17 +396,24 @@
SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_SCORE_NEXT]));
if (strlen(option_s[CONFIG_PLAYER]) > 0)
- fprintf(fp, "player %s\n", option_s[CONFIG_PLAYER]);
+ fprintf(fp, "player %s\n", option_s[CONFIG_PLAYER]);
if (strlen(option_s[CONFIG_BALL]) > 0)
- fprintf(fp, "ball_file %s\n", option_s[CONFIG_BALL]);
+ fprintf(fp, "ball_file %s\n", option_s[CONFIG_BALL]);
if (strlen(option_s[CONFIG_WIIMOTE_ADDR]) > 0)
- fprintf(fp, "wiimote_addr %s\n", option_s[CONFIG_WIIMOTE_ADDR]);
+ fprintf(fp, "wiimote_addr %s\n", option_s[CONFIG_WIIMOTE_ADDR]);
fprintf(fp, "stats %d\n", option_d[CONFIG_STATS]);
fprintf(fp, "uniform %d\n", option_d[CONFIG_UNIFORM]);
fprintf(fp, "screenshot %d\n", option_d[CONFIG_SCREENSHOT]);
fprintf(fp, "lock_goals %d\n", option_d[CONFIG_LOCK_GOALS]);
+ if (strlen(option_s[CONFIG_BALL_GAMMA]) > 0)
+ fprintf(fp, "gamma %s\n",
+ option_s[CONFIG_BALL_GAMMA]);
+
+ fprintf(fp, "ball_collisions %d\n",
+ option_d[CONFIG_BALL_COLLISIONS]);
+
if (config_cheat())
fprintf(fp, "cheat %d\n", option_d[CONFIG_CHEAT]);
Index: share/config.h
===================================================================
--- share/config.h (.../trunk) (revision 1922)
+++ share/config.h (.../branches/putt-collisions) (revision 1922)
@@ -86,11 +86,12 @@
CONFIG_KEY_PAUSE,
CONFIG_KEY_RESTART,
CONFIG_KEY_SCORE_NEXT,
- CONFIG_CHEAT,
CONFIG_STATS,
CONFIG_UNIFORM,
CONFIG_SCREENSHOT,
CONFIG_LOCK_GOALS,
+ CONFIG_BALL_COLLISIONS,
+ CONFIG_CHEAT,
CONFIG_OPTION_D_COUNT
};
@@ -99,6 +100,7 @@
CONFIG_PLAYER,
CONFIG_BALL,
CONFIG_WIIMOTE_ADDR,
+ CONFIG_BALL_GAMMA,
CONFIG_OPTION_S_COUNT
};
@@ -115,7 +117,7 @@
#define DEFAULT_REFLECTION 1
#define DEFAULT_MULTISAMPLE 0
#define DEFAULT_MIPMAP 0
-#define DEFAULT_ANISO 0
+#define DEFAULT_ANISO 1
#define DEFAULT_BACKGROUND 1
#define DEFAULT_SHADOW 1
#define DEFAULT_AUDIO_BUFF AUDIO_BUFF_HI
@@ -156,7 +158,6 @@
#define DEFAULT_ROTATE_FAST 200
#define DEFAULT_PLAYER ""
#define DEFAULT_BALL "ball/basic-ball/basic-ball"
-#define DEFAULT_CHEAT 0
#define DEFAULT_KEY_FORWARD SDLK_UP
#define DEFAULT_KEY_BACKWARD SDLK_DOWN
#define DEFAULT_KEY_LEFT SDLK_LEFT
@@ -167,7 +168,10 @@
#define DEFAULT_STATS 0
#define DEFAULT_UNIFORM 0
#define DEFAULT_SCREENSHOT 0
+#define DEFAULT_BALL_GAMMA "0.78"
+#define DEFAULT_BALL_COLLISIONS 0
#define DEFAULT_LOCK_GOALS 0
+#define DEFAULT_CHEAT 0
/*---------------------------------------------------------------------------*/
Index: share/mapc.c
===================================================================
--- share/mapc.c (.../trunk) (revision 1922)
+++ share/mapc.c (.../branches/putt-collisions) (revision 1922)
@@ -61,6 +61,7 @@
#define MAXX 1024
#define MAXR 2048
#define MAXU 1024
+#define MAXY 1024
#define MAXW 1024
#define MAXD 1024
#define MAXA 16384
@@ -153,6 +154,11 @@
return (fp->uc < MAXU) ? fp->uc++ : overflow("ball");
}
+static int incy(struct s_file *fp)
+{
+ return (fp->yc < MAXY) ? fp->yc++ : overflow("ball");
+}
+
static int incw(struct s_file *fp)
{
return (fp->wc < MAXW) ? fp->wc++ : overflow("view");
@@ -186,6 +192,7 @@
fp->xc = 0;
fp->rc = 0;
fp->uc = 0;
+ fp->yc = 0;
fp->wc = 0;
fp->dc = 0;
fp->ac = 0;
@@ -207,6 +214,7 @@
fp->xv = (struct s_swch *) calloc(MAXX, sizeof (struct s_swch));
fp->rv = (struct s_bill *) calloc(MAXR, sizeof (struct s_bill));
fp->uv = (struct s_ball *) calloc(MAXU, sizeof (struct s_ball));
+ fp->yv = (struct s_ball *) calloc(MAXY, sizeof (struct s_ball));
fp->wv = (struct s_view *) calloc(MAXW, sizeof (struct s_view));
fp->dv = (struct s_dict *) calloc(MAXD, sizeof (struct s_dict));
fp->av = (char *) calloc(MAXA, sizeof (char));
@@ -1204,6 +1212,9 @@
up->p[1] = 0.0f;
up->p[2] = 0.0f;
up->r = 0.25f;
+ up->m = 1;
+ up->n = 0;
+ up->c = 0;
for (i = 0; i < c; i++)
{
@@ -1220,11 +1231,65 @@
up->p[1] = +(float) (z - 24) / SCALE;
up->p[2] = -(float) (y) / SCALE;
}
+
+ if (strcmp(k[i], "mobile") == 0)
+ sscanf(v[i], "%d", &up->m);
+
+ if (strcmp(k[i], "return") == 0)
+ sscanf(v[i], "%d", &up->n);
+
+ if (strcmp(k[i], "collisions") == 0)
+ sscanf(v[i], "%d", &up->c);
}
up->p[1] += up->r + SMALL;
}
+static void make_abal(struct s_file *fp,
+ char k[][MAXSTR],
+ char v[][MAXSTR], int c)
+{
+ int i, yi = incy(fp);
+
+ struct s_ball *yp = fp->yv + yi;
+
+ yp->p[0] = 0.0f;
+ yp->p[1] = 0.0f;
+ yp->p[2] = 0.0f;
+ yp->r = 0.25f;
+ yp->m = 1;
+ yp->n = 0;
+ yp->c = 0;
+
+ for (i = 0; i < c; i++)
+ {
+ if (strcmp(k[i], "radius") == 0)
+ sscanf(v[i], "%f", &yp->r);
+
+ if (strcmp(k[i], "origin") == 0)
+ {
+ int x = 0, y = 0, z = 0;
+
+ sscanf(v[i], "%d %d %d", &x, &y, &z);
+
+ yp->p[0] = +(float) (x) / SCALE;
+ yp->p[1] = +(float) (z - 24) / SCALE;
+ yp->p[2] = -(float) (y) / SCALE;
+ }
+
+ if (strcmp(k[i], "mobile") == 0)
+ sscanf(v[i], "%d", &yp->m);
+
+ if (strcmp(k[i], "return") == 0)
+ sscanf(v[i], "%d", &yp->n);
+
+ if (strcmp(k[i], "collisions") == 0)
+ sscanf(v[i], "%d", &yp->c);
+ }
+
+ yp->p[1] += yp->r + SMALL;
+}
+
/*---------------------------------------------------------------------------*/
static void read_ent(struct s_file *fp, FILE *fin)
@@ -1254,6 +1319,7 @@
if (!strcmp(v[i], "info_null")) make_bill(fp, k, v, c);
if (!strcmp(v[i], "path_corner")) make_path(fp, k, v, c);
if (!strcmp(v[i], "info_player_start")) make_ball(fp, k, v, c);
+ if (!strcmp(v[i], "info_notnull")) make_abal(fp, k, v, c);
if (!strcmp(v[i], "info_player_intermission")) make_view(fp, k, v, c);
if (!strcmp(v[i], "info_player_deathmatch")) make_goal(fp, k, v, c);
if (!strcmp(v[i], "target_teleporter")) make_jump(fp, k, v, c);
@@ -2313,10 +2379,10 @@
name, n, m, c,
#endif
name, n, c,
- p->mc, p->vc, p->ec, p->sc, p->tc,
- p->gc, p->lc, p->pc, p->nc, p->bc,
- p->hc, p->zc, p->wc, p->jc, p->xc,
- p->rc, p->uc, p->ac, p->dc, p->ic);
+ p->mc, p->vc, p->ec, p->sc, p->tc,
+ p->gc, p->lc, p->pc, p->nc, p->bc,
+ p->hc, p->zc, p->wc, p->jc, p->xc,
+ p->rc, p->uc + p->yc, p->ac, p->dc, p->ic);
}
int main(int argc, char *argv[])
@@ -2370,4 +2436,3 @@
return 0;
}
-
Index: share/solid.c
===================================================================
--- share/solid.c (.../trunk) (revision 1922)
+++ share/solid.c (.../branches/putt-collisions) (revision 1922)
@@ -24,15 +24,20 @@
#include "solid.h"
#include "base_config.h"
#include "binary.h"
+#include "config.h"
#define MAGIC 0x4c4f53af
-#define SOL_VERSION 6
+#define SOL_VERSION 7
#define LARGE 1.0e+5f
#define SMALL 1.0e-3f
/*---------------------------------------------------------------------------*/
+static int amplitude = 0.f;
+
+/*---------------------------------------------------------------------------*/
+
static float erp(float t)
{
return 3.0f * t * t - 2.0f * t * t * t;
@@ -236,7 +241,12 @@
{
get_array(fin, bp->p, 3);
get_float(fin, &bp->r);
+ get_index(fin, &bp->m);
+ get_index(fin, &bp->n);
+ get_index(fin, &bp->c);
+ v_cpy(bp->O, bp->p);
+
bp->e[0][0] = bp->E[0][0] = 1.0f;
bp->e[0][1] = bp->E[0][1] = 0.0f;
bp->e[0][2] = bp->E[0][2] = 0.0f;
@@ -292,6 +302,7 @@
get_index(fin, &fp->xc);
get_index(fin, &fp->rc);
get_index(fin, &fp->uc);
+ get_index(fin, &fp->yc);
get_index(fin, &fp->wc);
get_index(fin, &fp->ic);
@@ -329,6 +340,8 @@
fp->rv = (struct s_bill *) calloc(fp->rc, sizeof (struct s_bill));
if (fp->uc)
fp->uv = (struct s_ball *) calloc(fp->uc, sizeof (struct s_ball));
+ if (fp->yc)
+ fp->yv = (struct s_ball *) calloc(fp->yc, sizeof (struct s_ball));
if (fp->wc)
fp->wv = (struct s_view *) calloc(fp->wc, sizeof (struct s_view));
if (fp->dc)
@@ -356,6 +369,7 @@
for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
+ for (i = 0; i < fp->yc; i++) sol_load_ball(fin, fp->yv + i);
for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
for (i = 0; i < fp->ic; i++) get_index(fin, fp->iv + i);
@@ -393,10 +407,11 @@
get_index(fin, &fp->xc);
get_index(fin, &fp->rc);
get_index(fin, &fp->uc);
+ get_index(fin, &fp->yc);
get_index(fin, &fp->wc);
get_index(fin, &fp->ic);
#endif
- fseek(fin, 18 * 4, SEEK_CUR);
+ fseek(fin, 19 * 4, SEEK_CUR);
if (fp->ac)
{
@@ -584,6 +599,9 @@
{
put_array(fout, bp->p, 3);
put_float(fout, &bp->r);
+ put_index(fout, &bp->m);
+ put_index(fout, &bp->n);
+ put_index(fout, &bp->c);
}
static void sol_stor_view(FILE *fout, struct s_view *wp)
@@ -625,6 +643,7 @@
put_index(fin, &fp->xc);
put_index(fin, &fp->rc);
put_index(fin, &fp->uc);
+ put_index(fin, &fp->yc);
put_index(fin, &fp->wc);
put_index(fin, &fp->ic);
@@ -647,6 +666,7 @@
for (i = 0; i < fp->xc; i++) sol_stor_swch(fin, fp->xv + i);
for (i = 0; i < fp->rc; i++) sol_stor_bill(fin, fp->rv + i);
for (i = 0; i < fp->uc; i++) sol_stor_ball(fin, fp->uv + i);
+ for (i = 0; i < fp->yc; i++) sol_stor_ball(fin, fp->yv + i);
for (i = 0; i < fp->wc; i++) sol_stor_view(fin, fp->wv + i);
for (i = 0; i < fp->ic; i++) put_index(fin, fp->iv + i);
}
@@ -686,6 +706,7 @@
if (fp->xv) free(fp->xv);
if (fp->rv) free(fp->rv);
if (fp->uv) free(fp->uv);
+ if (fp->yv) free(fp->yv);
if (fp->wv) free(fp->wv);
if (fp->dv) free(fp->dv);
if (fp->iv) free(fp->iv);
@@ -914,11 +935,132 @@
v_mad(p, q, n, up->r);
/* Return the "energy" of the impact, to determine the sound amplitude. */
-
return fabsf(v_dot(n, d));
}
/*
+ * Compute the new linear velocities of two colliding balls.
+ * t gives the time after which they collide.
+ */
+static float sol_bounce_ball(struct s_ball *up,
+ struct s_ball *u2p,
+ const float t)
+{
+ float r_rel[3], v_rel[3], v1_par[3], v1_perp[3], v2_par[3], v2_perp[3],
+ u[3];
+ float v11[3], v12[3], v21[3], v22[3];
+ float *p1 = up->p, *v1 = up->v, *p2 = u2p->p, *v2 = u2p->v;
+ float inertia, factor, gamma;
+ const int u1 = up->m;
+ const int u2 = u2p->m;
+
+ {
+ char gamma_str[MAXNAM];
+ config_get_s(CONFIG_BALL_GAMMA, gamma_str, MAXNAM);
+ gamma = atof(gamma_str);
+ }
+
+ /* Correct positions up to the collision */
+ v_mad(p1, p1, v1, t);
+ v_mad(p2, p2, v2, t);
+
+ /* Floating point precision */
+ if (!(p1[1] - p2[1] > 0.001f ) && !(p2[1] - p1[1] > 0.001f))
+ {
+ if (p1[1] > p2[1])
+ p2[1] = p1[1];
+ else
+ p1[1] = p2[1];
+ }
+
+ /* Hack: prevent losing balls */
+ v_sub(v_rel, v2, v1);
+ if (v_len(v_rel) < 0.001f)
+ {
+ return 0.0f;
+ }
+
+ /* r_rel is the unit vector from p1 to p2 */
+ v_sub(r_rel, p2, p1);
+ v_nrm(r_rel, r_rel);
+
+ /*
+ * project velocities upon r_rel to get components parallel
+ * to r_rel - only these will be changed in the collision
+ */
+ factor = v_dot(v1, r_rel);
+ v_scl(v1_par, r_rel, factor);
+ v_sub(v1_perp, v1, v1_par);
+
+ factor = v_dot(v2, r_rel);
+ v_scl(v2_par, r_rel, factor);
+ v_sub(v2_perp, v2, v2_par);
+
+ /* u is used to calculate the "energy" of the impact */
+ v_sub(u, v2_par, v1_par);
+
+ /* Ensure immobile balls don't travel inside of each other */
+ if (!up->m || !u2p->m)
+ gamma = 0.78f;
+
+ /*
+ * New parallel velocities follow from momentum conservation,
+ * coefficient of restitution GAMMA, mass ratio inertia
+ */
+ inertia = pow(up->r / u2p->r, 3);
+
+ if (!u2p->m)
+ {
+ v_scl(v11, v1_par, -gamma);
+ v_scl(v12, v2_par, gamma + 1.0f);
+ v_add(v1_par, v11, v12);
+ }
+
+ else if (!up->m)
+ {
+ v_scl(v21, v1_par, gamma + 1.0f);
+ v_scl(v22, v2_par, -gamma);
+ v_add(v2_par, v21, v22);
+ }
+
+ else
+ {
+ v_scl(v11, v1_par, (inertia - gamma) / (inertia + 1.0f));
+ v_scl(v12, v1_par, (gamma + 1.0f) * inertia / (inertia + 1.0f));
+ v_scl(v21, v2_par, (gamma + 1.0f) / (inertia + 1.0f));
+ v_scl(v22, v2_par, (1.0f - gamma * inertia) / (inertia + 1.0f));
+ v_add(v1_par, v11, v21);
+ v_add(v2_par, v12, v22);
+ }
+
+ if (up->m)
+ v_add(v1, v1_par, v1_perp);
+ if (u2p->m)
+ v_add(v2, v2_par, v2_perp);
+
+ /* Hack: prevent accidental spinning while the ball is stationary */
+ if (v_len(v1) < 0.01f && u1)
+ {
+ up->w[0] = 0.0f;
+ up->w[1] = 0.0f;
+ up->w[2] = 0.0f;
+ }
+
+ if (v_len(v2) < 0.01f && u2)
+ {
+ u2p->w[0] = 0.0f;
+ u2p->w[1] = 0.0f;
+ u2p->w[2] = 0.0f;
+ }
+
+ /*
+ * Return the length of the relative velocity parallel
+ * to the line of impact
+ */
+ return fabsf(v_len(u));
+}
+
+/*
* Compute the new angular velocity and orientation of a ball pendulum.
* A gives the accelleration of the ball. G gives the gravity vector.
*/
@@ -1039,6 +1181,18 @@
{
int i;
+ for (i = 0; i < fp->yc; i++)
+ {
+ struct s_ball *yp = fp->yv + i;
+
+ if (!yp->m)
+ continue;
+
+ v_mad(yp->p, yp->p, yp->v, dt);
+
+ sol_rotate(yp->e, yp->w, dt);
+ }
+
for (i = 0; i < fp->uc; i++)
{
struct s_ball *up = fp->uv + i;
@@ -1061,6 +1215,27 @@
return v_vert(T, o, vp->p, w, up->p, up->v, up->r);
}
+/*---------------------------------------------------------------------------*/
+
+static float sol_test_sphere_inter(const struct s_ball *up,
+ const struct s_ball *u2p)
+{
+ float P[3], V[3];
+ float t = LARGE;
+
+ v_sub(P, up->p, u2p->p);
+ v_sub(V, up->v, u2p->v);
+
+ if (v_dot(P, V) < 0.0f)
+ {
+ t = v_sol(P, V, up->r + u2p->r);
+ }
+
+ return (t > LARGE) ? (LARGE) : (t);
+}
+
+/*---------------------------------------------------------------------------*/
+
static float sol_test_edge(float dt,
float T[3],
const struct s_ball *up,
@@ -1181,7 +1356,7 @@
{
float U[3] = {0.0f, 0.0f, 0.0f}; /* init value only to avoid gcc warnings */
float u, t = dt;
- int i;
+ int i;
/* Short circuit a non-solid lump. */
@@ -1302,9 +1477,70 @@
v_cpy(V, W);
t = u;
}
+
return t;
}
+static float sol_test_balls(float dt, const struct s_file *fp)
+{
+ float t = 0.0f;
+ int i, j;
+
+ for (i = 0; i < fp->yc; i++)
+ {
+ struct s_ball *yp = fp->yv + i;
+
+ for (j = i + 1; j < fp->yc; j++)
+ {
+ struct s_ball *y2p = fp->yv + j;
+
+ if (!(yp->r > 0.0f || y2p->r > 0.0f))
+ continue;
+
+ if (sol_test_sphere_inter(yp, y2p) < dt)
+ {
+ t = sol_bounce_ball(yp, y2p, t);
+ }
+ }
+ }
+
+ for (i = 0; i < fp->uc; i++)
+ {
+ struct s_ball *up = fp->uv + i;
+
+ if (i > 0 && !up->P)
+ continue;
+
+ for (j = 0; j < fp->yc; j++)
+ {
+ struct s_ball *y2p = fp->yv + j;
+
+ if (!(up->r > 0.0f || y2p->r > 0.0f))
+ continue;
+
+ if (sol_test_sphere_inter(up, y2p) < dt)
+ {
+ t = sol_bounce_ball(up, y2p, t);
+ }
+ }
+
+ for (j = i + 1; config_get_d(CONFIG_BALL_COLLISIONS) && j < fp->uc; j++)
+ {
+ struct s_ball *u2p = fp->uv + j;
+
+ if (!(up->r > 0.0f || u2p->r > 0.0f))
+ continue;
+
+ if (u2p->P && up->P && sol_test_sphere_inter(up, u2p) < dt)
+ {
+ t = sol_bounce_ball(up, u2p, t);
+ }
+ }
+ }
+
+ return t;
+}
+
static float sol_test_file(float dt,
float T[3], float V[3],
const struct s_ball *up,
@@ -1324,6 +1560,12 @@
t = u;
}
}
+
+ if ((u = sol_test_balls(t, fp)) > 0.0f)
+ amplitude = u;
+ else
+ amplitude = 0.f;
+
return t;
}
@@ -1339,80 +1581,177 @@
float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
{
- float P[3], V[3], v[3], r[3], a[3], d, e, nt, b = 0.0f, tt = dt;
- int c = 16;
+ float b = 0.0f, nt = 0.0f;
+ int i, c = 16;
- if (ui < fp->uc)
+ /*
+ * The user ball loop
+ */
+ for (i = 0; (config_get_d(CONFIG_BALL_COLLISIONS) && i < fp->uc) ||
+ (!config_get_d(CONFIG_BALL_COLLISIONS) && i < 4 + 1); i++)
{
- struct s_ball *up = fp->uv + ui;
+ float P[3], V[3], v[3], r[3], a[3], d, e, tt = dt;
- /* If the ball is in contact with a surface, apply friction. */
+ if (i < fp->uc)
+ {
+ struct s_ball *up = fp->uv + i;
- v_cpy(a, up->v);
- v_cpy(v, up->v);
- v_cpy(up->v, g);
+ /* If the ball is in contact with a surface, apply friction. */
- if (m && sol_test_file(tt, P, V, up, fp) < 0.0005f)
- {
- v_cpy(up->v, v);
- v_sub(r, P, up->p);
+ v_cpy(a, up->v);
+ v_cpy(v, up->v);
+ v_cpy(up->v, g);
- if ((d = v_dot(r, g) / (v_len(r) * v_len(g))) > 0.999f)
+ if (m && sol_test_file(tt, P, V, up, fp) < 0.0005f)
{
- if ((e = (v_len(up->v) - dt)) > 0.0f)
+ v_cpy(up->v, v);
+ v_sub(r, P, up->p);
+
+ if ((d = v_dot(r, g) / (v_len(r) * v_len(g))) > 0.999f)
{
- /* Scale the linear velocity. */
+ if ((e = (v_len(up->v) - dt)) > 0.0f)
+ {
+ /* Scale the linear velocity. */
- v_nrm(up->v, up->v);
- v_scl(up->v, up->v, e);
+ v_nrm(up->v, up->v);
+ v_scl(up->v, up->v, e);
- /* Scale the angular velocity. */
+ /* Scale the angular velocity. */
- v_sub(v, V, up->v);
- v_crs(up->w, v, r);
- v_scl(up->w, up->w, -1.0f / (up->r * up->r));
- }
- else
- {
- /* Friction has brought the ball to a stop. */
+ v_sub(v, V, up->v);
+ v_crs(up->w, v, r);
+ v_scl(up->w, up->w, -1.0f / (up->r * up->r));
+ }
+ else
+ {
+ /* Friction has brought the ball to a stop. */
- up->v[0] = 0.0f;
- up->v[1] = 0.0f;
- up->v[2] = 0.0f;
+ up->v[0] = 0.0f;
+ up->v[1] = 0.0f;
+ up->v[2] = 0.0f;
- (*m)++;
+ if(i == ui)
+ (*m)++;
+ }
}
+ else v_mad(up->v, v, g, tt);
}
else v_mad(up->v, v, g, tt);
+
+ /* Test for collision. */
+
+ while (tt && tt > (nt = sol_test_file(tt, P, V, up, fp)) && c > 0)
+ {
+ sol_body_step(fp, nt);
+ sol_swch_step(fp, nt);
+ sol_ball_step(fp, nt);
+
+ tt -= nt;
+
+ if (b < ((d = sol_bounce(up, P, V, nt))))
+ b = d;
+
+ c--;
+ }
+
+ if (b < amplitude)
+ b = amplitude;
+
+ /* Apply the ball's accelleration to the pendulum. */
+
+ v_sub(a, up->v, a);
+
+ sol_pendulum(up, a, g, dt);
}
- else v_mad(up->v, v, g, tt);
+ }
- /* Test for collision. */
+ /*
+ * The arbitrary balls loop
+ */
+ for (i = 0; i < fp->yc; i++)
+ {
+ float P[3], V[3], v[3], r[3], a[3], d, e, tt = dt;
- while (c > 0 && tt > 0 && tt > (nt = sol_test_file(tt, P, V, up, fp)))
+ if (i < fp->yc)
{
- sol_body_step(fp, nt);
- sol_swch_step(fp, nt);
- sol_ball_step(fp, nt);
+ struct s_ball *yp = fp->yv + i;
- tt -= nt;
+ if ((!yp->m) || (!config_get_d(CONFIG_BALL_COLLISIONS) && yp->c))
+ continue;
- if (b < (d = sol_bounce(up, P, V, nt)))
- b = d;
+ /* If the ball is in contact with a surface, apply friction. */
- c--;
- }
+ v_cpy(a, yp->v);
+ v_cpy(v, yp->v);
+ v_cpy(yp->v, g);
- sol_body_step(fp, tt);
- sol_swch_step(fp, tt);
- sol_ball_step(fp, tt);
+ if (m && sol_test_file(tt, P, V, yp, fp) < 0.0005f)
+ {
+ v_cpy(yp->v, v);
+ v_sub(r, P, yp->p);
- /* Apply the ball's accelleration to the pendulum. */
+ if ((d = v_dot(r, g) / (v_len(r) * v_len(g))) > 0.999f)
+ {
+ if ((e = (v_len(yp->v) - dt)) > 0.0f)
+ {
+ /* Scale the linear velocity. */
- v_sub(a, up->v, a);
+ v_nrm(yp->v, yp->v);
+ v_scl(yp->v, yp->v, e);
- sol_pendulum(up, a, g, dt);
+ /* Scale the angular velocity. */
+
+ v_sub(v, V, yp->v);
+ v_crs(yp->w, v, r);
+ v_scl(yp->w, yp->w, -1.0f / (yp->r * yp->r));
+ }
+ else
+ {
+ /* Friction has brought the ball to a stop. */
+
+ yp->v[0] = 0.0f;
+ yp->v[1] = 0.0f;
+ yp->v[2] = 0.0f;
+ }
+ }
+ else v_mad(yp->v, v, g, tt);
+ }
+ else v_mad(yp->v, v, g, tt);
+
+ /* Test for collision. */
+
+ while (tt && tt > (nt = sol_test_file(tt, P, V, yp, fp)) && c > 0)
+ {
+ sol_body_step(fp, nt);
+ sol_swch_step(fp, nt);
+ sol_ball_step(fp, nt);
+
+ tt -= nt;
+
+ if (b < ((d = sol_bounce(yp, P, V, nt))))
+ b = d;
+
+ c--;
+ }
+
+ if (b < amplitude)
+ b = amplitude;
+
+ /* Apply the ball's accelleration to the pendulum. */
+
+ v_sub(a, yp->v, a);
+
+ sol_pendulum(yp, a, g, dt);
+ }
}
+
+ if (!c && !ui)
+ nt += dt;
+
+ sol_body_step(fp, nt);
+ sol_swch_step(fp, nt);
+ sol_ball_step(fp, nt);
+
return b;
}
@@ -1420,13 +1759,13 @@
struct s_item *sol_item_test(struct s_file *fp, float *p, float item_r)
{
- const float *ball_p = fp->uv->p;
- const float ball_r = fp->uv->r;
+ int hi, yi;
- int hi;
-
for (hi = 0; hi < fp->hc; hi++)
{
+ const float *ball_p = fp->uv->p;
+ const float ball_r = fp->uv->r;
+
float r[3];
r[0] = ball_p[0] - fp->hv[hi].p[0];
@@ -1441,36 +1780,110 @@
return &fp->hv[hi];
}
+
+ for (yi = 0; yi < fp->yc; yi++)
+ {
+ const float *ball_p = fp->yv[yi].p;
+ const float ball_r = fp->yv[yi].r;
+
+ float r[3];
+
+ r[0] = ball_p[0] - fp->hv[hi].p[0];
+ r[1] = ball_p[1] - fp->hv[hi].p[1];
+ r[2] = ball_p[2] - fp->hv[hi].p[2];
+
+ if (fp->hv[hi].t != ITEM_NONE && v_len(r) < ball_r + item_r)
+ {
+ p[0] = fp->hv[hi].p[0];
+ p[1] = fp->hv[hi].p[1];
+ p[2] = fp->hv[hi].p[2];
+
+ return &fp->hv[hi];
+ }
+ }
}
+
return NULL;
}
-struct s_goal *sol_goal_test(struct s_file *fp, float *p, int ui)
+int sol_goal_test(struct s_file *fp, float *p, int ui)
{
- const float *ball_p = fp->uv[ui].p;
- const float ball_r = fp->uv[ui].r;
- int zi;
-
- for (zi = 0; zi < fp->zc; zi++)
+ if (config_get_d(CONFIG_BALL_COLLISIONS) && ui)
{
- float r[3];
+ const float *ball_p = fp->uv[ui].p;
+ const float ball_r = fp->uv[ui].r;
+ float z[3] = {0.0f, 0.0f, 0.0f};
+ int zi, i;
- r[0] = ball_p[0] - fp->zv[zi].p[0];
- r[1] = ball_p[2] - fp->zv[zi].p[2];
- r[2] = 0;
+ for (i = 1; i < fp->uc; i++)
+ {
+ if(fp->uv[i].p[1] < -199.9f)
+ v_cpy(fp->uv[i].v, z);
+ if (v_len(fp->uv[i].v) > 0.0f)
+ return 0;
+ else
+ v_cpy(fp->uv[i].v, z);
+ }
- if (v_len(r) < fp->zv[zi].r * 1.1 - ball_r &&
- ball_p[1] > fp->zv[zi].p[1] &&
- ball_p[1] < fp->zv[zi].p[1] + GOAL_HEIGHT / 2)
+ for (i = 0; i < fp->yc; i++)
{
- p[0] = fp->zv[zi].p[0];
- p[1] = fp->zv[zi].p[1];
- p[2] = fp->zv[zi].p[2];
+ if(fp->yv[i].p[1] < -199.9f)
+ v_cpy(fp->yv[i].v, z);
+ if (v_len(fp->yv[i].v) > 0.0f)
+ return 0;
+ else
+ v_cpy(fp->yv[i].v, z);
+ }
- return &fp->zv[zi];
+ for (zi = 0; zi < fp->zc; zi++)
+ {
+ float r[3];
+
+ r[0] = ball_p[0] - fp->zv[zi].p[0];
+ r[1] = ball_p[2] - fp->zv[zi].p[2];
+ r[2] = 0;
+
+ if (v_len(r) < fp->zv[zi].r * 1.1 - ball_r &&
+ ball_p[1] > fp->zv[zi].p[1] &&
+ ball_p[1] < fp->zv[zi].p[1] + GOAL_HEIGHT / 2)
+ {
+ p[0] = fp->zv[zi].p[0];
+ p[1] = -200.0f;
+ p[2] = fp->zv[zi].p[2];
+
+ return 2;
+ }
}
+ return 1;
}
- return NULL;
+
+ else
+ {
+ const float *ball_p = fp->uv[ui].p;
+ const float ball_r = fp->uv[ui].r;
+ int zi;
+
+ for (zi = 0; zi < fp->zc; zi++)
+ {
+ float r[3];
+
+ r[0] = ball_p[0] - fp->zv[zi].p[0];
+ r[1] = ball_p[2] - fp->zv[zi].p[2];
+ r[2] = 0;
+
+ if (v_len(r) < fp->zv[zi].r * 1.1 - ball_r &&
+ ball_p[1] > fp->zv[zi].p[1] &&
+ ball_p[1] < fp->zv[zi].p[1] + GOAL_HEIGHT / 2)
+ {
+ p[0] = fp->zv[zi].p[0];
+ p[1] = -200.0f;
+ p[2] = fp->zv[zi].p[2];
+
+ return 1;
+ }
+ }
+ return 0;
+ }
}
/*
@@ -1519,75 +1932,145 @@
* a visible switch is activated, return 0 otherwise (no switch is
* activated or only invisible switches).
*/
-int sol_swch_test(struct s_file *fp, int ui)
+int sol_swch_test(struct s_file *fp)
{
- const float *ball_p = fp->uv[ui].p;
- const float ball_r = fp->uv[ui].r;
- int xi;
- int res = 0;
+ int xi, i, res = 0;
for (xi = 0; xi < fp->xc; xi++)
{
struct s_swch *xp = fp->xv + xi;
- if (xp->t0 == 0 || xp->f == xp->f0)
+ for (i = 0; i < fp->uc; i++)
{
- float l;
- float r[3];
+ float l, r[3];
- r[0] = ball_p[0] - xp->p[0];
- r[1] = ball_p[2] - xp->p[2];
- r[2] = 0;
+ const float *ball_p = fp->uv[i].p;
+ const float ball_r = fp->uv[i].r;
- l = v_len(r) - xp->r;
+ if (xp->t0 == 0 || xp->f == xp->f0)
+ {
+ r[0] = ball_p[0] - xp->p[0];
+ r[1] = ball_p[2] - xp->p[2];
+ r[2] = 0;
- if (l < ball_r &&
- ball_p[1] > xp->p[1] &&
- ball_p[1] < xp->p[1] + SWCH_HEIGHT / 2)
- {
- if (!xp->e && l < - ball_r)
+ l = v_len(r) - xp->r;
+
+ if (l < ball_r &&
+ ball_p[1] > xp->p[1] &&
+ ball_p[1] < xp->p[1] + SWCH_HEIGHT / 2)
{
- int pi = xp->pi;
- int pj = xp->pi;
+ if (!xp->e && l < -ball_r)
+ {
+ int pi = xp->pi;
+ int pj = xp->pi;
- /* The ball enters. */
+ xp->b = i * 2;
- if (xp->t0 == 0)
- xp->e = 1;
+ /* The ball enters. */
- /* Toggle the state, update the path. */
+ if (xp->t0 == 0)
+ xp->e = 1;
- xp->f = xp->f ? 0 : 1;
+ /* Toggle the state, update the path. */
- do /* Tortoise and hare cycle traverser. */
- {
- fp->pv[pi].f = xp->f;
- fp->pv[pj].f = xp->f;
+ xp->f = xp->f ? 0 : 1;
- pi = fp->pv[pi].pi;
- pj = fp->pv[pj].pi;
- pj = fp->pv[pj].pi;
- }
- while (pi != pj);
+ do /* Tortoise and hare cycle traverser. */
+ {
+ fp->pv[pi].f = xp->f;
+ fp->pv[pj].f = xp->f;
- /* It toggled to non-default state, start the timer. */
+ pi = fp->pv[pi].pi;
+ pj = fp->pv[pj].pi;
+ pj = fp->pv[pj].pi;
+ }
+ while (pi != pj);
- if (xp->f != xp->f0)
- xp->t = xp->t0;
+ /* It toggled to non-default state, start the timer. */
- /* If visible, set the result. */
+ if (xp->f != xp->f0)
+ xp->t = xp->t0;
- if (!xp->i)
- res = 1;
+ /* If visible, set the result. */
+
+ if (!xp->i)
+ res = 1;
+ }
}
+
+ /* The ball exits. */
+
+ else if (xp->e && xp->b == i * 2)
+ xp->e = 0;
}
+ }
- /* The ball exits. */
+ for (i = 0; i < fp->yc; i++)
+ {
+ float l, r[3];
- else if (xp->e)
- xp->e = 0;
+ const float *ball_p = fp->yv[i].p;
+ const float ball_r = fp->yv[i].r;
+
+ if (xp->t0 == 0 || xp->f == xp->f0)
+ {
+ r[0] = ball_p[0] - xp->p[0];
+ r[1] = ball_p[2] - xp->p[2];
+ r[2] = 0;
+
+ l = v_len(r) - xp->r;
+
+ if (l < ball_r &&
+ ball_p[1] > xp->p[1] &&
+ ball_p[1] < xp->p[1] + SWCH_HEIGHT / 2)
+ {
+ if (!xp->e && l < -ball_r)
+ {
+ int pi = xp->pi;
+ int pj = xp->pi;
+
+ xp->b = i * 2 + 1;
+
+ /* The ball enters. */
+
+ if (xp->t0 == 0)
+ xp->e = 1;
+
+ /* Toggle the state, update the path. */
+
+ xp->f = xp->f ? 0 : 1;
+
+ do /* Tortoise and hare cycle traverser. */
+ {
+ fp->pv[pi].f = xp->f;
+ fp->pv[pj].f = xp->f;
+
+ pi = fp->pv[pi].pi;
+ pj = fp->pv[pj].pi;
+ pj = fp->pv[pj].pi;
+ }
+ while (pi != pj);
+
+ /* It toggled to non-default state, start the timer. */
+
+ if (xp->f != xp->f0)
+ xp->t = xp->t0;
+
+ /* If visible, set the result. */
+
+ if (!xp->i)
+ res = 1;
+ }
+ }
+
+ /* The ball exits. */
+
+ else if (xp->e && xp->b == i * 2 + 1)
+ xp->e = 0;
+ }
}
}
+
return res;
}
@@ -1616,4 +2099,3 @@
}
/*---------------------------------------------------------------------------*/
-
Index: share/solid.h
===================================================================
--- share/solid.h (.../trunk) (revision 1922)
+++ share/solid.h (.../branches/putt-collisions) (revision 1922)
@@ -32,27 +32,29 @@
*
* The Xs are as documented by struct s_file:
*
- * f File (struct s_file)
- * m Material (struct s_mtrl)
- * v Vertex (struct s_vert)
- * e Edge (struct s_edge)
- * s Side (struct s_side)
- * t Texture coord (struct s_texc)
- * g Geometry (struct s_geom)
- * l Lump (struct s_lump)
- * n Node (struct s_node)
- * p Path (struct s_path)
- * b Body (struct s_body)
- * h Item (struct s_item)
- * z Goal (struct s_goal)
- * j Jump (struct s_jump)
- * x Switch (struct s_swch)
- * r Billboard (struct s_bill)
- * u User (struct s_ball)
- * w Viewpoint (struct s_view)
- * d Dictionary (struct s_dict)
- * i Index (int)
- * a Text (char)
+ * f File (struct s_file)
+ * m Material (struct s_mtrl)
+ * v Vertex (struct s_vert)
+ * e Edge (struct s_edge)
+ * s Side (struct s_side)
+ * t Texture coord (struct s_texc)
+ * g Geometry (struct s_geom)
+ * l Lump (struct s_lump)
+ * n Node (struct s_node)
+ * p Path (struct s_path)
+ * b Body (struct s_body)
+ * h Item (struct s_item)
+ * z Goal (struct s_goal)
+ * j Jump (struct s_jump)
+ * x Switch (struct s_swch)
+ * r Billboard (struct s_bill)
+ * u User (struct s_ball)
+ * y Arbitrary ball (struct s_ball)
+ * w Viewpoint (struct s_view)
+ * d Dictionary (struct s_dict)
+ * i Index (int)
+ * a Text (char)
+
*
* The Ys are as follows:
*
@@ -72,7 +74,7 @@
* Those members that do not conform to this convention are explicitly
* documented with a comment.
*
- * These prefixes are still available: c k o q y.
+ * These prefixes are still available: c k o q.
*/
/*---------------------------------------------------------------------------*/
@@ -223,6 +225,7 @@
int f; /* current state */
int i; /* is invisible? */
int e; /* is a ball inside it? */
+ int b; /* which ball? */
};
struct s_bill
@@ -258,6 +261,11 @@
float E[3][3]; /* basis of pendulum */
float W[3]; /* angular pendulum velocity */
float r; /* radius */
+ int P; /* ball in play state */
+ int m; /* is ball mobile? */
+ int n; /* return on fall-out flag */
+ int c; /* exists only when BCis set? */
+ float O[3]; /* original position */
};
struct s_view
@@ -274,26 +282,27 @@
struct s_file
{
- int ac;
- int mc;
- int vc;
- int ec;
- int sc;
- int tc;
- int gc;
- int lc;
- int nc;
- int pc;
- int bc;
- int hc;
- int zc;
- int jc;
- int xc;
- int rc;
- int uc;
- int wc;
- int dc;
- int ic;
+ int ac;
+ int mc;
+ int vc;
+ int ec;
+ int sc;
+ int tc;
+ int gc;
+ int lc;
+ int nc;
+ int pc;
+ int bc;
+ int hc;
+ int zc;
+ int jc;
+ int xc;
+ int rc;
+ int uc;
+ int wc;
+ int dc;
+ int ic;
+ int yc;
char *av;
struct s_mtrl *mv;
@@ -312,6 +321,7 @@
struct s_swch *xv;
struct s_bill *rv;
struct s_ball *uv;
+ struct s_ball *yv;
struct s_view *wv;
struct s_dict *dv;
int *iv;
@@ -331,9 +341,9 @@
float sol_step(struct s_file *, const float *, float, int, int *);
int sol_jump_test(struct s_file *, float *, int);
-int sol_swch_test(struct s_file *, int);
+int sol_swch_test(struct s_file *);
+int sol_goal_test(struct s_file *, float *, int);
-struct s_goal *sol_goal_test(struct s_file *, float *, int);
struct s_item *sol_item_test(struct s_file *, float *, float);
/*---------------------------------------------------------------------------*/
Index: doc/AUTHORS
===================================================================
--- doc/AUTHORS (.../trunk) (revision 1922)
+++ doc/AUTHORS (.../branches/putt-collisions) (revision 1922)
@@ -17,6 +17,7 @@
Mehdi Yousfi-Monod (mym)
Michael Middleton (slippifishi)
Florian Priester
+ Byron James Johnson (Krabby Krap)
* TRANSLATORS
@@ -63,6 +64,7 @@
- Feature ideas and testing
Byron James Johnson
- Platform acceleration toggle
+ - Neverputt ball vs. ball collision
Laurent Moussault (Lorant)
- Menu navigation improvements
- Layout improvements in several screens
@@ -82,6 +84,8 @@
- Map compiler speed-ups for debugging large maps
Uoti Urpala
- Bounces with moving objects
+ Georg Wachter
+ - Generic sphere-vs-sphere collision
Mehdi Yousfi-Monod
- Neverball Hall of Fame management
- Windows packaging
Index: doc/MANUAL
===================================================================
--- doc/MANUAL (.../trunk) (revision 1922)
+++ doc/MANUAL (.../branches/putt-collisions) (revision 1922)
@@ -222,6 +222,20 @@
Joystick exit button
+ gamma 0.78
+ gamma gives the Coefficient of restitution of a sphere-sphere
+ collision. Its square gives the fraction of kinetic energy
+ (in the center-of-mass system) that will be conserved in the
+ collision, so possible values range from 0 (completely
+ inelastic) to 1 (completely elastic) collision. Values greater
+ than 1 mean that in each collision, extra energy is generated.
+ putt_collisions 0
+
+ This key allows balls to collide with other balls in
+ Neverputt.
+
+
+
Contact: <robert.kooima@gmail.com>
Index: data/map-ckk/17.map
===================================================================
--- data/map-ckk/17.map (.../trunk) (revision 1922)
+++ data/map-ckk/17.map (.../branches/putt-collisions) (revision 1922)
@@ -3950,3 +3950,39 @@
( -112 -800 464 ) ( -128 -800 464 ) ( -128 -928 464 ) mtrl/turf-grey 128 128 0 0.5 0.5 0 0 0
}
}
+// entity 96
+{
+"classname" "info_notnull"
+"origin" "-48 6848 96"
+"radius" "0.0625"
+"collisions" "1"
+"return" "1"
+"mobile" "1"
+}
+// entity 97
+{
+"classname" "info_notnull"
+"origin" "48 6848 96"
+"radius" "0.0625"
+"collisions" "1"
+"return" "1"
+"mobile" "1"
+}
+// entity 98
+{
+"classname" "info_notnull"
+"origin" "32 6848 96"
+"radius" "0.0625"
+"collisions" "1"
+"return" "1"
+"mobile" "1"
+}
+// entity 99
+{
+"classname" "info_notnull"
+"origin" "-32 6848 96"
+"radius" "0.0625"
+"collisions" "1"
+"return" "1"
+"mobile" "1"
+}
Index: data/set-misc.txt
===================================================================
--- data/set-misc.txt (.../trunk) (revision 1922)
+++ data/set-misc.txt (.../branches/putt-collisions) (revision 1922)
@@ -17,3 +17,4 @@
map-misc/hurdles.sol
map-misc/canals.sol
map-misc/groweasy.sol
+map-misc/arbitrary_demo.sol
Index: data/shot-misc/arbitrary_demo.jpg
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: data/shot-misc/arbitrary_demo.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Index: data/ball/eyeball.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: data/map-misc/arbitrary_demo.map
===================================================================
--- data/map-misc/arbitrary_demo.map (.../trunk) (revision 0)
+++ data/map-misc/arbitrary_demo.map (.../branches/putt-collisions) (revision 1922)
@@ -0,0 +1,582 @@
+
+// entity 0
+{
+"classname" "worldspawn"
+"levelname" "billiard"
+"version" "1.0"
+"author" "Byron James Johnson (Krabby Krap)"
+"shot" "shot-misc/arbitrary_demo.jpg"
+"back" "map-back/clouds.sol"
+"grad" "back/land.png"
+"song" "bgm/track2.ogg"
+"time" "12000"
+"goal" "2"
+"time_hs" "7500 8000"
+"coin_hs" "16 15"
+"goal_hs" "600 700"
+"message" "Use the other balls to your advantage\Be careful, the universe effects all balls!"
+// brush 0
+{
+( 280 -192 64 ) ( 272 -192 64 ) ( 280 -64 64 ) mtrl/edge-green 0 0 0 0.5 0.5 0 0 0
+( 336 144 64 ) ( 336 144 56 ) ( 336 -208 56 ) mtrl/turf-grey -0 0 0 0.5 0.5 0 0 0
+( 336 -16 48 ) ( 336 -16 40 ) ( 320 0 40 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+( 272 -112 56 ) ( 272 -240 56 ) ( 280 -112 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 320 -56 40 ) ( 320 -56 48 ) ( 320 -184 40 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+( 336 144 40 ) ( 336 144 48 ) ( 320 128 48 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+}
+// brush 1
+{
+( 320 88 64 ) ( 320 80 64 ) ( 192 88 64 ) mtrl/edge-green 0 0 0 0.5 0.5 0 0 0
+( -16 144 64 ) ( -16 144 56 ) ( 336 144 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 336 144 48 ) ( 336 144 40 ) ( 320 128 40 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+( 192 80 56 ) ( 320 80 56 ) ( 192 88 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( -136 128 56 ) ( -136 128 64 ) ( -8 128 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -336 144 56 ) ( -336 144 64 ) ( -320 128 64 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 2
+{
+( 0 40 64 ) ( 0 48 64 ) ( 128 40 64 ) mtrl/edge-green 0 0 0 0.5 0.5 0 0 0
+( 336 -16 64 ) ( 336 -16 56 ) ( -16 -16 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( -336 -16 64 ) ( -336 -16 56 ) ( -320 0 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 80 48 56 ) ( -48 48 56 ) ( 80 40 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 136 0 56 ) ( 136 0 64 ) ( 8 0 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 336 -16 40 ) ( 336 -16 48 ) ( 320 0 48 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+}
+// brush 3
+{
+( -280 320 64 ) ( -272 320 64 ) ( -280 192 64 ) mtrl/edge-green 128 0 0 0.5 0.5 0 0 0
+( -336 -16 64 ) ( -336 -16 56 ) ( -336 336 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( -336 144 64 ) ( -336 144 56 ) ( -320 128 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -272 240 56 ) ( -272 368 56 ) ( -280 240 56 ) mtrl/turf-grey 128 0 0 0.5 0.5 0 0 0
+( -320 184 56 ) ( -320 184 64 ) ( -320 312 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -336 -16 56 ) ( -336 -16 64 ) ( -320 0 64 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 4
+{
+( 320 320 64 ) ( 320 192 64 ) ( 192 320 64 ) mtrl/arrow-green-light 128 128 90 0.5 0.5 134217728 0 0
+( 320 320 64 ) ( 192 320 64 ) ( 320 320 48 ) mtrl/invisible 128 128 90 0.5 0.5 134217728 0 0
+( 320 320 64 ) ( 320 320 48 ) ( 320 192 64 ) mtrl/invisible 128 128 90 0.5 0.5 134217728 0 0
+( 191 192 63 ) ( 319 192 63 ) ( 191 320 63 ) mtrl/invisible 128 128 90 0.5 0.5 134217728 0 0
+( 192 192 48 ) ( 192 192 64 ) ( 320 192 48 ) mtrl/invisible 128 128 90 0.5 0.5 134217728 0 0
+( 192 192 48 ) ( 192 320 48 ) ( 192 192 64 ) mtrl/invisible 128 128 90 0.5 0.5 134217728 0 0
+}
+// brush 5
+{
+( 320 128 64 ) ( 320 0 64 ) ( 192 128 64 ) mtrl/switch 128 192 0 1 1 0 0 0
+( 320 160 64 ) ( 192 160 64 ) ( 320 160 48 ) mtrl/invisible 128 192 0 1 1 0 0 0
+( 352 128 64 ) ( 352 128 48 ) ( 352 0 64 ) mtrl/invisible 128 192 0 1 1 0 0 0
+( 191 0 63 ) ( 319 0 63 ) ( 191 128 63 ) mtrl/invisible 128 192 0 1 1 0 0 0
+( 176 -32 48 ) ( 176 -32 64 ) ( 304 -32 48 ) mtrl/invisible 128 192 0 1 1 0 0 0
+( 160 -16 48 ) ( 160 112 48 ) ( 160 -16 64 ) mtrl/invisible 128 192 0 1 1 0 0 0
+}
+// brush 6
+{
+( 320 512 64 ) ( 320 384 64 ) ( 192 512 64 ) mtrl/teleporter 128 0 0 0.5 0.5 134217728 0 0
+( 320 512 64 ) ( 192 512 64 ) ( 320 512 48 ) mtrl/invisible -0 0 0 0.5 0.5 134217728 0 0
+( 320 512 64 ) ( 320 512 48 ) ( 320 384 64 ) mtrl/invisible -0 0 0 0.5 0.5 134217728 0 0
+( 191 384 63 ) ( 319 384 63 ) ( 191 512 63 ) mtrl/invisible -0 0 0 0.5 0.5 134217728 0 0
+( 192 384 48 ) ( 192 384 64 ) ( 320 384 48 ) mtrl/invisible -0 0 0 0.5 0.5 134217728 0 0
+( 192 384 48 ) ( 192 512 48 ) ( 192 384 64 ) mtrl/invisible -0 0 0 0.5 0.5 134217728 0 0
+}
+// brush 7
+{
+( -192 320 64 ) ( -192 192 64 ) ( -320 320 64 ) mtrl/teleporter 128 128 0 0.25 0.25 134217728 0 0
+( -160 288 64 ) ( -288 288 64 ) ( -160 288 48 ) mtrl/invisible 128 128 0 0.25 0.25 134217728 0 0
+( -224 352 64 ) ( -224 352 48 ) ( -224 224 64 ) mtrl/invisible 128 128 0 0.25 0.25 134217728 0 0
+( -321 192 63 ) ( -193 192 63 ) ( -321 320 63 ) mtrl/invisible 128 128 0 0.25 0.25 134217728 0 0
+( -352 224 48 ) ( -352 224 64 ) ( -224 224 48 ) mtrl/invisible 128 128 0 0.25 0.25 134217728 0 0
+( -288 176 48 ) ( -288 304 48 ) ( -288 176 64 ) mtrl/invisible 128 128 0 0.25 0.25 134217728 0 0
+}
+// brush 8
+{
+( 320 264 64 ) ( 320 256 64 ) ( 192 264 64 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( 264 320 64 ) ( 136 320 64 ) ( 264 320 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 320 264 64 ) ( 320 264 56 ) ( 320 256 64 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 192 256 56 ) ( 320 256 56 ) ( 192 264 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 192 192 56 ) ( 192 192 64 ) ( 320 192 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -320 320 56 ) ( -320 328 56 ) ( -320 320 64 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 9
+{
+( 320 72 64 ) ( 320 64 64 ) ( 192 72 64 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( 264 128 64 ) ( 136 128 64 ) ( 264 128 56 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( 320 72 64 ) ( 320 72 56 ) ( 320 64 64 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( 192 64 56 ) ( 320 64 56 ) ( 192 72 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 192 0 56 ) ( 192 0 64 ) ( 320 0 56 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( -320 128 56 ) ( -320 136 56 ) ( -320 128 64 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+}
+// brush 10
+{
+( -80 288 576 ) ( -64 288 576 ) ( -80 160 576 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -80 320 416 ) ( -80 192 416 ) ( -80 320 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -80 336 416 ) ( -80 336 400 ) ( -64 336 416 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 192 400 ) ( -64 320 400 ) ( -80 192 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 192 400 ) ( -64 192 416 ) ( -64 320 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 176 400 ) ( -80 176 400 ) ( -64 176 416 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+}
+// brush 11
+{
+( -32 176 576 ) ( -32 192 576 ) ( 96 176 576 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 176 416 ) ( 64 176 416 ) ( -64 176 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 176 416 ) ( -64 176 400 ) ( -64 192 416 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 64 192 400 ) ( -64 192 400 ) ( 64 176 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 192 400 ) ( 64 192 416 ) ( -64 192 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 192 400 ) ( 64 176 400 ) ( 64 192 416 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 12
+{
+( 80 224 576 ) ( 64 224 576 ) ( 80 352 576 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 80 192 416 ) ( 80 320 416 ) ( 80 192 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 80 176 416 ) ( 80 176 400 ) ( 64 176 416 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 320 400 ) ( 64 192 400 ) ( 80 320 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 320 400 ) ( 64 320 416 ) ( 64 192 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 336 400 ) ( 80 336 400 ) ( 64 336 416 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+}
+// brush 13
+{
+( 32 336 576 ) ( 32 320 576 ) ( -96 336 576 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 336 416 ) ( -64 336 416 ) ( 64 336 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 336 416 ) ( 64 336 400 ) ( 64 320 416 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -64 320 400 ) ( 64 320 400 ) ( -64 336 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 320 400 ) ( -64 320 416 ) ( 64 320 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 320 400 ) ( -64 336 400 ) ( -64 320 416 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 14
+{
+( 64 320 576 ) ( 64 192 576 ) ( -64 320 576 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 320 576 ) ( -64 320 576 ) ( 64 320 400 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 64 320 576 ) ( 64 320 400 ) ( 64 192 576 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -80 192 560 ) ( 48 192 560 ) ( -80 320 560 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 192 400 ) ( -64 192 576 ) ( 64 192 400 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -64 192 400 ) ( -64 320 400 ) ( -64 192 576 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 15
+{
+( 320 456 64 ) ( 320 448 64 ) ( 192 456 64 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( 264 512 64 ) ( 136 512 64 ) ( 264 512 56 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( 320 456 64 ) ( 320 456 56 ) ( 320 448 64 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( 192 448 56 ) ( 320 448 56 ) ( 192 456 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 192 384 56 ) ( 192 384 64 ) ( 320 384 56 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+( -320 512 56 ) ( -320 520 56 ) ( -320 512 64 ) mtrl/turf-green-small 0 0 0 0.5 0.5 0 0 0
+}
+// brush 16
+{
+( 280 192 64 ) ( 272 192 64 ) ( 280 320 64 ) mtrl/edge-green 0 0 0 0.5 0.5 0 0 0
+( 336 528 64 ) ( 336 528 56 ) ( 336 176 56 ) mtrl/turf-grey -0 0 0 0.5 0.5 0 0 0
+( 336 368 48 ) ( 336 368 40 ) ( 320 384 40 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+( 272 272 56 ) ( 272 144 56 ) ( 280 272 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 320 328 40 ) ( 320 328 48 ) ( 320 200 40 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+( 336 528 40 ) ( 336 528 48 ) ( 320 512 48 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+}
+// brush 17
+{
+( 0 424 64 ) ( 0 432 64 ) ( 128 424 64 ) mtrl/edge-green 0 0 0 0.5 0.5 0 0 0
+( 336 368 64 ) ( 336 368 56 ) ( -16 368 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( -336 368 64 ) ( -336 368 56 ) ( -320 384 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 80 432 56 ) ( -48 432 56 ) ( 80 424 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 136 384 56 ) ( 136 384 64 ) ( 8 384 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 336 368 40 ) ( 336 368 48 ) ( 320 384 48 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+}
+// brush 18
+{
+( -280 704 64 ) ( -272 704 64 ) ( -280 576 64 ) mtrl/edge-green 128 0 0 0.5 0.5 0 0 0
+( -336 368 64 ) ( -336 368 56 ) ( -336 720 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( -336 528 64 ) ( -336 528 56 ) ( -320 512 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -272 624 56 ) ( -272 752 56 ) ( -280 624 56 ) mtrl/turf-grey 128 0 0 0.5 0.5 0 0 0
+( -320 568 56 ) ( -320 568 64 ) ( -320 696 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -336 368 56 ) ( -336 368 64 ) ( -320 384 64 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 19
+{
+( 320 472 64 ) ( 320 464 64 ) ( 192 472 64 ) mtrl/edge-green 0 0 0 0.5 0.5 0 0 0
+( -16 528 64 ) ( -16 528 56 ) ( 336 528 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 336 528 48 ) ( 336 528 40 ) ( 320 512 40 ) mtrl/invisible 0 96 0 0.5 0.5 0 0 0
+( 192 464 56 ) ( 320 464 56 ) ( 192 472 56 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( -136 512 56 ) ( -136 512 64 ) ( -8 512 56 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -336 528 56 ) ( -336 528 64 ) ( -320 512 64 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 20
+{
+( -192 512 64 ) ( -192 384 64 ) ( -320 512 64 ) mtrl/switch 128 0 0 0.5 0.5 134217728 0 0
+( -256 512 64 ) ( -384 512 64 ) ( -256 512 48 ) mtrl/invisible 128 0 0 0.5 0.5 134217728 0 0
+( -192 480 64 ) ( -192 480 48 ) ( -192 352 64 ) mtrl/invisible 128 0 0 0.5 0.5 134217728 0 0
+( -321 384 63 ) ( -193 384 63 ) ( -321 512 63 ) mtrl/invisible 128 0 0 0.5 0.5 134217728 0 0
+( -320 384 48 ) ( -320 384 64 ) ( -192 384 48 ) mtrl/invisible 128 0 0 0.5 0.5 134217728 0 0
+( -320 384 48 ) ( -320 512 48 ) ( -320 384 64 ) mtrl/invisible 128 0 0 0.5 0.5 134217728 0 0
+}
+// brush 21
+{
+( 1072 208 160 ) ( 1072 48 160 ) ( 1024 208 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 1072 192 160 ) ( 1024 192 160 ) ( 1072 192 144 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 1168 176 152 ) ( 1168 176 160 ) ( 1152 192 160 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 1016 48 152 ) ( 1064 48 152 ) ( 1016 208 152 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 1168 176 160 ) ( 1168 176 152 ) ( 640 176 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 640 160 144 ) ( 640 320 144 ) ( 640 160 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+}
+// brush 22
+{
+( 1088 336 160 ) ( 1088 176 160 ) ( 1040 336 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 1168 336 152 ) ( 1168 336 160 ) ( 1152 320 160 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 1168 176 152 ) ( 1168 176 160 ) ( 1168 336 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 1032 176 152 ) ( 1080 176 152 ) ( 1032 336 152 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 1168 176 160 ) ( 1168 176 152 ) ( 1152 192 160 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 1152 160 144 ) ( 1152 320 144 ) ( 1152 160 160 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+// brush 23
+{
+( 1072 352 160 ) ( 1072 192 160 ) ( 1024 352 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 1168 336 152 ) ( 1168 336 160 ) ( 640 336 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 1168 336 160 ) ( 1168 336 152 ) ( 1152 320 152 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 1016 192 152 ) ( 1064 192 152 ) ( 1016 352 152 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 1024 320 144 ) ( 1024 320 160 ) ( 1072 320 144 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 640 304 144 ) ( 640 464 144 ) ( 640 304 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+}
+// brush 24
+{
+( 1072 336 160 ) ( 1072 176 160 ) ( 1024 336 160 ) mtrl/turf-red 0 0 0 0.5 0.5 0 0 0
+( 1072 320 160 ) ( 1024 320 160 ) ( 1072 320 144 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 1152 352 160 ) ( 1152 352 144 ) ( 1152 192 160 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 1016 176 152 ) ( 1064 176 152 ) ( 1016 336 152 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 1024 192 144 ) ( 1024 192 160 ) ( 1072 192 144 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 640 176 144 ) ( 640 336 144 ) ( 640 176 160 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+}
+// brush 25
+{
+( 1344 320 0 ) ( 1344 192 0 ) ( 1216 320 0 ) mtrl/goal 0 128 0 0.5 0.5 134217728 0 0
+( 1472 320 8 ) ( 1344 320 8 ) ( 1472 320 -8 ) mtrl/invisible 0 128 0 0.5 0.5 134217728 0 0
+( 1408 448 8 ) ( 1408 448 -8 ) ( 1408 320 8 ) mtrl/invisible 0 128 0 0.5 0.5 134217728 0 0
+( 1211 192 -1 ) ( 1339 192 -1 ) ( 1211 320 -1 ) mtrl/invisible 0 128 0 0.5 0.5 134217728 0 0
+( 1152 192 -8 ) ( 1152 192 8 ) ( 1280 192 -8 ) mtrl/invisible 0 128 0 0.5 0.5 134217728 0 0
+( 1280 128 -8 ) ( 1280 256 -8 ) ( 1280 128 8 ) mtrl/invisible 0 128 0 0.5 0.5 134217728 0 0
+}
+// brush 26
+{
+( 1344 320 0 ) ( 1344 192 0 ) ( 1216 320 0 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 1408 384 8 ) ( 1280 384 8 ) ( 1408 384 -8 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 1472 384 8 ) ( 1472 384 -8 ) ( 1472 256 8 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 1216 192 -16 ) ( 1344 192 -16 ) ( 1216 320 -16 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 1216 128 -8 ) ( 1216 128 8 ) ( 1344 128 -8 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 1216 192 -8 ) ( 1216 320 -8 ) ( 1216 192 8 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+}
+}
+// entity 1
+{
+"classname" "info_player_intermission"
+"target" "t1"
+"origin" "601 -444 624"
+}
+// entity 2
+{
+"classname" "target_position"
+"targetname" "t1"
+"origin" "-38 560 -40"
+}
+// entity 3
+{
+"classname" "info_player_start"
+"origin" "256 256 88"
+}
+// entity 4
+{
+"classname" "info_notnull"
+"origin" "144 256 88"
+"radius" "0.125"
+"collisions" "0"
+"mobile" "1"
+"return" "1"
+}
+// entity 5
+{
+"classname" "light"
+"origin" "-328 256 96"
+"light" "10"
+}
+// entity 6
+{
+"classname" "light"
+"origin" "0 328 96"
+"light" "5"
+}
+// entity 7
+{
+"classname" "light"
+"origin" "0 184 96"
+"light" "5"
+}
+// entity 8
+{
+"classname" "light"
+"origin" "-128 64 80"
+"light" "1"
+}
+// entity 9
+{
+"classname" "light"
+"origin" "80 256 80"
+"light" "1"
+}
+// entity 10
+{
+"classname" "light"
+"origin" "40 256 80"
+"light" "1"
+}
+// entity 11
+{
+"classname" "light"
+"origin" "64 64 80"
+"light" "1"
+}
+// entity 12
+{
+"classname" "light"
+"origin" "-32 64 80"
+"light" "5"
+}
+// entity 13
+{
+"classname" "func_train"
+"target" "p1_0"
+// brush 0
+{
+( 64 320 416 ) ( 64 192 416 ) ( -64 320 416 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( 64 320 416 ) ( -64 320 416 ) ( 64 320 400 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 64 320 416 ) ( 64 320 400 ) ( 64 192 416 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 192 400 ) ( 64 192 400 ) ( -64 320 400 ) mtrl/glass 0 0 0 0.5 0.5 0 0 0
+( -64 192 400 ) ( -64 192 416 ) ( 64 192 400 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( -64 192 400 ) ( -64 320 400 ) ( -64 192 416 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+}
+}
+// entity 14
+{
+"classname" "path_corner"
+"origin" "0 256 480"
+"targetname" "p1_0"
+"target" "p1_1"
+"speed" "3"
+"state" "0"
+}
+// entity 15
+{
+"classname" "path_corner"
+"origin" "-128 256 480"
+"targetname" "p1_1"
+}
+// entity 16
+{
+"classname" "info_notnull"
+"origin" "0 256 440"
+"mobile" "1"
+"collisions" "0"
+"return" "1"
+"radius" "0.375"
+}
+// entity 17
+{
+"classname" "light"
+"origin" "-32 448 80"
+"light" "1"
+}
+// entity 18
+{
+"classname" "light"
+"origin" "64 448 80"
+"light" "1"
+}
+// entity 19
+{
+"classname" "light"
+"origin" "-80 448 96"
+"light" "10"
+}
+// entity 20
+{
+"classname" "info_camp"
+"origin" "-256 448 64"
+"target" "p1_0"
+"timer" "9999"
+}
+// entity 21
+{
+"classname" "info_camp"
+"origin" "256 64 64"
+"target" "p2_0"
+"timer" "9999"
+"radius" "1.0"
+}
+// entity 22
+{
+"classname" "info_camp"
+"origin" "256 64 64"
+"target" "p3_0"
+"timer" "9999"
+"invisible" "1"
+"radius" "1.0"
+}
+// entity 23
+{
+"classname" "target_position"
+"origin" "-256 256 64"
+"targetname" "t2"
+}
+// entity 24
+{
+"classname" "target_position"
+"origin" "256 448 64"
+"targetname" "t3"
+}
+// entity 25
+{
+"classname" "target_teleporter"
+"origin" "-256 256 64"
+"target" "t3"
+"radius" "0.25"
+}
+// entity 26
+{
+"classname" "target_teleporter"
+"origin" "256 448 64"
+"target" "t2"
+}
+// entity 27
+{
+"classname" "func_train"
+"target" "p3_0"
+// brush 0
+{
+( 320 280 80 ) ( 320 272 80 ) ( 192 280 80 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -16 336 64 ) ( -16 336 56 ) ( 336 336 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 336 336 64 ) ( 336 336 56 ) ( 320 320 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 192 272 56 ) ( 320 272 56 ) ( 192 280 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 184 320 56 ) ( 184 320 64 ) ( 312 320 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -336 336 56 ) ( -336 336 64 ) ( -320 320 64 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+}
+// brush 1
+{
+( 280 0 80 ) ( 272 0 80 ) ( 280 128 80 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 336 336 64 ) ( 336 336 56 ) ( 336 -16 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 336 176 64 ) ( 336 176 56 ) ( 320 192 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 272 80 56 ) ( 272 -48 56 ) ( 280 80 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 320 136 56 ) ( 320 136 64 ) ( 320 8 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 336 336 56 ) ( 336 336 64 ) ( 320 320 64 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+}
+// brush 2
+{
+( 0 232 80 ) ( 0 240 80 ) ( 128 232 80 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 336 176 64 ) ( 336 176 56 ) ( -16 176 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -336 176 64 ) ( -336 176 56 ) ( -320 192 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 80 240 56 ) ( -48 240 56 ) ( 80 232 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -184 192 56 ) ( -184 192 64 ) ( -312 192 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( 336 176 56 ) ( 336 176 64 ) ( 320 192 64 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+}
+// brush 3
+{
+( -280 512 80 ) ( -272 512 80 ) ( -280 384 80 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -336 176 64 ) ( -336 176 56 ) ( -336 528 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -336 336 64 ) ( -336 336 56 ) ( -320 320 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -272 432 56 ) ( -272 560 56 ) ( -280 432 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -320 376 56 ) ( -320 376 64 ) ( -320 504 56 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+( -336 176 56 ) ( -336 176 64 ) ( -320 192 64 ) mtrl/wood 0 0 0 0.5 0.5 0 0 0
+}
+}
+// entity 28
+{
+"classname" "path_corner"
+"origin" "0 256 192"
+"targetname" "p3_0"
+"target" "p3_1"
+"speed" "3"
+"state" "0"
+}
+// entity 29
+{
+"classname" "path_corner"
+"origin" "0 256 192"
+"targetname" "p3_1"
+"target" "p3_2"
+"speed" "0.75"
+}
+// entity 30
+{
+"classname" "path_corner"
+"origin" "0 256 184"
+"targetname" "p3_2"
+}
+// entity 31
+{
+"classname" "light"
+"origin" "704 288 176"
+"light" "5"
+}
+// entity 32
+{
+"classname" "light"
+"origin" "704 224 176"
+"light" "5"
+}
+// entity 33
+{
+"classname" "info_notnull"
+"origin" "832 256 184"
+"collisions" "0"
+"return" "1"
+"mobile" "0"
+}
+// entity 34
+{
+"classname" "info_player_deathmatch"
+"origin" "1344 256 24"
+}
+// entity 35
+{
+"classname" "func_train"
+"target" "p2_0"
+// brush 0
+{
+( 640 352 240 ) ( 640 192 240 ) ( 336 192 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 400 336 160 ) ( 336 336 160 ) ( 400 336 144 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 640 464 232 ) ( 640 304 232 ) ( 640 304 240 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 640 192 232 ) ( 640 352 232 ) ( 336 192 152 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 336 320 144 ) ( 336 320 160 ) ( 400 320 144 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 336 192 144 ) ( 336 352 144 ) ( 336 192 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+}
+// brush 1
+{
+( 640 208 240 ) ( 640 48 240 ) ( 336 48 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 400 192 160 ) ( 336 192 160 ) ( 400 192 144 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 640 320 232 ) ( 640 160 232 ) ( 640 160 240 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 640 48 232 ) ( 640 208 232 ) ( 336 48 152 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 336 176 144 ) ( 336 176 160 ) ( 400 176 144 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+( 336 48 144 ) ( 336 208 144 ) ( 336 48 160 ) mtrl/chrome-faceted 0 0 0 0.5 0.5 0 0 0
+}
+// brush 2
+{
+( 640 336 240 ) ( 640 176 240 ) ( 336 176 160 ) mtrl/turf-red 0 0 0 0.5 0.5 0 0 0
+( 400 320 160 ) ( 336 320 160 ) ( 400 320 144 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 640 336 232 ) ( 640 176 232 ) ( 640 176 240 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 640 176 232 ) ( 640 336 232 ) ( 336 176 152 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+( 336 192 144 ) ( 336 192 160 ) ( 400 192 144 ) mtrl/invisible 0 0 0 0.5 0.5 0 0 0
+( 336 176 144 ) ( 336 336 144 ) ( 336 176 160 ) mtrl/turf-grey 0 0 0 0.5 0.5 0 0 0
+}
+}
+// entity 36
+{
+"classname" "path_corner"
+"origin" "1024 512 192"
+"targetname" "p2_0"
+"target" "p2_1"
+"state" "0"
+"speed" "3"
+}
+// entity 37
+{
+"classname" "path_corner"
+"origin" "1024 512 112"
+"targetname" "p2_1"
+}
+// entity 38
+{
+"classname" "light"
+"origin" "-128 448 80"
+"light" "1"
+}
Index: ball/game.c
===================================================================
--- ball/game.c (.../trunk) (revision 1922)
+++ ball/game.c (.../branches/putt-collisions) (revision 1922)
@@ -54,11 +54,12 @@
static float view_k;
static int coins = 0; /* Collected coins */
-static int goal_e = 0; /* Goal enabled flag */
+static int goal_e = 0; /* Goal coins remaining (0 = open) */
static float goal_k = 0; /* Goal animation */
static int jump_e = 1; /* Jumping enabled flag */
static int jump_b = 0; /* Jump-in-progress flag */
static float jump_dt; /* Jump duration */
+static int jump_y = 0; /* Which arbitrary ball is jumping? */
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 */
@@ -78,7 +79,7 @@
* r:
* -32767 = -VIEWR_BOUND
* +32767 = +VIEWR_BOUND
- *
+ *
*/
struct input
@@ -156,7 +157,7 @@
put_short(fout, &input_current.z);
put_short(fout, &input_current.r);
put_short(fout, &input_current.c);
-
+
return 1;
}
return 0;
@@ -340,6 +341,7 @@
jump_e = 1;
jump_b = 0;
+ jump_y = 0;
goal_e = e ? 1 : 0;
goal_k = e ? 1.0f : 0.0f;
@@ -398,14 +400,60 @@
/*---------------------------------------------------------------------------*/
+void game_check_balls(struct s_file *fp)
+{
+ float z[3] = {0.0f, 0.0f, 0.0f};
+ int i;
+
+ for (i = 0; i < fp->yc; i++)
+ {
+ struct s_ball *yp = fp->yv + i;
+
+ /*
+ * Test and deal with any fall-outs
+ */
+ if (yp->p[1] < fp->vv[0].p[1] && yp->n)
+ {
+ v_cpy(yp->p, yp->O);
+ v_cpy(yp->v, z);
+ v_cpy(yp->w, z);
+ }
+ }
+}
+
static void game_draw_balls(const struct s_file *fp,
const float *bill_M, float t)
{
- float c[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ float c[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
float ball_M[16];
float pend_M[16];
+ int yi;
+
+ for (yi = 0; yi < fp->yc; yi++)
+ {
+ float ball_M[16];
+ float pend_M[16];
+
+ m_basis(ball_M, fp->yv[yi].e[0], fp->yv[yi].e[1], fp->yv[yi].e[2]);
+ m_basis(pend_M, fp->yv[yi].E[0], fp->yv[yi].E[1], fp->yv[yi].E[2]);
+
+ glPushMatrix();
+ {
+ glTranslatef(fp->yv[yi].p[0],
+ fp->yv[yi].p[1] + BALL_FUDGE,
+ fp->yv[yi].p[2]);
+ glScalef(fp->yv[yi].r,
+ fp->yv[yi].r,
+ fp->yv[yi].r);
+
+ glColor4fv(c);
+ ball_draw(ball_M, pend_M, bill_M, t);
+ }
+ glPopMatrix();
+ }
+
m_basis(ball_M, fp->uv[0].e[0], fp->uv[0].e[1], fp->uv[0].e[2]);
m_basis(pend_M, fp->uv[0].E[0], fp->uv[0].E[1], fp->uv[0].E[2]);
@@ -510,7 +558,7 @@
glTranslatef(fp->zv[zi].p[0],
fp->zv[zi].p[1],
fp->zv[zi].p[2]);
-
+
part_draw_goal(M, fp->zv[zi].r, goal_k, t);
}
glPopMatrix();
@@ -795,8 +843,12 @@
{
float fov = view_fov;
- if (jump_b) fov *= 2.f * fabsf(jump_dt - 0.5);
+ if (jump_b && jump_y)
+ fov /= 1.9f * fabsf(jump_dt - 0.5f);
+ else if (jump_b)
+ fov *= 2.0f * fabsf(jump_dt - 0.5f);
+
if (game_state)
{
config_push_persp(fov, 0.1f, FAR_DIST);
@@ -994,12 +1046,13 @@
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 i;
+
/* Test for an item. */
if (bt && (hp = sol_item_test(fp, p, COIN_RADIUS)))
@@ -1016,30 +1069,56 @@
/* Discard item. */
+ /* Reset item type. */
+
hp->t = ITEM_NONE;
}
/* Test for a switch. */
- if (sol_swch_test(fp, 0))
+ if (sol_swch_test(fp))
audio_play(AUD_SWITCH, 1.f);
/* Test for a jump. */
- if (jump_e == 1 && jump_b == 0 && sol_jump_test(fp, jump_p, 0) == 1)
+ if (!jump_y && jump_e == 1 && jump_b == 0 &&
+ sol_jump_test(fp, jump_p, 0) == 1)
{
jump_b = 1;
jump_e = 0;
jump_dt = 0.f;
+ jump_y = 0;
audio_play(AUD_JUMP, 1.f);
}
if (jump_e == 0 && jump_b == 0 && sol_jump_test(fp, jump_p, 0) == 0)
jump_e = 1;
+ if (!jump_b && !jump_y && sol_jump_test(fp, jump_p, 0) == 0)
+ jump_y = 0;
+ for (i = 0; i < fp->yc; i++)
+ {
+ if (!jump_y && jump_e == 1 && jump_b == 0 &&
+ sol_jump_test(fp, jump_p, fp->yv + i - fp->uv) == 1)
+ {
+ jump_b = 1;
+ jump_e = 0;
+ jump_dt = 0.f;
+ jump_y = i + 1;
+
+ audio_play(AUD_JUMP, 1.f);
+ }
+ if (jump_e == 0 && jump_b == 0 &&
+ sol_jump_test(fp, jump_p, fp->yv + i - fp->uv) == 0)
+ jump_e = 1;
+ if (!jump_b && jump_y && i == jump_y - 1 &&
+ sol_jump_test(fp, jump_p, fp->yv + i - fp->uv) == 0)
+ jump_y = 0;
+ }
+
/* Test for a goal. */
- if (bt && goal_e && (zp = sol_goal_test(fp, p, 0)))
+ if (bt && goal_e && (sol_goal_test(fp, p, 0)))
{
audio_play(AUD_GOAL, 1.0f);
return GAME_GOAL;
@@ -1090,9 +1169,19 @@
if (0.5f < jump_dt)
{
- fp->uv[0].p[0] = jump_p[0];
- fp->uv[0].p[1] = jump_p[1];
- fp->uv[0].p[2] = jump_p[2];
+ if (jump_y)
+ {
+ fp->yv[jump_y - 1].p[0] = jump_p[0];
+ fp->yv[jump_y - 1].p[1] = jump_p[1];
+ fp->yv[jump_y - 1].p[2] = jump_p[2];
+ }
+
+ else
+ {
+ fp->uv[0].p[0] = jump_p[0];
+ fp->uv[0].p[1] = jump_p[1];
+ fp->uv[0].p[2] = jump_p[2];
+ }
}
if (1.0f < jump_dt)
jump_b = 0;
@@ -1103,6 +1192,8 @@
float b = sol_step(fp, h, dt, 0, NULL);
+ game_check_balls(fp);
+
/* Mix the sound of a ball bounce. */
if (b > 0.5f)
Index: putt/game.c
===================================================================
--- putt/game.c (.../trunk) (revision 1922)
+++ putt/game.c (.../branches/putt-collisions) (revision 1922)
@@ -46,6 +46,7 @@
static float jump_e = 1; /* Jumping enabled flag */
static float jump_b = 0; /* Jump-in-progress flag */
+static int jump_u = 0; /* Which ball is jumping? */
static float jump_dt; /* Jump duration */
static float jump_p[3]; /* Jump destination */
@@ -82,6 +83,7 @@
{
jump_e = 1;
jump_b = 0;
+ jump_u = 0;
view_init();
sol_load_gl(&file, config_data(s), config_get_d(CONFIG_TEXTURES),
@@ -95,6 +97,124 @@
/*---------------------------------------------------------------------------*/
+int game_check_balls(struct s_file *fp)
+{
+ float z[3] = {0.0f, 0.0f, 0.0f};
+ int i, j;
+
+ for (i = 1; i < fp->uc && config_get_d(CONFIG_BALL_COLLISIONS); i++)
+ {
+ struct s_ball *up = fp->uv + i;
+
+ /*
+ * If a ball falls out, return the ball to the camera marker
+ * and reset the play state for fair play
+ */
+ if (i != ball && up->p[1] < -10.f &&
+ (up->p[1] > -199.9f || up->p[1] < -599.9f))
+ {
+ up->P = 0;
+ v_cpy(up->p, fp->uv->p);
+ v_cpy(up->v, z);
+ v_cpy(up->w, z);
+ }
+
+ if (i == ball && up->p[1] < -30.0f)
+ {
+ v_cpy(up->p, fp->uv->p);
+ v_cpy(up->v, z);
+ v_cpy(up->w, z);
+ }
+
+ /*
+ * If an OTHER ball stops in a hole, mark it as done
+ * and drop it -200.0 units to allow room for more balls
+ */
+ if (i != ball && !(v_len(up->v) > 0.0f))
+ {
+ const float *ball_p = up->p;
+ const float ball_r = up->r;
+ int zi;
+ for (zi = 0; zi < fp->zc; zi++)
+ {
+ float r[3];
+
+ r[0] = ball_p[0] - fp->zv[zi].p[0];
+ r[1] = ball_p[2] - fp->zv[zi].p[2];
+ r[2] = 0;
+
+ if (v_len(r) < fp->zv[zi].r * 1.1 - ball_r &&
+ ball_p[1] > fp->zv[zi].p[1] &&
+ ball_p[1] < fp->zv[zi].p[1] + GOAL_HEIGHT / 2)
+ {
+ up->p[1] = -200.0f;
+ v_cpy(up->v, z);
+ v_cpy(up->w, z);
+ return i;
+ }
+ }
+ }
+
+ /*
+ * Check for intesecting balls.
+ * If there are any, reset the proper
+ * ball's play state
+ */
+ for (j = i + 1; j < fp->uc && config_get_d(CONFIG_BALL_COLLISIONS); j++)
+ {
+ struct s_ball *u2p = fp->uv + j;
+ float d[3];
+ v_sub(d, up->p, u2p->p);
+ if (v_len(up->v) > 0.005f || v_len(u2p->v) > 0.005f)
+ continue;
+ if (v_len(d) < (fsqrtf((up->r + u2p->r)
+ * (up->r + u2p->r))) * 1.0f && i != ball)
+ up->P = 0;
+ else if (v_len(d) < (fsqrtf((up->r
+ + u2p->r) * (up->r + u2p->r)) * 1.0f))
+ u2p->P = 0;
+ }
+ }
+
+ for (i = 0; i < fp->yc; i++)
+ {
+ struct s_ball *yp = fp->yv + i;
+
+ if (yp->p[1] < -20.0f && yp->n)
+ {
+ v_cpy(yp->p, yp->O);
+ v_cpy(yp->v, z);
+ v_cpy(yp->w, z);
+ }
+
+ if (!(v_len(yp->v) > 0.0f))
+ {
+ const float *ball_p = yp->p;
+ const float ball_r = yp->r;
+ int zi;
+ for (zi = 0; zi < fp->zc; zi++)
+ {
+ float r[3];
+
+ r[0] = ball_p[0] - fp->zv[zi].p[0];
+ r[1] = ball_p[2] - fp->zv[zi].p[2];
+ r[2] = 0;
+
+ if (v_len(r) < fp->zv[zi].r * 1.1 - ball_r &&
+ ball_p[1] > fp->zv[zi].p[1] &&
+ ball_p[1] < fp->zv[zi].p[1] + GOAL_HEIGHT / 2)
+ {
+ v_cpy(yp->p, yp->O);
+ v_cpy(yp->v, z);
+ v_cpy(yp->w, z);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
static void game_draw_vect_prim(const struct s_file *fp, GLenum mode)
{
float p[3];
@@ -158,19 +278,50 @@
static void game_draw_balls(const struct s_file *fp,
const float *bill_M, float t)
{
- static const GLfloat color[5][4] = {
+ static const GLfloat color[6][4] = {
{ 1.0f, 1.0f, 1.0f, 0.7f },
{ 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.0f, 1.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f, 1.0f },
{ 1.0f, 1.0f, 0.0f, 1.0f },
+ { 0.1f, 0.1f, 0.1f, 1.0f },
};
- int ui;
+ int ui, yi;
+ for (yi = 0; yi < fp->yc; yi++)
+ {
+ float ball_M[16];
+ float pend_M[16];
+
+ if (!config_get_d(CONFIG_BALL_COLLISIONS) && fp->yv[yi].c)
+ continue;
+
+ m_basis(ball_M, fp->yv[yi].e[0], fp->yv[yi].e[1], fp->yv[yi].e[2]);
+ m_basis(pend_M, fp->yv[yi].E[0], fp->yv[yi].E[1], fp->yv[yi].E[2]);
+
+ glPushMatrix();
+ {
+ glTranslatef(fp->yv[yi].p[0],
+ fp->yv[yi].p[1] + BALL_FUDGE,
+ fp->yv[yi].p[2]);
+ glScalef(fp->yv[yi].r,
+ fp->yv[yi].r,
+ fp->yv[yi].r);
+
+ glEnable(GL_COLOR_MATERIAL);
+ glColor4fv(color[5]);
+
+ ball_draw(ball_M, pend_M, bill_M, t);
+ glDisable(GL_COLOR_MATERIAL);
+ }
+ glPopMatrix();
+ }
+
for (ui = curr_party(); ui > 0; ui--)
{
- if (ui == ball)
+ if (ui == ball || (config_get_d(CONFIG_BALL_COLLISIONS) &&
+ fp->uv[ui].P))
{
float ball_M[16];
float pend_M[16];
@@ -189,6 +340,7 @@
glEnable(GL_COLOR_MATERIAL);
glColor4fv(color[ui]);
+
ball_draw(ball_M, pend_M, bill_M, t);
glDisable(GL_COLOR_MATERIAL);
}
@@ -280,15 +432,21 @@
static const float s[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
static const float e[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
static const float h[1] = { 0.0f };
-
+
const float light_p[4] = { 8.f, 32.f, 8.f, 1.f };
const struct s_file *fp = &file;
float fov = FOV;
- if (jump_b) fov *= 2.0f * fabsf(jump_dt - 0.5f);
+ int i = 0;
+ if (config_get_d(CONFIG_BALL_COLLISIONS) && jump_b && jump_u != ball * 2)
+ fov /= 1.9f * fabsf(jump_dt - 0.5f);
+
+ else if (jump_b)
+ fov *= 2.0f * fabsf(jump_dt - 0.5f);
+
config_push_persp(fov, 0.1f, FAR_DIST);
glPushAttrib(GL_LIGHTING_BIT);
glPushMatrix();
@@ -325,6 +483,23 @@
if (config_get_d(CONFIG_SHADOW) && !pose)
{
+ for (i = 0; i < fp->yc; i++)
+ {
+ shad_draw_set(fp->yv[i].p, fp->yv[i].r);
+ sol_shad(fp);
+ shad_draw_clr();
+ }
+
+ for (i = 0; i < fp->uc; i++)
+ {
+ if (fp->uv[i].P)
+ {
+ shad_draw_set(fp->uv[i].p, fp->uv[i].r);
+ sol_shad(fp);
+ shad_draw_clr();
+ }
+ }
+
shad_draw_set(fp->uv[ball].p, fp->uv[ball].r);
sol_shad(fp);
shad_draw_clr();
@@ -442,49 +617,133 @@
struct s_file *fp = &file;
float p[3];
+ int i;
+
if (dt > 0.f)
t += dt;
else
t = 0.f;
/* Test for a switch. */
-
- if (sol_swch_test(fp, ball))
+ if (sol_swch_test(fp))
audio_play(AUD_SWITCH, 1.f);
/* Test for a jump. */
- if (jump_e == 1 && jump_b == 0 && sol_jump_test(fp, jump_p, ball) == 1)
+ if (config_get_d(CONFIG_BALL_COLLISIONS))
{
- jump_b = 1;
- jump_e = 0;
- jump_dt = 0.f;
+ for (i = 1; i < curr_party() + 1; i++)
+ {
+ if (!jump_u && jump_e == 1 && jump_b == 0 &&
+ sol_jump_test(fp, jump_p, i) == 1)
+ {
+ jump_b = 1;
+ jump_e = 0;
+ jump_dt = 0.f;
+ jump_u = i * 2;
- audio_play(AUD_JUMP, 1.f);
+ audio_play(AUD_JUMP, 1.f);
+ }
+ if (jump_e == 0 && jump_b == 0 &&
+ sol_jump_test(fp, jump_p, i) == 0)
+ jump_e = 1;
+ if (!jump_b && jump_u && i == jump_u / 2 &&
+ sol_jump_test(fp, jump_p, i) == 0)
+ jump_u = 0;
+ }
+
+ for (i = 0; i < fp->yc; i++)
+ {
+ if (!jump_u && jump_e == 1 && jump_b == 0 &&
+ sol_jump_test(fp, jump_p, fp->yv + i - fp->uv) == 1)
+ {
+ jump_b = 1;
+ jump_e = 0;
+ jump_dt = 0.f;
+ jump_u = i * 2 + 1;
+
+ audio_play(AUD_JUMP, 1.f);
+ }
+ if (jump_e == 0 && jump_b == 0 &&
+ sol_jump_test(fp,
+ jump_p, fp->yv + i - fp->uv) == 0)
+ jump_e = 1;
+ if (!jump_b && jump_u && i == jump_u / 2 &&
+ sol_jump_test(fp, jump_p, fp->yv + i - fp->uv) == 0)
+ jump_u = 0;
+ }
}
- if (jump_e == 0 && jump_b == 0 && sol_jump_test(fp, jump_p, ball) == 0)
- jump_e = 1;
+ else
+ {
+ if (jump_e == 1 && jump_b == 0 && sol_jump_test(fp, jump_p, ball) == 1)
+ {
+ 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, ball) == 0)
+ jump_e = 1;
+ }
+
/* Test for fall-out. */
- if (fp->uv[ball].p[1] < -10.f)
+ if (fp->uv[ball].p[1] < -10.0f)
return GAME_FALL;
/* Test for a goal or stop. */
- if (t > 1.f)
+ if (t > 1.0f)
{
- t = 0.f;
+ t = 0.0f;
- if (sol_goal_test(fp, p, ball))
- return GAME_GOAL;
+ if (config_get_d(CONFIG_BALL_COLLISIONS))
+ {
+ switch (sol_goal_test(fp, p, ball))
+ {
+ case 2: /* All balls stopped & Player's ball stopped in hole */
+ t = 0.0f;
+ return GAME_GOAL;
+ break;
+ case 1: /* All balls stopped */
+ t = 0.0f;
+ return GAME_STOP;
+ break;
+ case 0: /* At least one ball is still in motion */
+ return GAME_NONE;
+ break;
+ default: /* Should never reach this */
+ break;
+ }
+ }
+
else
- return GAME_STOP;
+ {
+ if (sol_goal_test(fp, p, ball))
+ return GAME_GOAL;
+ else
+ return GAME_STOP;
+ }
}
return GAME_NONE;
}
+void game_set_played(int b)
+{
+ if (ball)
+ file.uv[ball].P = b;
+ if (!b)
+ {
+ file.uv[0].P = 0;
+ file.uv[1].P = 0;
+ file.uv[2].P = 0;
+ file.uv[3].P = 0;
+ file.uv[4].P = 0;
+ }
+}
+
/*
* On most hardware, rendering requires much more computing power than
* physics. Since physics takes less time than graphics, it make sense to
@@ -517,18 +776,49 @@
if (jump_b)
{
- jump_dt += dt;
+ if (config_get_d(CONFIG_BALL_COLLISIONS))
+ {
+ jump_dt += dt;
- /* Handle a jump. */
+ /* Handle a jump. */
- if (0.5 < jump_dt)
+ if (0.5 < jump_dt)
+ {
+ if (jump_u % 2)
+ {
+ fp->yv[jump_u / 2].p[0] = jump_p[0];
+ fp->yv[jump_u / 2].p[1] = jump_p[1];
+ fp->yv[jump_u / 2].p[2] = jump_p[2];
+ }
+
+ else
+ {
+ fp->uv[jump_u / 2].p[0] = jump_p[0];
+ fp->uv[jump_u / 2].p[1] = jump_p[1];
+ fp->uv[jump_u / 2].p[2] = jump_p[2];
+ }
+ }
+ if (1.f < jump_dt)
+ {
+ jump_b = 0;
+ }
+ }
+
+ else
{
- fp->uv[ball].p[0] = jump_p[0];
- fp->uv[ball].p[1] = jump_p[1];
- fp->uv[ball].p[2] = jump_p[2];
+ jump_dt += dt;
+
+ /* Handle a jump. */
+
+ if (0.5 < jump_dt)
+ {
+ fp->uv[ball].p[0] = jump_p[0];
+ fp->uv[ball].p[1] = jump_p[1];
+ fp->uv[ball].p[2] = jump_p[2];
+ }
+ if (1.f < jump_dt)
+ jump_b = 0;
}
- if (1.f < jump_dt)
- jump_b = 0;
}
else
{
@@ -542,8 +832,13 @@
for (i = 0; i < n; i++)
{
+ int ball_in_hole = 0;
+
d = sol_step(fp, g, t, ball, &m);
+ if ((ball_in_hole = game_check_balls(fp)))
+ hole_goal(ball_in_hole);
+
if (b < d)
b = d;
if (m)
@@ -568,10 +863,20 @@
* friction too early and stopping the ball prematurely.
*/
- file.uv[ball].v[0] = -4.f * view_e[2][0] * view_m;
- file.uv[ball].v[1] = -4.f * view_e[2][1] * view_m + BALL_FUDGE;
- file.uv[ball].v[2] = -4.f * view_e[2][2] * view_m;
+ if (config_get_d(CONFIG_BALL_COLLISIONS))
+ {
+ file.uv[ball].v[0] = -4.f * view_e[2][0] * view_m;
+ file.uv[ball].v[1] = -4.f * view_e[2][1] * view_m + BALL_FUDGE;
+ file.uv[ball].v[2] = -4.f * view_e[2][2] * view_m;
+ }
+ else
+ {
+ file.uv[ball].v[0] = -4.f * view_e[2][0] * view_m;
+ file.uv[ball].v[1] = -4.f * view_e[2][1] * view_m + BALL_FUDGE;
+ file.uv[ball].v[2] = -4.f * view_e[2][2] * view_m;
+ }
+
view_m = 0.f;
}
@@ -705,4 +1010,3 @@
}
/*---------------------------------------------------------------------------*/
-
Index: putt/st_all.c
===================================================================
--- putt/st_all.c (.../trunk) (revision 1922)
+++ putt/st_all.c (.../branches/putt-collisions) (revision 1922)
@@ -239,7 +239,7 @@
static void title_timer(int id, float dt)
{
- float g[3] = { 0.f, 0.f, 0.f };
+ float g[3] = { 0.0f, -9.8f, 0.0f };
game_step(g, dt);
game_set_fly(fcosf(time_state() / 10.f));
@@ -873,6 +873,8 @@
if (paused)
paused = 0;
+ game_set_played(1);
+
return 0;
}
@@ -891,7 +893,7 @@
static void stroke_timer(int id, float dt)
{
- float g[3] = { 0.f, 0.f, 0.f };
+ float g[3] = { 0.0f, -9.8f, 0.0f };
float k;
@@ -1002,7 +1004,7 @@
if (paused)
paused = 0;
else
- hole_goal();
+ hole_goal(0);
hud_init();
@@ -1089,7 +1091,7 @@
static void stop_timer(int id, float dt)
{
- float g[3] = { 0.f, 0.f, 0.f };
+ float g[3] = { 0.0f, -9.8f, 0.0f };
game_update_view(dt);
game_step(g, dt);
@@ -1216,6 +1218,8 @@
if (paused)
paused = 0;
+ game_set_played(0);
+
return score_card(_("Scores"), gui_yel, gui_red);
}
Index: putt/game.h
===================================================================
--- putt/game.h (.../trunk) (revision 1922)
+++ putt/game.h (.../branches/putt-collisions) (revision 1922)
@@ -43,6 +43,8 @@
void game_update_view(float);
+void game_set_played(int);
+
void game_set_rot(int);
void game_clr_mag(void);
void game_set_mag(int);
Index: putt/main.c
===================================================================
--- putt/main.c (.../trunk) (revision 1922)
+++ putt/main.c (.../branches/putt-collisions) (revision 1922)
@@ -48,6 +48,7 @@
return 1;
}
+
/*---------------------------------------------------------------------------*/
static void toggle_wire(void)
@@ -294,4 +295,3 @@
}
/*---------------------------------------------------------------------------*/
-
Index: putt/hole.c
===================================================================
--- putt/hole.c (.../trunk) (revision 1922)
+++ putt/hole.c (.../branches/putt-collisions) (revision 1922)
@@ -134,7 +134,7 @@
if (p <= party)
{
- for (h = 1; h <= hole && h < count; h++)
+ for (h = 1; h <= hole && h <= 18; h++)
T += score_v[h][p];
sprintf(str, "%d", T);
@@ -152,7 +152,7 @@
if (p <= party)
{
- for (h = 1; h <= hole && h <= count / 2; h++)
+ for (h = 1; h <= hole && h <= 9; h++)
T += score_v[h][p];
sprintf(str, "%d", T);
@@ -167,11 +167,10 @@
static char str[MAXSTR];
int h, T = 0;
- int out = count / 2;
- if (hole > out && p <= party)
+ if (hole > 9 && p <= party)
{
- for (h = out + 1; h <= hole && h < count; h++)
+ for (h = 10; h <= hole && h <= 18; h++)
T += score_v[h][p];
sprintf(str, "%d", T);
@@ -267,31 +266,63 @@
return 0;
}
-void hole_goal(void)
+void hole_goal(int playerid)
{
- score_v[hole][player]++;
+ if (playerid)
+ {
+ /* HACK: If the player has already beaten the hole, return */
+ if (stat_v[playerid] == 1)
+ return;
- if (score_v[hole][player] == 1)
- audio_play(AUD_ONE, 1.0f);
+ if (score_v[hole][playerid] == 1)
+ audio_play(AUD_ONE, 1.0f);
- else if (score_v[hole][player] == score_v[hole][0] - 2)
- audio_play(AUD_EAGLE, 1.0f);
- else if (score_v[hole][player] == score_v[hole][0] - 1)
- audio_play(AUD_BIRDIE, 1.0f);
- else if (score_v[hole][player] == score_v[hole][0])
- audio_play(AUD_PAR, 1.0f);
- else if (score_v[hole][player] == score_v[hole][0] + 1)
- audio_play(AUD_BOGEY, 1.0f);
- else if (score_v[hole][player] == score_v[hole][0] + 2)
- audio_play(AUD_DOUBLE, 1.0f);
+ else if (score_v[hole][playerid] == score_v[hole][0] - 2)
+ audio_play(AUD_EAGLE, 1.0f);
+ else if (score_v[hole][playerid] == score_v[hole][0] - 1)
+ audio_play(AUD_BIRDIE, 1.0f);
+ else if (score_v[hole][playerid] == score_v[hole][0])
+ audio_play(AUD_PAR, 1.0f);
+ else if (score_v[hole][playerid] == score_v[hole][0] + 1)
+ audio_play(AUD_BOGEY, 1.0f);
+ else if (score_v[hole][playerid] == score_v[hole][0] + 2)
+ audio_play(AUD_DOUBLE, 1.0f);
+ else
+ audio_play(AUD_SUCCESS, 1.0f);
+
+ stat_v[playerid] = 1;
+ done++;
+
+ if (done == party)
+ audio_music_fade_out(2.0f);
+ }
+
else
- audio_play(AUD_SUCCESS, 1.0f);
+ {
+ score_v[hole][player]++;
- stat_v[player] = 1;
- done++;
+ if (score_v[hole][player] == 1)
+ audio_play(AUD_ONE, 1.0f);
- if (done == party)
- audio_music_fade_out(2.0f);
+ else if (score_v[hole][player] == score_v[hole][0] - 2)
+ audio_play(AUD_EAGLE, 1.0f);
+ else if (score_v[hole][player] == score_v[hole][0] - 1)
+ audio_play(AUD_BIRDIE, 1.0f);
+ else if (score_v[hole][player] == score_v[hole][0])
+ audio_play(AUD_PAR, 1.0f);
+ else if (score_v[hole][player] == score_v[hole][0] + 1)
+ audio_play(AUD_BOGEY, 1.0f);
+ else if (score_v[hole][player] == score_v[hole][0] + 2)
+ audio_play(AUD_DOUBLE, 1.0f);
+ else
+ audio_play(AUD_SUCCESS, 1.0f);
+
+ stat_v[player] = 1;
+ done++;
+
+ if (done == party)
+ audio_music_fade_out(2.0f);
+ }
}
void hole_stop(void)
Index: putt/st_balt.c
===================================================================
--- putt/st_balt.c (.../trunk) (revision 0)
+++ putt/st_balt.c (.../branches/putt-collisions) (revision 1922)
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2003 Robert Kooima - 2008 Byron Johnson
+ * Part of the Neverball Project http://icculus.org/neverball/
+ *
+ * NEVERBALL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+
+#include "gui.h"
+#include "back.h"
+#include "part.h"
+#include "game.h"
+#include "audio.h"
+#include "config.h"
+
+#include "st_balt.h"
+
+extern struct state st_conf;
+extern struct state st_null;
+
+/*---------------------------------------------------------------------------*/
+
+enum {
+ BALT_BACK = 1,
+ BALT_GOLF,
+ BALT_BILL,
+ BALT_CRAZ
+};
+
+static int balt_action(int i)
+{
+ int r = 1;
+
+ audio_play(AUD_MENU, 1.0f);
+
+ switch (i)
+ {
+ case BALT_BACK:
+ goto_state(&st_conf);
+ break;
+
+ case BALT_GOLF:
+ goto_state(&st_null);
+ config_set_s(CONFIG_BALL_GAMMA, "0.78");
+ goto_state(&st_balt);
+ break;
+
+ case BALT_BILL:
+ goto_state(&st_null);
+ config_set_s(CONFIG_BALL_GAMMA, "1.00");
+ goto_state(&st_balt);
+ break;
+
+ case BALT_CRAZ:
+ goto_state(&st_null);
+ config_set_s(CONFIG_BALL_GAMMA, "1.50");
+ goto_state(&st_balt);
+ break;
+
+ default:
+ break;
+ }
+
+ return r;
+}
+
+static int balt_enter(void)
+{
+ int id, jd;
+
+ char gamma[MAXNAM];
+
+ config_get_s(CONFIG_BALL_GAMMA, gamma, MAXNAM);
+
+ back_init("back/gui.png", config_get_d(CONFIG_GEOMETRY));
+
+ if ((id = gui_vstack(0)))
+ {
+ if ((jd = gui_harray(id)))
+ {
+ gui_space(jd);
+ gui_space(jd);
+ gui_start(jd, _("Back"), GUI_SML, BALT_BACK, 0);
+ }
+
+ gui_space(id);
+ gui_space(id);
+
+ if ((jd = gui_harray(id)))
+ {
+ gui_state(jd, _("Billiards"), GUI_SML, BALT_BILL,
+ strcmp(gamma, "1.00") == 0 ||
+ strcmp(gamma, "1.0") == 0);
+ gui_state(jd, _("Golf Balls"), GUI_SML, BALT_GOLF,
+ strcmp(gamma, "0.78") == 0);
+ }
+
+ if ((jd = gui_harray(id)))
+ {
+ gui_state(jd, _("Crazy Balls"), GUI_SML, BALT_CRAZ,
+ strcmp(gamma, "1.50") == 0 ||
+ strcmp(gamma, "1.5") == 0);
+ }
+
+ gui_layout(id, 0, 0);
+ }
+
+ audio_music_fade_to(0.5f, "bgm/inter.ogg");
+
+ return id;
+}
+
+static void balt_leave(int id)
+{
+ back_free();
+ gui_delete(id);
+}
+
+static void balt_paint(int id, float st)
+{
+ config_push_persp((float) config_get_d(CONFIG_VIEW_FOV), 0.1f, FAR_DIST);
+ {
+ back_draw(0);
+ }
+ config_pop_matrix();
+ gui_paint(id);
+}
+
+static void balt_timer(int id, float dt)
+{
+ gui_timer(id, dt);
+}
+
+static void balt_point(int id, int x, int y, int dx, int dy)
+{
+ gui_pulse(gui_point(id, x, y), 1.2f);
+}
+
+static void balt_stick(int id, int a, int v)
+{
+ if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
+ gui_pulse(gui_stick(id, v, 0), 1.2f);
+ if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
+ gui_pulse(gui_stick(id, 0, v), 1.2f);
+}
+
+static int balt_click(int b, int d)
+{
+ if (b < 0 && d == 1)
+ return balt_action(gui_token(gui_click()));
+ return 1;
+}
+
+static int balt_keybd(int c, int d)
+{
+ return (d && c == SDLK_ESCAPE) ? goto_state(&st_conf) : 1;
+}
+
+static int balt_buttn(int b, int d)
+{
+ if (d)
+ {
+ if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
+ return balt_action(gui_token(gui_click()));
+ if (config_tst_d(CONFIG_JOYSTICK_BUTTON_B, b))
+ return goto_state(&st_conf);
+ if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
+ return goto_state(&st_conf);
+ }
+ return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+
+
+struct state st_balt = {
+ balt_enter,
+ balt_leave,
+ balt_paint,
+ balt_timer,
+ balt_point,
+ balt_stick,
+ NULL,
+ balt_click,
+ balt_keybd,
+ balt_buttn,
+ 1, 0
+};
Property changes on: putt/st_balt.c
___________________________________________________________________
Name: svn:executable
+ *
Index: putt/st_conf.c
===================================================================
--- putt/st_conf.c (.../trunk) (revision 1922)
+++ putt/st_conf.c (.../branches/putt-collisions) (revision 1922)
@@ -25,6 +25,7 @@
#include "st_conf.h"
#include "st_all.h"
#include "st_resol.h"
+#include "st_balt.h"
/*---------------------------------------------------------------------------*/
@@ -38,7 +39,10 @@
CONF_SHDON,
CONF_SHDOF,
CONF_BACK,
- CONF_RESOL
+ CONF_RESOL,
+ CONF_BALT,
+ CONF_BCLON,
+ CONF_BCLOF
};
static int music_id[11];
@@ -112,6 +116,22 @@
goto_state(&st_resol);
break;
+ case CONF_BALT:
+ goto_state(&st_balt);
+ break;
+
+ case CONF_BCLON:
+ goto_state(&st_null);
+ config_set_d(CONFIG_BALL_COLLISIONS, 1);
+ goto_state(&st_conf);
+ break;
+
+ case CONF_BCLOF:
+ goto_state(&st_null);
+ config_set_d(CONFIG_BALL_COLLISIONS, 0);
+ goto_state(&st_conf);
+ break;
+
default:
if (100 <= i && i <= 110)
{
@@ -151,18 +171,39 @@
if ((id = gui_vstack(0)))
{
int f = config_get_d(CONFIG_FULLSCREEN);
+ int c = config_get_d(CONFIG_BALL_COLLISIONS);
int t = config_get_d(CONFIG_TEXTURES);
int g = config_get_d(CONFIG_GEOMETRY);
int h = config_get_d(CONFIG_SHADOW);
int s = config_get_d(CONFIG_SOUND_VOLUME);
int m = config_get_d(CONFIG_MUSIC_VOLUME);
+ char gamma[MAXNAM];
+
char resolution[20];
+ char balt[22];
+
+ config_get_s(CONFIG_BALL_GAMMA, gamma, MAXNAM);
+
sprintf(resolution, "%d x %d",
config_get_d(CONFIG_WIDTH),
config_get_d(CONFIG_HEIGHT));
+ if (strcmp(gamma, "0.78") == 0)
+ strcpy(balt, "Golf Balls");
+
+ else if (strcmp(gamma, "1.00") == 0 ||
+ strcmp(gamma, "1.0") == 0)
+ strcpy(balt, "Billiards");
+
+ else if (strcmp(gamma, "1.50") == 0 ||
+ strcmp(gamma, "1.5") == 0)
+ strcpy(balt, "Crazy Balls");
+
+ else
+ sprintf(balt, "Custom");
+
if ((jd = gui_harray(id)))
{
gui_label(jd, _("Options"), GUI_SML, GUI_ALL, 0, 0);
@@ -184,7 +225,7 @@
if ((jd = gui_harray(id)) &&
(kd = gui_harray(jd)))
{
- gui_state(kd, resolution, GUI_SML, CONF_RESOL, 0);
+ gui_state(kd, resolution, GUI_SML, CONF_RESOL, 0);
gui_label(jd, _("Resolution"), GUI_SML, GUI_ALL, 0, 0);
}
@@ -194,30 +235,57 @@
if ((jd = gui_harray(id)) &&
(kd = gui_harray(jd)))
{
- gui_state(kd, _("Low"), GUI_SML, CONF_TEXLO, (t == 2));
- gui_state(kd, _("High"), GUI_SML, CONF_TEXHI, (t == 1));
+ gui_state(kd, _("Off"), GUI_SML, CONF_BCLOF, (c == 0));
+ gui_state(kd, _("On"), GUI_SML, CONF_BCLON, (c == 1));
- gui_label(jd, _("Textures"), GUI_SML, GUI_ALL, 0, 0);
+ gui_label(jd, _("Ball Collisions"), GUI_SML, GUI_ALL, 0, 0);
}
if ((jd = gui_harray(id)) &&
(kd = gui_harray(jd)))
{
- gui_state(kd, _("Low"), GUI_SML, CONF_GEOLO, (g == 0));
- gui_state(kd, _("High"), GUI_SML, CONF_GEOHI, (g == 1));
+ if (c == 1)
+ {
+ gui_state(kd, balt, GUI_SML, CONF_BALT, 0);
+ gui_space(jd);
+ }
+ else
+ {
+ gui_space(kd);
+ gui_space(jd);
+ gui_space(id);
+ }
+ }
- gui_label(jd, _("Geometry"), GUI_SML, GUI_ALL, 0, 0);
+ gui_space(id);
+
+ if ((jd = gui_harray(id)) &&
+ (kd = gui_harray(jd)))
+ {
+ gui_state(kd, _("Low"), GUI_SML, CONF_TEXLO, (t == 2));
+ gui_state(kd, _("High"), GUI_SML, CONF_TEXHI, (t == 1));
+
+ gui_label(jd, _("Textures"), GUI_SML, GUI_ALL, 0, 0);
}
if ((jd = gui_harray(id)) &&
(kd = gui_harray(jd)))
{
- gui_state(kd, _("Off"), GUI_SML, CONF_SHDOF, (h == 0));
- gui_state(kd, _("On"), GUI_SML, CONF_SHDON, (h == 1));
+ gui_state(kd, _("Low"), GUI_SML, CONF_GEOLO, (g == 0));
+ gui_state(kd, _("High"), GUI_SML, CONF_GEOHI, (g == 1));
- gui_label(jd, _("Shadow"), GUI_SML, GUI_ALL, 0, 0);
+ gui_label(jd, _("Geometry"), GUI_SML, GUI_ALL, 0, 0);
}
+ if ((jd = gui_harray(id)) &&
+ (kd = gui_harray(jd)))
+ {
+ gui_state(kd, _("Off"), GUI_SML, CONF_SHDOF, (h == 0));
+ gui_state(kd, _("On"), GUI_SML, CONF_SHDON, (h == 1));
+
+ gui_label(jd, _("Shadow"), GUI_SML, GUI_ALL, 0, 0);
+ }
+
gui_space(id);
if ((jd = gui_harray(id)) &&
Index: putt/hole.h
===================================================================
--- putt/hole.h (.../trunk) (revision 1922)
+++ putt/hole.h (.../branches/putt-collisions) (revision 1922)
@@ -28,7 +28,7 @@
void hole_goto(int, int);
int hole_next(void);
int hole_move(void);
-void hole_goal(void);
+void hole_goal(int);
void hole_stop(void);
void hole_fall(void);
Index: putt/st_balt.h
===================================================================
--- putt/st_balt.h (.../trunk) (revision 0)
+++ putt/st_balt.h (.../branches/putt-collisions) (revision 1922)
@@ -0,0 +1,8 @@
+#ifndef ST_BALT_H
+#define ST_BALT_H
+
+#include "state.h"
+
+extern struct state st_balt;
+
+#endif
Property changes on: putt/st_balt.h
___________________________________________________________________
Name: svn:executable
+ *
Index: Makefile
===================================================================
--- Makefile (.../trunk) (revision 1922)
+++ Makefile (.../branches/putt-collisions) (revision 1922)
@@ -125,6 +125,8 @@
share/solid.o \
share/binary.o \
share/base_config.o \
+ share/config.o \
+ share/sync.o \
share/mapc.o
BALL_OBJS := \
share/lang.o \
@@ -200,6 +202,7 @@
putt/course.o \
putt/st_all.o \
putt/st_conf.o \
+ putt/st_balt.o \
putt/main.o
BALL_DEPS := $(BALL_OBJS:.o=.d)
@@ -229,7 +232,7 @@
$(CC) $(ALL_CFLAGS) -o $(PUTT_TARG) $(PUTT_OBJS) $(LDFLAGS) $(ALL_LIBS)
$(MAPC_TARG) : $(MAPC_OBJS)
- $(CC) $(ALL_CFLAGS) -o $(MAPC_TARG) $(MAPC_OBJS) $(LDFLAGS) $(BASE_LIBS)
+ $(CC) $(ALL_CFLAGS) -o $(MAPC_TARG) $(MAPC_OBJS) $(LDFLAGS) $(ALL_LIBS)
# Work around some extremely helpful sdl-config scripts.