Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 1 | /* Fireworks demo written by Dave Ashley */ |
2 | /* dash@xdr.com */ |
||
3 | /* http://www.xdr.com/dash */ |
||
4 | /* Sat Jun 13 02:46:09 PDT 1998 */ |
||
5 | /* This is my first attempt at an SDL program */ |
||
6 | /* See the SDL home page http://www.devolution.com/~slouken/projects/SDL/ */ |
||
7 | |||
8 | #include |
||
9 | #include |
||
10 | #include |
||
11 | #include |
||
12 | |||
13 | #include "SDL.h" |
||
14 | |||
15 | #define XSIZE 640 |
||
16 | #define YSIZE 480 |
||
17 | |||
18 | SDL_Surface *thescreen; |
||
19 | unsigned char *vmem1, *vmem2; |
||
20 | int mousex,mousey; |
||
21 | SDL_Color themap[256]; |
||
22 | |||
23 | int scrlock() |
||
24 | { |
||
25 | if(SDL_MUSTLOCK(thescreen)) |
||
26 | { |
||
27 | if ( SDL_LockSurface(thescreen) < 0 ) |
||
28 | { |
||
29 | SDL_printf("Couldn't lock display surface: %s\n", |
||
30 | SDL_GetError()); |
||
31 | return -1; |
||
32 | } |
||
33 | } |
||
34 | return 0; |
||
35 | } |
||
36 | void scrunlock(void) |
||
37 | { |
||
38 | if(SDL_MUSTLOCK(thescreen)) |
||
39 | SDL_UnlockSurface(thescreen); |
||
40 | SDL_UpdateRect(thescreen, 0, 0, 0, 0); |
||
41 | } |
||
42 | |||
43 | #define MOUSEFRAC 2 |
||
44 | #define MAXBLOBS 512 |
||
45 | #define BLOBFRAC 6 |
||
46 | #define BLOBGRAVITY 5 |
||
47 | #define THRESHOLD 20 |
||
48 | #define SMALLSIZE 3 |
||
49 | #define BIGSIZE 6 |
||
50 | |||
51 | #define ABS(x) ((x)<0 ? -(x) : (x)) |
||
52 | |||
53 | int explodenum; |
||
54 | |||
55 | char sizes[]={2,3,4,5,8,5,4,3}; |
||
56 | |||
57 | |||
58 | struct blob { |
||
59 | struct blob *blobnext; |
||
60 | int blobx; |
||
61 | int bloby; |
||
62 | int blobdx; |
||
63 | int blobdy; |
||
64 | int bloblife; |
||
65 | int blobsize; |
||
66 | } *blobs,*freeblobs,*activeblobs; |
||
67 | |||
68 | |||
69 | unsigned char **mul640; |
||
70 | int oldmode; |
||
71 | |||
72 | char sqrttab[]={ |
||
73 | 0,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3, |
||
74 | 4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5, |
||
75 | 5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6, |
||
76 | 6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, |
||
77 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, |
||
78 | 8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, |
||
79 | 9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10, |
||
80 | 10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11, |
||
81 | 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, |
||
82 | 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, |
||
83 | 12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13, |
||
84 | 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, |
||
85 | 13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, |
||
86 | 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, |
||
87 | 14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, |
||
88 | 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 |
||
89 | }; |
||
90 | |||
91 | |||
92 | void nomem(void) |
||
93 | { |
||
94 | SDL_printf("Not enough low memory!\n"); |
||
95 | SDL_Quit(); |
||
96 | exit(1); |
||
97 | } |
||
98 | |||
99 | |||
100 | |||
101 | void fire(unsigned char *p1,unsigned char *p2,int pitch,char *map) |
||
102 | { |
||
103 | int x,y; |
||
104 | unsigned char *p3, *p4; |
||
105 | |||
106 | for(y=2;y |
||
107 | { |
||
108 | for(x=0;x |
||
109 | { |
||
110 | p3 = p1+y*XSIZE+x; |
||
111 | p4 = p2+y*pitch+x; |
||
112 | *p4=map[*p3+p3[-XSIZE]+p3[-XSIZE-1]+p3[-XSIZE+1]+p3[-1]+p3[1]+p3[-XSIZE-XSIZE-1]+p3[-XSIZE-XSIZE]+p3[-XSIZE-XSIZE+1]]; |
||
113 | } |
||
114 | } |
||
115 | } |
||
116 | |||
117 | void disk(x,y,rad) |
||
118 | { |
||
119 | unsigned char *p; |
||
120 | int i,j,k,aj; |
||
121 | int rad2=rad*rad; |
||
122 | int w; |
||
123 | |||
124 | |||
125 | for(j=-rad;j<=rad;j++) |
||
126 | { |
||
127 | w=sqrttab[rad2-j*j]; |
||
128 | aj=ABS(j)<<2; |
||
129 | if(w) |
||
130 | { |
||
131 | p=mul640[y+j]+x-w; |
||
132 | k=w+w+1; |
||
133 | i=-w; |
||
134 | while(k--) {*p++=255-(ABS(i)<<2)-aj;i++;} |
||
135 | } |
||
136 | } |
||
137 | } |
||
138 | void trydisk(void) |
||
139 | { |
||
140 | if(mousex>10 && mousex |
||
141 | disk(mousex,mousey,8); |
||
142 | } |
||
143 | |||
144 | void addblob(void) |
||
145 | { |
||
146 | int dx,dy; |
||
147 | struct blob *ablob; |
||
148 | |||
149 | if(!freeblobs) return; |
||
150 | dx=(rand()&255)-128; |
||
151 | dy=(rand()%200)+340; |
||
152 | ablob=freeblobs; |
||
153 | freeblobs=freeblobs->blobnext; |
||
154 | ablob->bloblife=(rand()&511)+256; |
||
155 | ablob->blobdx=dx; |
||
156 | ablob->blobdy=dy; |
||
157 | ablob->blobx=(256+(rand()&127))< |
||
158 | ablob->bloby=2< |
||
159 | ablob->blobnext=activeblobs; |
||
160 | ablob->blobsize=BIGSIZE; |
||
161 | activeblobs=ablob; |
||
162 | } |
||
163 | void moveblobs(void) |
||
164 | { |
||
165 | struct blob **lastblob,*ablob; |
||
166 | int x,y; |
||
167 | |||
168 | lastblob=&activeblobs; |
||
169 | while(ablob=*lastblob) |
||
170 | { |
||
171 | x=ablob->blobx>>BLOBFRAC; |
||
172 | y=ablob->bloby>>BLOBFRAC; |
||
173 | if(!--ablob->bloblife || y<0 || x<10 || x>XSIZE-10) |
||
174 | { |
||
175 | *lastblob=ablob->blobnext; |
||
176 | ablob->blobnext=freeblobs; |
||
177 | freeblobs=ablob; |
||
178 | continue; |
||
179 | } |
||
180 | ablob->blobx+=ablob->blobdx; |
||
181 | ablob->bloby+=ablob->blobdy; |
||
182 | ablob->blobdy-=BLOBGRAVITY; |
||
183 | lastblob=&ablob->blobnext; |
||
184 | } |
||
185 | } |
||
186 | void putblobs(void) |
||
187 | { |
||
188 | struct blob *ablob,*ablob2,*temp; |
||
189 | int x,y,dy; |
||
190 | int i,size; |
||
191 | long x2,y2,vel; |
||
192 | |||
193 | ablob=activeblobs; |
||
194 | activeblobs=0; |
||
195 | while(ablob) |
||
196 | { |
||
197 | dy=ablob->blobdy; |
||
198 | if(ablob->blobsize!=SMALLSIZE && (dy>-THRESHOLD && dy |
||
199 | { |
||
200 | i=explodenum; |
||
201 | while(i-- && freeblobs) |
||
202 | { |
||
203 | ablob2=freeblobs; |
||
204 | freeblobs=freeblobs->blobnext; |
||
205 | ablob2->blobx=ablob->blobx; |
||
206 | ablob2->bloby=ablob->bloby; |
||
207 | for(;;) |
||
208 | { |
||
209 | x2=(rand()&511)-256; |
||
210 | y2=(rand()&511)-256; |
||
211 | vel=x2*x2+y2*y2; |
||
212 | if(vel>0x3000 && vel<0x10000L) break; |
||
213 | } |
||
214 | ablob2->blobdx=ablob->blobdx+x2; |
||
215 | ablob2->blobdy=ablob->blobdy+y2; |
||
216 | ablob2->bloblife=16+(rand()&31); |
||
217 | ablob2->blobsize=SMALLSIZE; |
||
218 | ablob2->blobnext=activeblobs; |
||
219 | activeblobs=ablob2; |
||
220 | ablob->bloblife=1; |
||
221 | } |
||
222 | } |
||
223 | x=ablob->blobx>>BLOBFRAC; |
||
224 | y=ablob->bloby>>BLOBFRAC; |
||
225 | size=ablob->blobsize; |
||
226 | if(size==BIGSIZE && ablob->blobdy>0 && ablob->blobdy<200) |
||
227 | size=sizes[ablob->bloblife&7]; |
||
228 | if(x>10 && x |
||
229 | disk(x,YSIZE-1-y,size); |
||
230 | temp=ablob; |
||
231 | ablob=ablob->blobnext; |
||
232 | temp->blobnext=activeblobs; |
||
233 | activeblobs=temp; |
||
234 | } |
||
235 | } |
||
236 | |||
237 | |||
238 | |||
239 | #define RATE 1 |
||
240 | void normal(char *map) |
||
241 | { |
||
242 | int i,j; |
||
243 | for(i=0;i<8192;i++) |
||
244 | { |
||
245 | j=i/9; |
||
246 | map[i]=j<256 ? (j>=RATE ? j-RATE : 0) : 255; |
||
247 | } |
||
248 | } |
||
249 | void bright(char *map) |
||
250 | { |
||
251 | int i; |
||
252 | for(i=0;i<8192;i++) map[i]=i>>3<255 ? (i>>3) : 255; |
||
253 | } |
||
254 | |||
255 | void updatemap(void) |
||
256 | { |
||
257 | SDL_SetColors(thescreen, themap, 0, 256); |
||
258 | } |
||
259 | |||
260 | |||
261 | void loadcolor(int n,int r,int g,int b) |
||
262 | { |
||
263 | themap[n].r=r<<2; |
||
264 | themap[n].g=g<<2; |
||
265 | themap[n].b=b<<2; |
||
266 | } |
||
267 | |||
268 | |||
269 | void loadcolors(unsigned int which) |
||
270 | { |
||
271 | int i,j; |
||
272 | int r,g,b; |
||
273 | |||
274 | which%=11; |
||
275 | for(i=0;i<256;i++) |
||
276 | { |
||
277 | switch(which) |
||
278 | { |
||
279 | case 0: |
||
280 | if(i<64) loadcolor(i,0,0,0); |
||
281 | else if(i<128) loadcolor(i,i-64,0,0); |
||
282 | else if(i<192) loadcolor(i,63,i-128,0); |
||
283 | else loadcolor(i,63,63,i-192); |
||
284 | break; |
||
285 | case 1: |
||
286 | if(i<64) loadcolor(i,0,0,0); |
||
287 | else if(i<128) loadcolor(i,0,0,i-64); |
||
288 | else loadcolor(i,(i-128)>>1,(i-128)>>1,63); |
||
289 | break; |
||
290 | case 2: |
||
291 | loadcolor(i,i>>2,i>>2,i>>2); |
||
292 | break; |
||
293 | case 3: |
||
294 | r=rand()&0x3f; |
||
295 | g=rand()&0x3f; |
||
296 | b=rand()&0x3f; |
||
297 | loadcolor(i,r*i>>8,g*i>>8,b*i>>8); |
||
298 | break; |
||
299 | case 4: |
||
300 | loadcolor(i,i>>2,0,0); |
||
301 | break; |
||
302 | case 5: |
||
303 | loadcolor(i,0,i>>2,0); |
||
304 | break; |
||
305 | case 6: |
||
306 | loadcolor(i,0,0,i>>2); |
||
307 | break; |
||
308 | case 7: |
||
309 | j=i&15; |
||
310 | if(i&16) j=15-j; |
||
311 | j=(i>>2)*j/16; |
||
312 | loadcolor(i,j,j,j); |
||
313 | break; |
||
314 | case 8: |
||
315 | j=0; |
||
316 | if(i>8 && i<128) j=63; |
||
317 | loadcolor(i,j,j,j); |
||
318 | break; |
||
319 | case 9: |
||
320 | j=31-(i&31)<<1; |
||
321 | r=i&32 ? j : 0; |
||
322 | g=i&64 ? j : 0; |
||
323 | b=i&128 ? j : 0; |
||
324 | loadcolor(i,r,g,b); |
||
325 | break; |
||
326 | case 10: |
||
327 | j=(i&15)<<2; |
||
328 | if(i&16) j=63-j; |
||
329 | r=i&32 ? j : 0; |
||
330 | g=i&64 ? j : 0; |
||
331 | b=i&128 ? j : 0; |
||
332 | loadcolor(i,r,g,b); |
||
333 | break; |
||
334 | } |
||
335 | } |
||
336 | updatemap(); |
||
337 | } |
||
338 | |||
339 | int main(int argc, char *argv[]) |
||
340 | { |
||
341 | int i,k; |
||
342 | char *remap,*remap2; |
||
343 | unsigned char *p1, *p2; |
||
344 | long frames; |
||
345 | int flash; |
||
346 | int whichmap; |
||
347 | int key; |
||
348 | int ispaused; |
||
349 | unsigned long videoflags; |
||
350 | int done; |
||
351 | int now; |
||
352 | SDL_Event event; |
||
353 | long starttime; |
||
354 | int buttonstate; |
||
355 | |||
356 | srand(time(NULL)); |
||
357 | if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) |
||
358 | { |
||
359 | SDL_printf("Couldn't initialize SDL: %s\n",SDL_GetError()); |
||
360 | exit(1); |
||
361 | } |
||
362 | videoflags = SDL_SWSURFACE; |
||
363 | |||
364 | thescreen = SDL_SetVideoMode(XSIZE, YSIZE, 8, videoflags); |
||
365 | if ( thescreen == NULL ) |
||
366 | { |
||
367 | SDL_printf("Couldn't set display mode: %s\n", |
||
368 | SDL_GetError()); |
||
369 | SDL_Quit(); |
||
370 | exit(5); |
||
371 | } |
||
372 | |||
373 | vmem1=NULL; |
||
374 | vmem2=malloc(XSIZE*YSIZE); |
||
375 | if(!vmem2) nomem(); |
||
376 | mul640=malloc(YSIZE*sizeof(char *)); |
||
377 | if(!mul640) nomem(); |
||
378 | remap=malloc(16384); |
||
379 | if(!remap) nomem(); |
||
380 | remap2=malloc(16384); |
||
381 | if(!remap2) nomem(); |
||
382 | blobs=malloc(MAXBLOBS*sizeof(struct blob)); |
||
383 | if(!blobs) nomem(); |
||
384 | |||
385 | SDL_printf("Fire demo by David Ashley (dash@xdr.com)"); |
||
386 | SDL_printf("1 = Change color map"); |
||
387 | SDL_printf("2 = Randomly change color map"); |
||
388 | SDL_printf("p = Pause"); |
||
389 | SDL_printf("spc = Fire"); |
||
390 | SDL_printf("esc = Exit"); |
||
391 | SDL_printf("Left mouse button = paint"); |
||
392 | SDL_printf("Right mouse button, CR = ignite atmosphere"); |
||
393 | |||
394 | freeblobs=activeblobs=0; |
||
395 | for(i=0;i |
||
396 | { |
||
397 | blobs[i].blobnext=freeblobs; |
||
398 | freeblobs=blobs+i; |
||
399 | } |
||
400 | |||
401 | normal(remap); |
||
402 | bright(remap2); |
||
403 | |||
404 | |||
405 | flash=0; |
||
406 | whichmap=0; |
||
407 | loadcolors(whichmap); |
||
408 | frames=0; |
||
409 | ispaused=0; |
||
410 | addblob(); |
||
411 | done = 0; |
||
412 | now=0; |
||
413 | starttime=SDL_GetTicks(); |
||
414 | buttonstate=0; |
||
415 | mousex=mousey=0; |
||
416 | |||
417 | while(!done) |
||
418 | { |
||
419 | if ( scrlock() < 0 ) continue; |
||
420 | frames++; |
||
421 | if ( vmem1 != (unsigned char *)thescreen->pixels ) |
||
422 | { |
||
423 | p1=vmem1=thescreen->pixels; |
||
424 | for (i=0;i |
||
425 | { |
||
426 | mul640[i]=i*thescreen->pitch+vmem1; |
||
427 | memset(p1,0,XSIZE); |
||
428 | p1+=thescreen->pitch; |
||
429 | } |
||
430 | } |
||
431 | if(!ispaused) |
||
432 | { |
||
433 | now++; |
||
434 | if(!flash) |
||
435 | { |
||
436 | if(explodenum>96 && explodenum<160 && !(rand()&511) || (buttonstate&8)) |
||
437 | flash=60; |
||
438 | } else --flash; |
||
439 | explodenum=(now>>4)+1;if(explodenum==320) now=0; |
||
440 | if(explodenum>256) explodenum=256; |
||
441 | if(!(rand()&31)) |
||
442 | addblob(); |
||
443 | moveblobs(); |
||
444 | putblobs(); |
||
445 | if(buttonstate&2) trydisk(); |
||
446 | p1=vmem1; |
||
447 | p2=vmem2; |
||
448 | k=thescreen->pitch; |
||
449 | for(i=0;i |
||
450 | { |
||
451 | memcpy(p2,p1,XSIZE); |
||
452 | p2+=XSIZE; |
||
453 | p1+=k; |
||
454 | } |
||
455 | fire(vmem2,vmem1,k,flash ? remap2 :remap); |
||
456 | } |
||
457 | scrunlock(); |
||
458 | |||
459 | while(SDL_PollEvent(&event)) |
||
460 | { |
||
461 | switch (event.type) |
||
462 | { |
||
463 | case SDL_MOUSEBUTTONDOWN: |
||
464 | case SDL_MOUSEBUTTONUP: |
||
465 | if ( event.button.state == SDL_PRESSED ) |
||
466 | buttonstate|=1< |
||
467 | else |
||
468 | buttonstate&=~(1< |
||
469 | mousex=event.button.x; |
||
470 | mousey=event.button.y; |
||
471 | if(!ispaused && buttonstate&2) trydisk(); |
||
472 | break; |
||
473 | case SDL_MOUSEMOTION: |
||
474 | mousex=event.motion.x; |
||
475 | mousey=event.motion.y; |
||
476 | if(!ispaused && buttonstate&2) trydisk(); |
||
477 | break; |
||
478 | case SDL_KEYDOWN: |
||
479 | key=event.key.keysym.sym; |
||
480 | if(key==SDLK_RETURN) {flash=60;break;} |
||
481 | if(key==SDLK_1 || key==SDLK_2) |
||
482 | { |
||
483 | if(key==SDLK_1) |
||
484 | ++whichmap; |
||
485 | else |
||
486 | whichmap=rand(); |
||
487 | loadcolors(whichmap); |
||
488 | break; |
||
489 | } |
||
490 | if(key==SDLK_ESCAPE) {done=1;break;} |
||
491 | if(key==SDLK_SPACE && !ispaused) {addblob();break;} |
||
492 | if(key==SDLK_p) {ispaused=!ispaused;break;} |
||
493 | break; |
||
494 | case SDL_QUIT: |
||
495 | done = 1; |
||
496 | break; |
||
497 | default: |
||
498 | break; |
||
499 | } |
||
500 | } |
||
501 | } |
||
502 | |||
503 | starttime=SDL_GetTicks()-starttime; |
||
504 | if(!starttime) starttime=1; |
||
505 | SDL_Quit(); |
||
506 | SDL_printf("fps = %d\n",1000*frames/starttime); |
||
507 | exit(0); |
||
508 | } |