home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////////////////////
- // Game Programming All In One, Third Edition
- // Particles Program
- /////////////////////////////////////////////////////////////////////////
-
- #include "math.h"
- #include "allegro.h"
-
- #define NUM 4000
- #define STARTING_MASS 0.00001
-
- #define GRAY makecol(30,30,30)
- #define RED makecol(150,0,0)
-
- //particle structure
- struct particle
- {
- int alive;
- double mass;
- double x, y;
- long oldX, oldY;
- long xp;
- long yp;
- double ax;
- double ay;
- double vx;
- double vy;
-
- }p[NUM];
-
- int CX, CY;
- int living=0;
- int biggest=0;
-
- void resetparticle(int n);
- void updateparticles();
- void resetall();
-
-
- void attract(struct particle *A, struct particle *B)
- {
- double distance;
- double dist, distX, distY;
- double transX, transY;
-
- //increase position by velocity value
- A->x += A->vx;
- A->y += A->vy;
-
- //calculate distance between particles
- distX = A->x - B->x;
- distY = A->y - B->y;
- dist = distX * distX + distY * distY;
- if (dist != 0)
- distance = 1 / dist;
- else
- distance = 0;
-
- transX = distX * distance;
- transY = distY * distance;
-
- //acceleration = mass * distance
- A->ax = -1 * B->mass * transX;
- A->ay = -1 * B->mass * transY;
-
- //increase velocity by acceleration value
- A->vx += A->ax;
- A->vy += A->ay;
-
- //scale position to the screen
- A->xp = A->x;
- A->yp = A->y;
-
- }
-
- void drawparticle(int n, int color)
- {
- int rad=1;
- float m=p[n].mass;
-
- if (m > STARTING_MASS * 10) {
- rad++;
- if (m > STARTING_MASS * 50) rad++;
- if (m > STARTING_MASS * 100) rad++;
- if (m > STARTING_MASS * 200) rad++;
- if (m > STARTING_MASS * 400) rad++;
- if (m > STARTING_MASS * 800) rad++;
- circle(screen, p[n].xp, p[n].yp, rad, color);
- }
- else
- putpixel(screen, p[n].xp, p[n].yp, color);
- }
-
- int collided(int p1, int p2)
- {
- return (p[p1].xp == p[p2].xp && p[p1].yp == p[p2].yp);
- }
-
- void update()
- {
- int n;
- int i;
- living=0;
-
- //calculate gravity for each particle
- for (n = 0; n < NUM; n++)
- if (p[n].alive)
- {
- living++;
-
- //track the biggest object
- if (p[n].mass > p[biggest].mass)
- biggest = n;
-
- //erase old particle
- drawparticle(n, GRAY);
-
- //apply gravity from every particle to every other particle
- for (i = 0; i < NUM; i++)
- if (p[i].alive)
- {
- if (i != n)
- {
- attract(&p[n], &p[i]);
- if (collided(n,i))
- {
- //collision: larger object absorbs smaller one
- if (p[n].mass >= p[i].mass)
- {
- p[n].mass += p[i].mass;
- p[i].alive = 0;
- drawparticle(i, RED);
- }
- else
- {
- p[i].mass += p[n].mass;
- p[n].alive = 0;
- drawparticle(n, RED);
- }
-
- }
- }
- }
-
- //plot the particle
- drawparticle(n, 7);
-
- //keep track of the current position
- p[n].oldX = p[n].xp;
- p[n].oldY = p[n].yp;
- }
-
- }
-
-
- void resetparticle(int n)
- {
- p[n].alive = 1;
- p[n].mass = STARTING_MASS;
- p[n].ax = 0;
- p[n].ay = 0;
- p[n].xp = 0;
- p[n].yp = 0;
- p[n].x = rand() % SCREEN_W;
- p[n].y = rand() % SCREEN_H;
- p[n].vx = 0;
- p[n].vy = 0;
- }
-
-
- void resetall()
- {
- int n;
-
- for (n = 0; n < NUM; n++)
- resetparticle(n);
-
- }
-
- void main(void)
- {
- int done=0;
- int start=0;
- int counter;
-
- //initialize some stuff
- allegro_init();
- install_keyboard();
- install_timer();
- srand(time(NULL));
-
- //initialize video mode
- int ret = set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 800, 600, 0, 0);
- if (ret != 0) {
- allegro_message(allegro_error);
- return;
- }
-
- //display screen resolution
- textprintf_ex(screen, font, 0, 0, 15, 0,
- "Star Builder %dx%d ESC to quit",
- SCREEN_W, SCREEN_H);
-
- resetall();
-
- while(!done)
- {
-
- //slow down the simulation
- if (clock() > start + 1) {
- start = clock();
-
- update();
- textprintf_ex(screen, font, 400, 0, 15, 0,
- "Count:%4d - Biggest:%4d (mass=%1.6f)",
- living, biggest, p[biggest].mass);
- }
-
-
- if (keypressed()) {
- if (key[KEY_ESC])
- done++;
- }
- }
-
- //end program
- allegro_exit();
- }
-
- END_OF_MAIN();
-
-