2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
25 /*---------------------------------------------------------------------------*/
37 static struct part part_coin[PART_MAX_COIN];
38 static struct part part_goal[PART_MAX_GOAL];
39 static struct part part_jump[PART_MAX_JUMP];
40 static GLuint part_text_star;
41 static GLuint part_text_squiggle;
42 static GLuint part_list;
44 static float goal_height;
45 static float jump_height;
47 /*---------------------------------------------------------------------------*/
51 static float rnd(float l, float h)
53 return l + (h - l) * rand() / RAND_MAX;
56 /*---------------------------------------------------------------------------*/
58 void part_reset(float zh, float jh)
65 for (i = 0; i < PART_MAX_COIN; i++)
66 part_coin[i].t = 0.0f;
68 for (i = 0; i < PART_MAX_GOAL; i++)
70 float t = rnd(+0.1f, +1.0f);
71 float a = rnd(-1.0f * PI, +1.0f * PI);
72 float w = rnd(-2.0f * PI, +2.0f * PI);
75 part_goal[i].a = V_DEG(a);
76 part_goal[i].w = V_DEG(w);
78 part_goal[i].c[0] = 1.0f;
79 part_goal[i].c[1] = 1.0f;
80 part_goal[i].c[2] = 0.0f;
82 part_goal[i].p[0] = fsinf(a);
83 part_goal[i].p[1] = (1.f - t) * goal_height;
84 part_goal[i].p[2] = fcosf(a);
86 part_goal[i].v[0] = 0.f;
87 part_goal[i].v[1] = 0.f;
88 part_goal[i].v[2] = 0.f;
91 for (i = 0; i < PART_MAX_JUMP; i++)
93 float t = rnd(+0.1f, +1.0f);
94 float a = rnd(-1.0f * PI, +1.0f * PI);
95 float w = rnd(+0.5f, +2.5f);
97 float vy = rnd(+0.025f, +0.25f);
100 part_jump[i].a = V_DEG(a);
103 part_jump[i].c[0] = 1.0f;
104 part_jump[i].c[1] = 1.0f;
105 part_jump[i].c[2] = 1.0f;
107 part_jump[i].p[0] = fsinf(a);
108 part_jump[i].p[1] = (1.f - t) * jump_height;
109 part_jump[i].p[2] = fcosf(a);
111 part_jump[i].v[0] = 0.f;
112 part_jump[i].v[1] = vy;
113 part_jump[i].v[2] = 0.f;
117 void part_init(float zh, float jh)
119 memset(part_coin, 0, PART_MAX_COIN * sizeof (struct part));
120 memset(part_goal, 0, PART_MAX_GOAL * sizeof (struct part));
121 memset(part_jump, 0, PART_MAX_JUMP * sizeof (struct part));
123 part_text_star = make_image_from_file(IMG_PART_STAR);
124 part_text_squiggle = make_image_from_file(IMG_PART_SQUIGGLE);
126 part_list = glGenLists(1);
128 glNewList(part_list, GL_COMPILE);
132 glTexCoord2f(0.f, 0.f);
133 glVertex2f(-PART_SIZE, -PART_SIZE);
135 glTexCoord2f(1.f, 0.f);
136 glVertex2f(+PART_SIZE, -PART_SIZE);
138 glTexCoord2f(1.f, 1.f);
139 glVertex2f(+PART_SIZE, +PART_SIZE);
141 glTexCoord2f(0.f, 1.f);
142 glVertex2f(-PART_SIZE, +PART_SIZE);
153 if (glIsList(part_list))
154 glDeleteLists(part_list, 1);
156 if (glIsTexture(part_text_star))
157 glDeleteTextures(1, &part_text_star);
159 if (glIsTexture(part_text_squiggle))
160 glDeleteTextures(1, &part_text_squiggle);
163 /*---------------------------------------------------------------------------*/
165 void part_burst(const float *p, const float *c)
169 for (i = 0; n < 10 && i < PART_MAX_COIN; i++)
170 if (part_coin[i].t <= 0.f)
172 float a = rnd(-1.0f * PI, +1.0f * PI);
173 float b = rnd(+0.3f * PI, +0.5f * PI);
174 float w = rnd(-4.0f * PI, +4.0f * PI);
176 part_coin[i].p[0] = p[0];
177 part_coin[i].p[1] = p[1];
178 part_coin[i].p[2] = p[2];
180 part_coin[i].v[0] = 4.f * fcosf(a) * fcosf(b);
181 part_coin[i].v[1] = 4.f * fsinf(b);
182 part_coin[i].v[2] = 4.f * fsinf(a) * fcosf(b);
184 part_coin[i].c[0] = c[0];
185 part_coin[i].c[1] = c[1];
186 part_coin[i].c[2] = c[2];
188 part_coin[i].t = 1.f;
189 part_coin[i].a = 0.f;
190 part_coin[i].w = V_DEG(w);
196 /*---------------------------------------------------------------------------*/
198 static void part_fall(struct part *part, int n, const float *g, float dt)
202 for (i = 0; i < n; i++)
207 part[i].v[0] += (g[0] * dt);
208 part[i].v[1] += (g[1] * dt);
209 part[i].v[2] += (g[2] * dt);
211 part[i].p[0] += (part[i].v[0] * dt);
212 part[i].p[1] += (part[i].v[1] * dt);
213 part[i].p[2] += (part[i].v[2] * dt);
217 static void part_spin(struct part *part, int n, const float *g, float dt)
221 for (i = 0; i < n; i++)
224 part[i].a += 30.f * dt;
226 part[i].p[0] = fsinf(V_RAD(part[i].a));
227 part[i].p[2] = fcosf(V_RAD(part[i].a));
231 void part_step(const float *g, float dt)
235 part_fall(part_coin, PART_MAX_COIN, g, dt);
238 part_fall(part_goal, PART_MAX_GOAL, g, dt);
240 part_spin(part_goal, PART_MAX_GOAL, g, dt);
242 for (i = 0; i < PART_MAX_JUMP; i++)
244 part_jump[i].p[1] += part_jump[i].v[1] * dt;
246 if (part_jump[i].p[1] > jump_height)
247 part_jump[i].p[1] = 0.0f;
251 /*---------------------------------------------------------------------------*/
253 static void part_draw(const float *M,
254 const float *p, float r, float rz, float s)
258 glTranslatef(r * p[0], p[1], r * p[2]);
260 glRotatef(rz, 0.f, 0.f, 1.f);
261 glScalef(s, s, 1.0f);
263 glCallList(part_list);
268 void part_draw_coin(const float *M, float t)
272 glBindTexture(GL_TEXTURE_2D, part_text_star);
274 for (i = 0; i < PART_MAX_COIN; i++)
275 if (part_coin[i].t > 0.f)
277 glColor4f(part_coin[i].c[0],
282 part_draw(M, part_coin[i].p, 1.0f, t * part_coin[i].w, 1.0f);
286 void part_draw_goal(const float *M, float radius, float a, float t)
290 glBindTexture(GL_TEXTURE_2D, part_text_star);
292 glColor4f(1.0f, 1.0f, 0.0f, a);
294 for (i = 0; i < PART_MAX_GOAL; i++)
295 if (part_goal[i].t > 0.0f)
296 part_draw(M, part_goal[i].p, radius - 0.05f,
297 t * part_goal[i].w, 1.0f);
300 void part_draw_jump(const float *M, float radius, float a, float t)
304 glBindTexture(GL_TEXTURE_2D, part_text_squiggle);
306 for (i = 0; i < PART_MAX_JUMP; i++)
308 glColor4f(part_jump[i].c[0],
311 1.0f - part_jump[i].p[1] / jump_height);
314 * X is the current time since some Epoch, Y is the time it
315 * takes for a squiggle to grow to its full size and then
316 * shrink again. F is the current scale of the squiggle in
317 * the interval [0.0, 1.0].
320 #define F(x, y) fabsf(fsinf(((x) / (y)) * PI))
322 part_draw(M, part_jump[i].p, radius - 0.05f,
323 0.0f, F(t, part_jump[i].w));
329 /*---------------------------------------------------------------------------*/