Import from neverball-1.3.1.tar.gz
[neverball-archive.git] / share / part.c
blob0b94f626178ac073c6bbd237ab619cdc9af5d94a
1 /*
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.
15 #include <SDL.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
20 #include "glext.h"
21 #include "part.h"
22 #include "vec3.h"
23 #include "image.h"
25 /*---------------------------------------------------------------------------*/
27 struct part
29 float t;
30 float a;
31 float w;
32 float c[3];
33 float p[3];
34 float v[3];
37 static struct part part_coin[PART_MAX_COIN];
38 static struct part part_goal[PART_MAX_GOAL];
39 static GLuint part_text;
40 static GLuint part_list;
42 /*---------------------------------------------------------------------------*/
44 #define PI 3.1415927f
46 static float rnd(float l, float h)
48 return l + (h - l) * rand() / RAND_MAX;
51 /*---------------------------------------------------------------------------*/
53 void part_reset(float h)
55 int i;
57 for (i = 0; i < PART_MAX_GOAL; i++)
59 float t = rnd(+0.1f, +1.0f);
60 float a = rnd(-1.0f * PI, +1.0f * PI);
61 float w = rnd(-2.0f * PI, +2.0f * PI);
63 part_goal[i].t = t;
64 part_goal[i].a = V_DEG(a);
65 part_goal[i].w = V_DEG(w);
67 part_goal[i].c[0] = 1.0f;
68 part_goal[i].c[1] = 1.0f;
69 part_goal[i].c[2] = 0.0f;
71 part_goal[i].p[0] = fsinf(a);
72 part_goal[i].p[1] = (1.f - t) * h;
73 part_goal[i].p[2] = fcosf(a);
75 part_goal[i].v[0] = 0.f;
76 part_goal[i].v[1] = 0.f;
77 part_goal[i].v[2] = 0.f;
79 part_coin[i].t = 0.0f;
83 void part_init(float h)
85 memset(part_coin, 0, PART_MAX_COIN * sizeof (struct part));
86 memset(part_goal, 0, PART_MAX_GOAL * sizeof (struct part));
88 part_text = make_image_from_file(NULL, NULL, NULL, NULL, IMG_PART);
89 part_list = glGenLists(1);
91 glNewList(part_list, GL_COMPILE);
93 glBegin(GL_QUADS);
95 glTexCoord2f(0.f, 0.f);
96 glVertex2f(-PART_SIZE, -PART_SIZE);
98 glTexCoord2f(1.f, 0.f);
99 glVertex2f(+PART_SIZE, -PART_SIZE);
101 glTexCoord2f(1.f, 1.f);
102 glVertex2f(+PART_SIZE, +PART_SIZE);
104 glTexCoord2f(0.f, 1.f);
105 glVertex2f(-PART_SIZE, +PART_SIZE);
107 glEnd();
109 glEndList();
111 part_reset(h);
114 void part_free(void)
116 if (glIsList(part_list))
117 glDeleteLists(part_list, 1);
119 if (glIsTexture(part_text))
120 glDeleteTextures(1, &part_text);
123 /*---------------------------------------------------------------------------*/
125 void part_burst(const float *p, const float *c)
127 int i, n = 0;
129 for (i = 0; n < 10 && i < PART_MAX_COIN; i++)
130 if (part_coin[i].t <= 0.f)
132 float a = rnd(-1.0f * PI, +1.0f * PI);
133 float b = rnd(+0.3f * PI, +0.5f * PI);
134 float w = rnd(-4.0f * PI, +4.0f * PI);
136 part_coin[i].p[0] = p[0];
137 part_coin[i].p[1] = p[1];
138 part_coin[i].p[2] = p[2];
140 part_coin[i].v[0] = 4.f * fcosf(a) * fcosf(b);
141 part_coin[i].v[1] = 4.f * fsinf(b);
142 part_coin[i].v[2] = 4.f * fsinf(a) * fcosf(b);
144 part_coin[i].c[0] = c[0];
145 part_coin[i].c[1] = c[1];
146 part_coin[i].c[2] = c[2];
148 part_coin[i].t = 1.f;
149 part_coin[i].a = 0.f;
150 part_coin[i].w = V_DEG(w);
152 n++;
156 /*---------------------------------------------------------------------------*/
158 static void part_fall(struct part *part, int n, const float *g, float dt)
160 int i;
162 for (i = 0; i < n; i++)
163 if (part[i].t > 0.f)
165 part[i].t -= dt;
167 part[i].v[0] += (g[0] * dt);
168 part[i].v[1] += (g[1] * dt);
169 part[i].v[2] += (g[2] * dt);
171 part[i].p[0] += (part[i].v[0] * dt);
172 part[i].p[1] += (part[i].v[1] * dt);
173 part[i].p[2] += (part[i].v[2] * dt);
177 static void part_spin(struct part *part, int n, const float *g, float dt)
179 int i;
181 for (i = 0; i < n; i++)
182 if (part[i].t > 0.f)
184 part[i].a += 30.f * dt;
186 part[i].p[0] = fsinf(V_RAD(part[i].a));
187 part[i].p[2] = fcosf(V_RAD(part[i].a));
191 void part_step(const float *g, float dt)
193 part_fall(part_coin, PART_MAX_COIN, g, dt);
195 if (g[1] > 0.f)
196 part_fall(part_goal, PART_MAX_GOAL, g, dt);
197 else
198 part_spin(part_goal, PART_MAX_GOAL, g, dt);
201 /*---------------------------------------------------------------------------*/
203 static void part_draw(const float p[3], const float c[3],
204 float a, float r, float rx, float ry, float rz)
206 glPushMatrix();
208 glTranslatef(r * p[0], p[1], r * p[2]);
209 glRotatef(ry, 0.f, 1.f, 0.f);
210 glRotatef(rx, 1.f, 0.f, 0.f);
211 glRotatef(rz, 0.f, 0.f, 1.f);
213 glColor4f(c[0], c[1], c[2], a);
215 glCallList(part_list);
217 glPopMatrix();
220 void part_draw_coin(float rx, float ry)
222 float r = (float) SDL_GetTicks() / 1000.f;
223 int i;
225 glPushAttrib(GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT);
227 glDisable(GL_LIGHTING);
228 glEnable(GL_COLOR_MATERIAL);
230 glDepthMask(GL_FALSE);
231 glBindTexture(GL_TEXTURE_2D, part_text);
233 for (i = 0; i < PART_MAX_COIN; i++)
234 if (part_coin[i].t > 0.f)
235 part_draw(part_coin[i].p,
236 part_coin[i].c,
237 part_coin[i].t,
238 1.f, rx, ry, r * part_coin[i].w);
240 glPopAttrib();
243 void part_draw_goal(float rx, float ry, float radius, float a)
245 float r = (float) SDL_GetTicks() / 1000.f;
246 int i;
248 glPushAttrib(GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT);
250 glDisable(GL_LIGHTING);
252 glEnable(GL_COLOR_MATERIAL);
254 glDepthMask(GL_FALSE);
255 glBindTexture(GL_TEXTURE_2D, part_text);
257 for (i = 0; i < PART_MAX_GOAL; i++)
258 if (part_goal[i].t > 0.f)
259 part_draw(part_goal[i].p,
260 part_goal[i].c, a,
261 radius - 0.05f, rx, ry, r * part_goal[i].w);
263 glPopAttrib();
266 /*---------------------------------------------------------------------------*/