7 static void putpixel(struct SDL_Surface *screen, const int x, const int y,
8 const unsigned char r, const unsigned char g,
11 int offset = y * screen->pitch + x * 4;
12 unsigned char *buf = screen->pixels;
19 static void reshape_planet(struct planet *p)
21 p->radius = pow(p->mass / 100, 1 / 3.0);
24 void init_planet(struct planet *p)
32 p->r = get_random() % 256;
33 p->g = get_random() % 256;
34 p->b = get_random() % 256;
36 INIT_LIST_HEAD(&p->list);
40 * setup_planet - set the planet on a "solarsystem"
41 * @p: pointer to struct planet to set up
42 * @mass: mass of the planet to set up
43 * @total_mass: total mass of the system
44 * @radius: maximum radius of the system
47 static void setup_planet(struct planet *p, double mass, double total_mass,
50 double angle = M_PI * 2 * get_random_double();
54 distance = radius * get_random_double();
55 velocity = sqrt(total_mass / radius);
57 velocity *= pow(distance / radius, 0.2);
59 p->pos.x = cos(angle) * distance;
60 p->pos.y = sin(angle) * distance;
62 p->speed.x = -sin(angle) * velocity;
63 p->speed.y = cos(angle) * velocity;
70 void create_planets(struct planet *p, int num, double total_mass, double radius)
74 struct planet *new_planet;
76 for (i = 1; i < num; i++) {
77 new_planet = malloc(sizeof(*new_planet));
78 init_planet(new_planet);
79 list_add(&new_planet->list, &p->list);
80 setup_planet(new_planet,
81 total_mass / num * 2 * get_random_double(),
85 sum += new_planet->mass;
88 printf("Requested mass: %f, got %f\n", total_mass, sum);
91 void draw_planet(SDL_Surface *screen, struct planet *p,
92 const struct camera *cam)
95 float radius = p->radius * cam->zoom;
96 float r2 = radius * radius;
97 int x, x_start, y, x_end, y_end;
99 vector_sub(&p->pos, &cam->pos, &pos);
100 vector_scale(&pos, cam->zoom, &pos);
101 pos.x += screen->w / 2;
102 pos.y += screen->h / 2;
104 y = MAX(pos.y - radius, 0);
106 if (radius * 2 <= 1 ) {
107 if (pos.x >= 0 && pos.x < screen->w &&
108 pos.y >= 0 && pos.y < screen->h)
109 putpixel(screen, (int)pos.x, (int)pos.y,
114 for (; y < MIN(pos.y + radius, screen->h); y++) {
116 unsigned char *buf = screen->pixels;
117 float y2 = (y - pos.y);
119 y2 = sqrt(r2 - y2 * y2);
120 x_start = pos.x - y2;
122 x_start = MAX(0, x_start);
123 x_end = MIN(x_end, screen->w);
125 offset = y * screen->pitch + x_start * 4;
126 for (x = x_start; x < x_end; x++) {
127 buf[offset++] = p->b;
128 buf[offset++] = p->g;
129 buf[offset++] = p->r;
135 int gravitize_planets(struct planet *a, struct planet *b, const double time)
137 struct vector distance, sum;
140 vector_sub(&a->pos, &b->pos, &distance);
142 dist = vector_abs(&distance);
144 /* Return true in case of a collision */
145 if (dist < (a->radius + b->radius))
148 vector_div(&distance, dist, &distance);
150 f = a->mass * b->mass / (dist * dist) * time;
153 vector_scale(&distance, acc, &sum);
154 vector_add(&b->speed, &sum, &b->speed);
157 vector_scale(&distance, acc, &sum);
158 vector_sub(&a->speed, &sum, &a->speed);
164 * Merge planets a and b into planet a
166 * It is left for the caller to deal with the scrap planet b
168 static void _merge_planets(struct planet *a, struct planet *b)
170 struct vector pa, pb, p;
172 vector_scale(&a->speed, a->mass, &pa);
173 vector_scale(&b->speed, b->mass, &pb);
174 vector_add(&pa, &pb, &p);
176 if (a->mass < b->mass)
181 vector_div(&p, a->mass, &a->speed);
185 * Merge planets a and b into a the new planet a, which pointer is
186 * returned to the caller. Planet b is removed from the linked list
187 * and it's memory is freed. The merged planet will retain in the
190 struct planet *merge_planets(struct planet *a, struct planet *b)
192 _merge_planets(a, b);
199 void move_planet(struct planet *p, const double time)
202 vector_scale(&p->speed, time, &tmp);
203 vector_add(&p->pos, &tmp, &p->pos);
206 void print_planet(const struct planet *p)
208 printf("pos: (%f,%f), speed: (%f,%f), mass: %f, radius %f\n",
209 p->pos.x, p->pos.y, p->speed.x, p->speed.y, p->mass, p->radius);