Rename GP_Context -> GP_Pixmap
[gfxprim.git] / demos / particle / space.c
blob8dfc956d656aa673727416d3762f5336eac3d65c
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
18 * *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
23 #include <time.h>
24 #include "space.h"
26 struct space *space_create(unsigned int particle_count, int min_w, int min_h,
27 int max_w, int max_h)
29 struct space *new = malloc(sizeof(struct space) +
30 sizeof(struct particle) * particle_count);
32 if (new == NULL)
33 return NULL;
35 new->particle_count = particle_count;
36 new->min_w = min_w;
37 new->min_h = min_h;
38 new->max_w = max_w;
39 new->max_h = max_h;
41 new->gax = 0;
42 new->gay = 0;
44 new->elasticity = (1<<8) - (1<<6);
45 new->mass_kappa = 1<<1;
47 unsigned int i;
49 srandom(time(NULL));
51 for (i = 0; i < particle_count; i++) {
52 new->particles[i].x = random() % (max_w - min_w) + min_w;
53 new->particles[i].y = random() % (max_h - min_h) + min_h;
54 new->particles[i].vx = random() % 40 - 20;
55 new->particles[i].vy = random() % 40 - 20;
56 // new->particles[i].vx = 0;
57 // new->particles[i].vy = 0;
60 return new;
63 void space_destroy(struct space *space)
65 free(space);
68 #define SQUARE(x) ((x) * (x))
70 void space_draw_particles(GP_Pixmap *pixmap, struct space *space)
72 unsigned int i;
74 GP_Fill(pixmap, 0x000000);
76 for (i = 0; i < space->particle_count; i++) {
77 GP_Pixel color;
79 GP_Coord x = space->particles[i].x;
80 GP_Coord y = space->particles[i].y;
81 GP_Coord a1 = GP_FP_1 * 4;
82 GP_Coord a2 = GP_FP_1_2 * 2;
85 if (i == 0) {
86 x = GP_FP_1 * 10 + GP_FP_1_2;
87 y = GP_FP_1 * 10 + GP_FP_1_2;
91 color = GP_RGBToPixmapPixel(0xee, 0xee, 0xee, pixmap);
93 GP_PutPixelAA(pixmap, x, y, color);
95 int val = SQUARE(space->particles[i].vx) + SQUARE(space->particles[i].vy);
97 val = sqrt(val) + 0x40;
99 if (val > 255)
100 val = 255;
102 color = GP_RGBToPixmapPixel(val, val, 0x40, pixmap);
104 /* Hexagons */
105 GP_LineAA(pixmap, x - a2, y - a1, x + a2, y - a1, color);
106 // GP_LineAA(pixmap, x + a2, y - a1, x + a1, y - a2, color);
107 GP_LineAA(pixmap, x + a1, y - a2, x + a1, y + a2, color);
108 // GP_LineAA(pixmap, x + a1, y + a2, x + a2, y + a1, color);
109 GP_LineAA(pixmap, x + a2, y + a1, x - a2, y + a1, color);
110 // GP_LineAA(pixmap, x - a2, y + a1, x - a1, y + a2, color);
111 GP_LineAA(pixmap, x - a1, y + a2, x - a1, y - a2, color);
112 // GP_LineAA(pixmap, x - a1, y - a2, x - a2, y - a1, color);
114 GP_PutPixelAA(pixmap, x + a2, y - a1, 0xffffff);
115 GP_PutPixelAA(pixmap, x + a1, y - a2, 0xffffff);
117 GP_PutPixelAA(pixmap, x + a1, y + a2, 0xffffff);
118 GP_PutPixelAA(pixmap, x + a2, y + a1, 0xffffff);
120 GP_PutPixelAA(pixmap, x - a2, y + a1, 0xffffff);
121 GP_PutPixelAA(pixmap, x - a1, y + a2, 0xffffff);
123 GP_PutPixelAA(pixmap, x - a1, y - a2, 0xffffff);
124 GP_PutPixelAA(pixmap, x - a2, y - a1, 0xffffff);
129 static void central_gravity(struct space *space, int time)
131 unsigned int i;
133 for (i = 0; i < space->particle_count; i++) {
134 space->particles[i].vx += space->gax * time;
135 space->particles[i].vy += space->gay * time;
139 #define DIST_X(space, i, j) ((space)->particles[i].x - (space)->particles[j].x)
140 #define DIST_Y(space, i, j) ((space)->particles[i].y - (space)->particles[j].y)
141 #define SIGN(x) ((x) < 0 ? -1 : 1)
143 static void gravity_forces(struct space *space, int time)
145 unsigned int i, j;
147 for (i = 0; i < space->particle_count; i++)
148 for (j = 0; j < space->particle_count; j++) {
149 int dist_x = DIST_X(space, i, j);
150 int dist_y = DIST_Y(space, i, j);
152 int dist_squared = (SQUARE((dist_x + (1<<7))>>8) + SQUARE((dist_y + (1<<7))>>8)) + (1<<8);
153 int dist = ((int)sqrt(dist_squared))<<4;
155 if (dist < (2<<8))
156 dist = -(dist>>1);
157 else if (dist < (8<<8))
158 dist = dist>>1;
161 int a = GP_FP_DIV(space->mass_kappa, dist_squared) * time;
163 space->particles[i].vx -= (a * dist_x) / dist;
164 space->particles[i].vy -= (a * dist_y) / dist;
168 void space_time_tick(struct space *space, int time)
170 unsigned int i;
172 central_gravity(space, time);
173 gravity_forces(space, time);
175 for (i = 0; i < space->particle_count; i++) {
177 if ((space->particles[i].x < space->min_w && space->particles[i].vx < 0) ||
178 (space->particles[i].x >= space->max_w && space->particles[i].vx > 0))
179 space->particles[i].vx = GP_FP_MUL(space->particles[i].vx, -space->elasticity);
181 if ((space->particles[i].y < space->min_h && space->particles[i].vy < 0) ||
182 (space->particles[i].y >= space->max_h && space->particles[i].vy > 0))
183 space->particles[i].vy = GP_FP_MUL(space->particles[i].vy, -space->elasticity);
185 space->particles[i].x += space->particles[i].vx * time;
186 space->particles[i].y += space->particles[i].vy * time;