Mercurial > sdl-ios-xcode
comparison XCodeiPhoneOS/Demos/src/fireworks.c @ 2382:36bcf13ccb48 gsoc2008_iphone
fireworks demo
author | Holmes Futrell <hfutrell@umail.ucsb.edu> |
---|---|
date | Fri, 18 Jul 2008 20:51:34 +0000 |
parents | |
children | ac26bd83db1f |
comparison
equal
deleted
inserted
replaced
2381:d3952f445f4d | 2382:36bcf13ccb48 |
---|---|
1 /* | |
2 * fireworks.c | |
3 * written by Holmes Futrell | |
4 * use however you want | |
5 */ | |
6 | |
7 #include "SDL.h" | |
8 #include "math.h" | |
9 #include "common.h" | |
10 #include <math.h> | |
11 #include <time.h> | |
12 #include <OpenGLES/ES1/gl.h> | |
13 | |
14 #define MILLESECONDS_PER_FRAME 16 /* about 60 frames per second */ | |
15 #define ACCEL 0.0001f | |
16 #define WIND_RESISTANCE 0.00005f | |
17 #define MAX_PARTICLES 2000 | |
18 #define VEL_BEFORE_EXPLODE 0.0f | |
19 | |
20 SDL_TextureID flashTextureID; | |
21 | |
22 | |
23 enum particleType { | |
24 emitter = 0, | |
25 trail, | |
26 dust | |
27 }; | |
28 | |
29 struct glformat { | |
30 int SDL_GL_RED_SIZE; | |
31 int SDL_GL_GREEN_SIZE; | |
32 int SDL_GL_BLUE_SIZE; | |
33 int SDL_GL_ALPHA_SIZE; | |
34 int SDL_GL_BUFFER_SIZE; | |
35 int SDL_GL_DOUBLEBUFFER; | |
36 int SDL_GL_DEPTH_SIZE; | |
37 int SDL_GL_STENCIL_SIZE; | |
38 int SDL_GL_ACCUM_RED_SIZE; | |
39 int SDL_GL_ACCUM_GREEN_SIZE; | |
40 int SDL_GL_ACCUM_BLUE_SIZE; | |
41 int SDL_GL_ACCUM_ALPHA_SIZE; | |
42 int SDL_GL_STEREO; | |
43 int SDL_GL_MULTISAMPLEBUFFERS; | |
44 int SDL_GL_MULTISAMPLESAMPLES; | |
45 int SDL_GL_ACCELERATED_VISUAL; | |
46 int SDL_GL_RETAINED_BACKING; | |
47 }; | |
48 | |
49 struct particle { | |
50 | |
51 GLfloat x; | |
52 GLfloat y; | |
53 GLubyte color[4]; | |
54 GLfloat size; | |
55 GLfloat xvel; | |
56 GLfloat yvel; | |
57 int isActive; | |
58 enum particleType type; | |
59 int framesSinceEmission; | |
60 } particles[MAX_PARTICLES]; | |
61 | |
62 void spawnParticleFromEmitter(struct particle *emitter); | |
63 void explodeEmitter(struct particle *emitter); | |
64 | |
65 static int num_active_particles; | |
66 | |
67 static void getError(const char *prefix) | |
68 { | |
69 const char *error; | |
70 | |
71 GLenum result = glGetError(); | |
72 if (result == GL_NO_ERROR) | |
73 return; | |
74 | |
75 switch (result) { | |
76 case GL_NO_ERROR: | |
77 error = "GL_NO_ERROR"; | |
78 break; | |
79 case GL_INVALID_ENUM: | |
80 error = "GL_INVALID_ENUM"; | |
81 break; | |
82 case GL_INVALID_VALUE: | |
83 error = "GL_INVALID_VALUE"; | |
84 break; | |
85 case GL_INVALID_OPERATION: | |
86 error = "GL_INVALID_OPERATION"; | |
87 break; | |
88 case GL_STACK_OVERFLOW: | |
89 error = "GL_STACK_OVERFLOW"; | |
90 break; | |
91 case GL_STACK_UNDERFLOW: | |
92 error = "GL_STACK_UNDERFLOW"; | |
93 break; | |
94 case GL_OUT_OF_MEMORY: | |
95 error = "GL_OUT_OF_MEMORY"; | |
96 break; | |
97 default: | |
98 error = "UNKNOWN"; | |
99 break; | |
100 } | |
101 printf("%s: %s\n", prefix, error); | |
102 } | |
103 | |
104 void render(void) { | |
105 | |
106 /* draw the background */ | |
107 glClear(GL_COLOR_BUFFER_BIT); | |
108 | |
109 struct particle *slot = particles; | |
110 struct particle *curr = particles; | |
111 int i; | |
112 for (i=0; i<num_active_particles; i++) { | |
113 if (curr->isActive) { | |
114 | |
115 if (curr->y > SCREEN_HEIGHT) curr->isActive = 0; | |
116 if (curr->y < 0) curr->isActive = 0; | |
117 if (curr->x > SCREEN_WIDTH) curr->isActive = 0; | |
118 if (curr->x < 0) curr->isActive = 0; | |
119 | |
120 curr->yvel += ACCEL * MILLESECONDS_PER_FRAME; | |
121 curr->xvel += 0.0f; | |
122 curr->y += curr->yvel * MILLESECONDS_PER_FRAME; | |
123 curr->x += curr->xvel * MILLESECONDS_PER_FRAME; | |
124 | |
125 if (curr->type == emitter) { | |
126 spawnParticleFromEmitter(curr); | |
127 curr->framesSinceEmission = 0; | |
128 if (curr->yvel > -VEL_BEFORE_EXPLODE) { | |
129 explodeEmitter(curr); | |
130 } | |
131 curr->framesSinceEmission++; | |
132 } | |
133 else { | |
134 | |
135 float speed = sqrt(curr->xvel*curr->xvel + curr->yvel*curr->yvel); | |
136 | |
137 if (WIND_RESISTANCE * MILLESECONDS_PER_FRAME < speed) { | |
138 float normx = curr->xvel / speed; | |
139 float normy = curr->yvel / speed; | |
140 curr->xvel -= normx * WIND_RESISTANCE * MILLESECONDS_PER_FRAME; | |
141 curr->yvel -= normy * WIND_RESISTANCE * MILLESECONDS_PER_FRAME; | |
142 } | |
143 else { | |
144 curr->xvel = 0; | |
145 curr->yvel = 0; | |
146 } | |
147 | |
148 if (curr->color[3] <= MILLESECONDS_PER_FRAME * 0.0005f * 255) { | |
149 curr->isActive = 0; | |
150 | |
151 } | |
152 else { | |
153 curr->color[3] -= MILLESECONDS_PER_FRAME * 0.0005f * 255; | |
154 } | |
155 | |
156 if (curr->type == dust) | |
157 curr->size -= MILLESECONDS_PER_FRAME * 0.010f; | |
158 | |
159 } | |
160 | |
161 *(slot++) = *curr; | |
162 } | |
163 curr++; | |
164 } | |
165 num_active_particles = slot - particles; | |
166 | |
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
169 glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, 1); | |
170 | |
171 glEnableClientState(GL_VERTEX_ARRAY); | |
172 glVertexPointer(2, GL_FLOAT, sizeof(struct particle), particles + 0); | |
173 getError("vertices"); | |
174 | |
175 glEnableClientState(GL_COLOR_ARRAY); | |
176 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(struct particle), particles[0].color); | |
177 getError("colors"); | |
178 | |
179 glEnableClientState(GL_POINT_SIZE_ARRAY_OES); | |
180 getError("enable client state"); | |
181 glPointSizePointerOES(GL_FLOAT, sizeof(struct particle), &(particles[0].size)); | |
182 getError("point size"); | |
183 | |
184 glEnable(GL_POINT_SPRITE_OES); | |
185 glDrawArrays(GL_POINTS, 0, num_active_particles); | |
186 getError("glDrawArrays"); | |
187 | |
188 | |
189 /* update screen */ | |
190 SDL_RenderPresent(); | |
191 | |
192 } | |
193 | |
194 void printOpenGLAttributes(struct glformat *format) { | |
195 printf("\tSDL_GL_RED_SIZE = %d\n", format->SDL_GL_RED_SIZE); | |
196 printf("\tSDL_GL_GREEN_SIZE = %d\n", format->SDL_GL_GREEN_SIZE); | |
197 printf("\tSDL_GL_BLUE_SIZE = %d\n", format->SDL_GL_BLUE_SIZE); | |
198 printf("\tSDL_GL_ALPHA_SIZE = %d\n", format->SDL_GL_ALPHA_SIZE); | |
199 printf("\tSDL_GL_BUFFER_SIZE = %d\n", format->SDL_GL_BUFFER_SIZE); | |
200 printf("\tSDL_GL_DOUBLEBUFFER = %d\n", format->SDL_GL_DOUBLEBUFFER); | |
201 printf("\tSDL_GL_DEPTH_SIZE = %d\n", format->SDL_GL_DEPTH_SIZE); | |
202 printf("\tSDL_GL_STENCIL_SIZE = %d\n", format->SDL_GL_STENCIL_SIZE); | |
203 printf("\tSDL_GL_ACCUM_RED_SIZE = %d\n", format->SDL_GL_ACCUM_RED_SIZE); | |
204 printf("\tSDL_GL_ACCUM_GREEN_SIZE = %d\n", format->SDL_GL_ACCUM_GREEN_SIZE); | |
205 printf("\tSDL_GL_ACCUM_BLUE_SIZE = %d\n", format->SDL_GL_ACCUM_BLUE_SIZE); | |
206 printf("\tSDL_GL_ACCUM_ALPHA_SIZE = %d\n", format->SDL_GL_ACCUM_ALPHA_SIZE); | |
207 printf("\tSDL_GL_STEREO = %d\n", format->SDL_GL_STEREO); | |
208 printf("\tSDL_GL_MULTISAMPLEBUFFERS = %d\n", format->SDL_GL_MULTISAMPLEBUFFERS); | |
209 printf("\tSDL_GL_MULTISAMPLESAMPLES = %d\n", format->SDL_GL_MULTISAMPLESAMPLES); | |
210 printf("\tSDL_GL_ACCELERATED_VISUAL = %d\n", format->SDL_GL_ACCELERATED_VISUAL); | |
211 printf("\tSDL_GL_RETAINED_BACKING = %d\n", format->SDL_GL_RETAINED_BACKING); | |
212 } | |
213 | |
214 void setOpenGLAttributes(struct glformat *format) { | |
215 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, format->SDL_GL_RED_SIZE); | |
216 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, format->SDL_GL_GREEN_SIZE); | |
217 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, format->SDL_GL_BLUE_SIZE); | |
218 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, format->SDL_GL_ALPHA_SIZE); | |
219 SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, format->SDL_GL_BUFFER_SIZE); | |
220 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, format->SDL_GL_DOUBLEBUFFER); | |
221 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, format->SDL_GL_DEPTH_SIZE); | |
222 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, format->SDL_GL_STENCIL_SIZE); | |
223 SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, format->SDL_GL_ACCUM_RED_SIZE); | |
224 SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, format->SDL_GL_ACCUM_GREEN_SIZE); | |
225 SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, format->SDL_GL_ACCUM_BLUE_SIZE); | |
226 SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, format->SDL_GL_ACCUM_ALPHA_SIZE); | |
227 SDL_GL_SetAttribute(SDL_GL_STEREO, format->SDL_GL_STEREO); | |
228 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, format->SDL_GL_MULTISAMPLEBUFFERS); | |
229 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, format->SDL_GL_MULTISAMPLESAMPLES); | |
230 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, format->SDL_GL_ACCELERATED_VISUAL); | |
231 SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, format->SDL_GL_RETAINED_BACKING); | |
232 } | |
233 | |
234 void getOpenGLAttributes(struct glformat *format) { | |
235 | |
236 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &(format->SDL_GL_RED_SIZE)); | |
237 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &(format->SDL_GL_GREEN_SIZE)); | |
238 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &(format->SDL_GL_BLUE_SIZE)); | |
239 SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &(format->SDL_GL_ALPHA_SIZE)); | |
240 SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &(format->SDL_GL_BUFFER_SIZE)); | |
241 SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &(format->SDL_GL_DOUBLEBUFFER)); | |
242 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &(format->SDL_GL_DEPTH_SIZE)); | |
243 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &(format->SDL_GL_STENCIL_SIZE)); | |
244 SDL_GL_GetAttribute(SDL_GL_ACCUM_RED_SIZE, &(format->SDL_GL_ACCUM_RED_SIZE)); | |
245 SDL_GL_GetAttribute(SDL_GL_ACCUM_GREEN_SIZE, &(format->SDL_GL_ACCUM_GREEN_SIZE)); | |
246 SDL_GL_GetAttribute(SDL_GL_ACCUM_BLUE_SIZE, &(format->SDL_GL_ACCUM_BLUE_SIZE)); | |
247 SDL_GL_GetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, &(format->SDL_GL_ACCUM_ALPHA_SIZE)); | |
248 SDL_GL_GetAttribute(SDL_GL_STEREO, &(format->SDL_GL_STEREO)); | |
249 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &(format->SDL_GL_MULTISAMPLEBUFFERS)); | |
250 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &(format->SDL_GL_MULTISAMPLESAMPLES)); | |
251 SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &(format->SDL_GL_ACCELERATED_VISUAL)); | |
252 SDL_GL_GetAttribute(SDL_GL_RETAINED_BACKING, &(format->SDL_GL_RETAINED_BACKING)); | |
253 } | |
254 | |
255 void explodeEmitter(struct particle *emitter) { | |
256 | |
257 emitter->isActive = 0; | |
258 | |
259 int i; | |
260 for (i=0; i<200; i++) { | |
261 | |
262 if (num_active_particles >= MAX_PARTICLES) return; | |
263 | |
264 float theta = randomFloat(0, 2.0f * 3.141592); | |
265 float max = 3.0f; | |
266 float speed = randomFloat(0.00, powf(0.17, max)); | |
267 speed = powf(speed, 1.0f / max); | |
268 | |
269 struct particle *p = &particles[num_active_particles]; | |
270 p->xvel = speed * cos(theta); | |
271 p->yvel = speed * sin(theta); | |
272 p->x = emitter->x + emitter->xvel; | |
273 p->y = emitter->y + emitter->yvel; | |
274 p->isActive = 1; | |
275 p->type = dust; | |
276 p->color[0] = emitter->color[0]; | |
277 p->color[1] = emitter->color[1]; | |
278 p->color[2] = emitter->color[2]; | |
279 p->color[3] = 255; | |
280 | |
281 p->size = 15; | |
282 | |
283 num_active_particles++; | |
284 | |
285 } | |
286 | |
287 } | |
288 | |
289 void spawnParticleFromEmitter(struct particle *emitter) { | |
290 | |
291 if (num_active_particles >= MAX_PARTICLES) return; | |
292 | |
293 struct particle *p = &particles[num_active_particles]; | |
294 p->x = emitter->x + randomFloat(-3.0, 3.0); | |
295 p->y = emitter->y + emitter->size / 2.0f; | |
296 p->xvel = emitter->xvel + randomFloat(-0.005, 0.005); | |
297 p->yvel = emitter->yvel + 0.1; | |
298 p->color[0] = (0.8f + randomFloat(-0.1, 0.0)) * 255; | |
299 p->color[1] = (0.4f + randomFloat(-0.1, 0.1)) * 255; | |
300 p->color[2] = (0.0f + randomFloat(0.0, 0.2)) * 255; | |
301 p->color[3] = (0.7f) * 255; | |
302 p->size = 10; | |
303 p->type = trail; | |
304 p->isActive = 1; | |
305 num_active_particles++; | |
306 | |
307 } | |
308 | |
309 void spawnEmitterParticle(int x, int y) { | |
310 | |
311 if (num_active_particles >= MAX_PARTICLES) return; | |
312 | |
313 struct particle *p = &particles[num_active_particles]; | |
314 p->x = x; | |
315 p->y = SCREEN_HEIGHT; | |
316 p->xvel = 0; | |
317 p->yvel = -sqrt(2*ACCEL*(SCREEN_HEIGHT-y) + VEL_BEFORE_EXPLODE * VEL_BEFORE_EXPLODE); | |
318 p->color[0] = 1.0 * 255; | |
319 p->color[1] = 0.4 * 255; | |
320 p->color[2] = 0.4 * 255; | |
321 p->color[3] = 1.0f * 255; | |
322 p->size = 10; | |
323 p->type = emitter; | |
324 p->framesSinceEmission = 0; | |
325 p->isActive = 1; | |
326 num_active_particles++; | |
327 } | |
328 | |
329 void initializeParticles(void) { | |
330 | |
331 num_active_particles = 0; | |
332 | |
333 } | |
334 | |
335 /* | |
336 loads the brush texture | |
337 */ | |
338 void initializeTexture() { | |
339 SDL_Surface *bmp_surface; | |
340 bmp_surface = SDL_LoadBMP("stroke.bmp"); | |
341 if (bmp_surface == NULL) { | |
342 fatalError("could not load stroke.bmp"); | |
343 } | |
344 flashTextureID = SDL_CreateTextureFromSurface(SDL_PIXELFORMAT_ABGR8888, bmp_surface); | |
345 SDL_FreeSurface(bmp_surface); | |
346 if (flashTextureID == 0) { | |
347 fatalError("could not create brush texture"); | |
348 } | |
349 glEnable(GL_TEXTURE_2D); | |
350 glEnable(GL_BLEND); | |
351 glBlendFunc(GL_SRC_ALPHA, GL_ONE); | |
352 } | |
353 | |
354 int main(int argc, char *argv[]) { | |
355 | |
356 SDL_WindowID windowID; /* ID of main window */ | |
357 Uint32 startFrame; /* time frame began to process */ | |
358 Uint32 endFrame; /* time frame ended processing */ | |
359 Uint32 delay; /* time to pause waiting to draw next frame */ | |
360 int done; /* should we clean up and exit? */ | |
361 | |
362 struct glformat requested, obtained; | |
363 | |
364 /* initialize SDL */ | |
365 if (SDL_Init(SDL_INIT_VIDEO) < 0) { | |
366 fatalError("Could not initialize SDL"); | |
367 } | |
368 | |
369 srand(time(NULL)); | |
370 | |
371 SDL_GL_LoadLibrary(NULL); | |
372 | |
373 SDL_memset(&requested, 0, sizeof(requested)); | |
374 requested.SDL_GL_RED_SIZE = 5; | |
375 requested.SDL_GL_GREEN_SIZE = 6; | |
376 requested.SDL_GL_BLUE_SIZE = 5; | |
377 requested.SDL_GL_ALPHA_SIZE = 0; | |
378 requested.SDL_GL_DEPTH_SIZE = 0; | |
379 requested.SDL_GL_RETAINED_BACKING = 0; | |
380 requested.SDL_GL_ACCELERATED_VISUAL = 1; | |
381 | |
382 setOpenGLAttributes(&requested); | |
383 | |
384 /* create main window and renderer */ | |
385 windowID = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,\ | |
386 SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_BORDERLESS); | |
387 SDL_CreateRenderer(windowID, 0, 0); | |
388 | |
389 printf("Requested:\n"); | |
390 printOpenGLAttributes(&requested); | |
391 | |
392 printf("obtained:\n"); | |
393 getOpenGLAttributes(&obtained); | |
394 printOpenGLAttributes(&obtained); | |
395 | |
396 initializeTexture(); | |
397 | |
398 done = 0; | |
399 /* enter main loop */ | |
400 while(!done) { | |
401 startFrame = SDL_GetTicks(); | |
402 SDL_Event event; | |
403 while (SDL_PollEvent(&event)) { | |
404 if (event.type == SDL_QUIT) { | |
405 done = 1; | |
406 } | |
407 if (event.type == SDL_MOUSEBUTTONDOWN) { | |
408 printf("mouse down\n"); | |
409 int which = event.button.which; | |
410 int x, y; | |
411 SDL_SelectMouse(which); | |
412 SDL_GetMouseState(&x, &y); | |
413 spawnEmitterParticle(x, y); | |
414 } | |
415 } | |
416 render(); | |
417 endFrame = SDL_GetTicks(); | |
418 | |
419 /* figure out how much time we have left, and then sleep */ | |
420 delay = MILLESECONDS_PER_FRAME - (endFrame - startFrame); | |
421 if (delay > MILLESECONDS_PER_FRAME) { | |
422 delay = MILLESECONDS_PER_FRAME; | |
423 } | |
424 if (delay > 0) { | |
425 SDL_Delay(delay); | |
426 } | |
427 | |
428 //SDL_Delay(delay); | |
429 } | |
430 | |
431 /* delete textures */ | |
432 | |
433 /* shutdown SDL */ | |
434 SDL_Quit(); | |
435 | |
436 return 0; | |
437 | |
438 } |