static void reshape_planet(struct planet *p)
{
- p->size = pow(p->mass / 100, 1 / 3.0);
+ p->radius = pow(p->mass / 100, 1 / 3.0);
}
void init_planet(struct planet *p)
{
p->speed.x = 0;
p->speed.y = 0;
- p->pos.x = (signed)(get_random() % 1000) - 500;
- p->pos.y = (signed)(get_random() % 1000) - 500;
- p->mass = get_random() % 1000 + 100;
+ p->pos.x = 0;
+ p->pos.y = 0;
+ p->mass = 0;
reshape_planet(p);
p->r = get_random() % 256;
p->g = get_random() % 256;
INIT_LIST_HEAD(&p->list);
}
+/**
+ * setup_planet - set the planet on a "solarsystem"
+ * @p: pointer to struct planet to set up
+ * @mass: mass of the planet to set up
+ * @total_mass: total mass of the system
+ * @radius: maximum radius of the system
+ */
+
+static void setup_planet(struct planet *p, double mass, double total_mass,
+ double radius)
+{
+ double angle = M_PI * 2 * get_random_double();
+ double velocity;
+ double distance;
+
+ distance = radius * pow(get_random_double(), 2);
+ velocity = sqrt(total_mass / radius);
+
+ velocity *= pow(distance / radius, 0.2);
+
+ p->pos.x = cos(angle) * distance;
+ p->pos.y = sin(angle) * distance;
+
+ p->speed.x = -sin(angle) * velocity;
+ p->speed.y = cos(angle) * velocity;
+
+ p->mass = mass;
+
+ reshape_planet(p);
+}
+
+void create_planets(struct planet *p, int num, double total_mass, double radius)
+{
+ int i;
+ double sum = 0;
+ struct planet *new_planet;
+
+ setup_planet(p,
+ total_mass / num * 2 * get_random_double(),
+ total_mass,
+ radius);
+
+ for (i = 0; i < num; i++) {
+ new_planet = malloc(sizeof(*new_planet));
+ init_planet(new_planet);
+ list_add(&new_planet->list, &p->list);
+ setup_planet(new_planet,
+ total_mass / num * 2 * get_random_double(),
+ total_mass,
+ radius);
+
+ sum += new_planet->mass;
+ }
+}
+
void draw_planet(SDL_Surface *screen, struct planet *p,
const struct camera *cam)
{
struct vector pos;
- int size = p->size * cam->zoom;
- int x, x_start, y, x_end, y_end;
+ float radius = p->radius * cam->zoom;
+ float r2 = radius * radius;
+ int x, x_start, y, x_end;
vector_sub(&p->pos, &cam->pos, &pos);
vector_scale(&pos, cam->zoom, &pos);
pos.x += screen->w / 2;
pos.y += screen->h / 2;
- x_start = MAX(pos.x - size, 0);
- y = MAX(pos.y - size, 0);
-
- x_end = MIN(pos.x + size + 1, screen->w);
- y_end = MIN(pos.y + size + 1, screen->h);
-
- for (; y < y_end; y++)
- for (x = x_start; x < x_end; x++)
- putpixel(screen, x, y, p->r, p->g, p->b);
+ y = MAX(pos.y - radius, 0);
+
+ if (radius * 2 <= 1) {
+ if (pos.x >= 0 && pos.x < screen->w &&
+ pos.y >= 0 && pos.y < screen->h)
+ putpixel(screen, (int)pos.x, (int)pos.y,
+ p->r, p->g, p->b);
+ return;
+ }
+
+ for (; y < MIN(pos.y + radius, screen->h); y++) {
+ int offset;
+ unsigned char *buf = screen->pixels;
+ float y2 = (y - pos.y);
+
+ y2 = sqrt(r2 - y2 * y2);
+ x_start = pos.x - y2;
+ x_end = pos.x + y2;
+ x_start = MAX(0, x_start);
+ x_end = MIN(x_end, screen->w);
+
+ offset = y * screen->pitch + x_start * 4;
+ for (x = x_start; x < x_end; x++) {
+ buf[offset++] = p->b;
+ buf[offset++] = p->g;
+ buf[offset++] = p->r;
+ offset++;
+ }
+ }
}
int gravitize_planets(struct planet *a, struct planet *b, const double time)
dist = vector_abs(&distance);
/* Return true in case of a collision */
- if (dist < (a->size + b->size))
+ if (dist < (a->radius + b->radius))
return 1;
vector_div(&distance, dist, &distance);
- f = a->mass * b->mass / (dist * dist + 5) * time;
+ f = a->mass * b->mass / (dist * dist) * time;
acc = f / b->mass;
vector_scale(&distance, acc, &sum);
void print_planet(const struct planet *p)
{
- printf("pos: (%f,%f), speed: (%f,%f), mass: %f, size %f\n",
- p->pos.x, p->pos.y, p->speed.x, p->speed.y, p->mass, p->size);
+ printf("pos: (%f,%f), speed: (%f,%f), mass: %f, radius %f\n",
+ p->pos.x, p->pos.y, p->speed.x, p->speed.y, p->mass, p->radius);
}