1 /*****************************************************************************
2 * This file is part of gfxprim library. *
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. *
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. *
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 *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
26 struct space
*space_create(unsigned int particle_count
, int min_w
, int min_h
,
29 struct space
*new = malloc(sizeof(struct space
) +
30 sizeof(struct particle
) * particle_count
);
35 new->particle_count
= particle_count
;
44 new->elasticity
= (1<<8) - (1<<6);
45 new->mass_kappa
= 1<<1;
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;
63 void space_destroy(struct space
*space
)
68 #define SQUARE(x) ((x) * (x))
70 void space_draw_particles(GP_Pixmap
*pixmap
, struct space
*space
)
74 GP_Fill(pixmap
, 0x000000);
76 for (i
= 0; i
< space
->particle_count
; i
++) {
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;
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;
102 color
= GP_RGBToPixmapPixel(val
, val
, 0x40, pixmap
);
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
)
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
)
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;
157 else if (dist
< (8<<8))
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
)
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
;