--- /dev/null
+*.o
+*~
+.*.d
+TAGS
+sdl-planet
--- /dev/null
+SDL_CONFIG=$(shell sdl-config --cflags)
+SDL_LIBS=$(shell sdl-config --libs)
+CFLAGS=$(SDL_CONFIG) -Wall -O2
+
+LIBS=$(SDL_LIBS) -lm
+
+CC=gcc
+
+TESTOBJS=main.o random.o vector.o planet.o
+
+sdl-planet: $(TESTOBJS)
+ gcc $(LIBS) -o $@ $(TESTOBJS)
+
+.c.o:
+ @echo -e "\tCC\t" $@
+ $(CC) -MMD -MF .$@.d $(CFLAGS) -c $< -o $@
+
+TAGS:
+ @echo -e "\tTAGS\t"
+ @etags *.[ch]
+
+clean:
+ rm -rfv $(TESTOBJS) *~ sdl-planet TAGS
+
+.PHONY: all clean TAGS
+
+-include .*.d
--- /dev/null
+#include <SDL.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "random.h"
+#include "planet.h"
+
+#define SCREEN_WIDTH 640
+#define SCREEN_HEIGHT 480
+
+static void fade_buf(SDL_Surface *screen, double amount)
+{
+ int i;
+ unsigned char *buf = screen->pixels;
+
+ for (i = 0; i < screen->pitch * screen->h; i++) {
+ buf[i] = (buf[i] < amount) ? 0 : buf[i] - amount;
+ }
+}
+
+static void loop(SDL_Surface *screen)
+{
+ int num_of_planets = 100;
+ struct planet planet[num_of_planets];
+ SDL_Event event;
+ int i, j, old_ticks, ticks, framecount = 0;
+ double time = 0;
+
+ for (i = 0; i < num_of_planets; i++)
+ init_planet(screen, &planet[i]);
+
+ ticks = SDL_GetTicks();
+ while (1) {
+ for (i = 0; i < num_of_planets; i++) {
+ for (j = i + 1; j < num_of_planets; j++)
+ gravitize_planets(&planet[i], &planet[j], time);
+
+ move_planet(&planet[i], time);
+ }
+
+ SDL_LockSurface(screen);
+
+ for (i = 0; i < num_of_planets; i++)
+ draw_planet(screen, &planet[i]);
+
+ if (!(framecount % 64))
+ fade_buf(screen, 1);
+
+ SDL_UnlockSurface(screen);
+
+ SDL_Flip(screen);
+
+ while(SDL_PollEvent(&event)) {
+ if (event.type == SDL_KEYDOWN) {
+ printf("Exiting. Good bye!\n");
+ return;
+ }
+ }
+
+ old_ticks = ticks;
+ ticks = SDL_GetTicks();
+ time = (ticks - old_ticks) / 1000.0;
+ printf("\rFrame: %d", framecount++);
+ }
+}
+
+int main(void)
+{
+ SDL_Surface *screen;
+ int flags = SDL_DOUBLEBUF | SDL_HWSURFACE;
+
+ // Load SDL
+ if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+ fprintf(stderr, "Unable to initialize SDL: %s\n",
+ SDL_GetError());
+
+ return 1;
+ }
+ atexit(SDL_Quit); // Clean it up nicely :)
+
+ screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, flags);
+ if (screen == NULL) {
+ fprintf(stderr, "Unable to set video mode: %s\n",
+ SDL_GetError());
+ return 2;
+ }
+
+ loop(screen);
+
+ return 0;
+}
+
--- /dev/null
+#include "random.h"
+#include "planet.h"
+
+static void putpixel(struct SDL_Surface *screen, const int x, const int y,
+ const unsigned char r, const unsigned char g,
+ const unsigned char b)
+{
+ int offset = y * screen->pitch + x * 4;
+ unsigned char *buf = screen->pixels;
+
+ buf[offset++] = b;
+ buf[offset++] = g;
+ buf[offset ] = r;
+}
+
+void init_planet(const SDL_Surface *screen, struct planet *p)
+{
+ p->speed.x = 0;
+ p->speed.y = 0;
+ p->pos.x = get_random() % screen->w;
+ p->pos.y = get_random() % screen->h;
+ p->mass = get_random() % 1000 + 100;
+ p->r = get_random() % 256;
+ p->g = get_random() % 256;
+ p->b = get_random() % 256;
+}
+
+void draw_planet(SDL_Surface *screen, struct planet *p)
+{
+ if (p->pos.x < screen->w &&
+ p->pos.y < screen->h &&
+ p->pos.x >= 0 &&
+ p->pos.y >= 0)
+ putpixel(screen, p->pos.x, p->pos.y, p->r, p->g, p->b);
+}
+
+void gravitize_planets(struct planet *a, struct planet *b, const double time)
+{
+ struct vector distance, sum;
+ double dist, f, acc;
+
+ vector_sub(&a->pos, &b->pos, &distance);
+
+ dist = vector_abs(&distance);
+ vector_div(&distance, dist, &distance);
+
+ f = a->mass * b->mass / (dist * dist + 5) * time;
+
+ acc = f / b->mass;
+ vector_scale(&distance, acc, &sum);
+ vector_add(&b->speed, &sum, &b->speed);
+
+ acc = f / a->mass;
+ vector_scale(&distance, acc, &sum);
+ vector_sub(&a->speed, &sum, &a->speed);
+}
+
+void move_planet(struct planet *p, const double time)
+{
+ struct vector tmp;
+ vector_scale(&p->speed, time, &tmp);
+ vector_add(&p->pos, &tmp, &p->pos);
+}
+
+void print_planet(const struct planet *p)
+{
+ printf("pos: (%f.%f), speed: (%f.%f), mass: %f\n",
+ p->pos.x, p->pos.y, p->speed.x, p->speed.y, p->mass);
+}
--- /dev/null
+#ifndef _PLANET_H
+#define _PLANET_H
+
+#include <SDL.h>
+
+#include "vector.h"
+
+struct planet {
+ struct vector speed;
+ struct vector pos;
+ double mass;
+ unsigned char r, g, b;
+};
+
+void init_planet(const SDL_Surface *screen, struct planet *p);
+void draw_planet(SDL_Surface *screen, struct planet *p);
+void gravitize_planets(struct planet *a, struct planet *b, const double time);
+void move_planet(struct planet *p, const double time);
+void print_planet(const struct planet *p);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "random.h"
+
+#define RAND_BUF_SIZE 1024
+#define RND_DEV "/dev/urandom"
+
+unsigned int get_random(void)
+{
+ static int rndbuf[RAND_BUF_SIZE];
+ static int index = RAND_BUF_SIZE;
+ int fd, error, i = 0, ret;
+
+ if (index < RAND_BUF_SIZE)
+ return rndbuf[index++];
+
+ fd = open(RND_DEV, O_RDONLY);
+ if (fd < 0) {
+ error = errno;
+ fprintf(stderr, "Error opening file %s: %s\n",
+ RND_DEV, strerror(error));
+ return -1;
+ }
+
+ do {
+ ret = read(fd, rndbuf + i,
+ RAND_BUF_SIZE * (sizeof(rndbuf[0]) - i));
+
+ if (ret <= 0) {
+ error = errno;
+ fprintf(stderr, "Error reading file %s: %s\n",
+ RND_DEV, strerror(error));
+ goto out;
+ }
+
+ i += ret;
+ } while (i < RAND_BUF_SIZE * sizeof(rndbuf[0]));
+ index = 0;
+ out:
+ return get_random();
+ close(fd);
+}
--- /dev/null
+#ifndef _RANDOM_H
+#define _RANDOM_H
+
+unsigned int get_random(void);
+
+#endif
--- /dev/null
+#include "vector.h"
+
--- /dev/null
+#ifndef _VECTOR_H
+#define _VECTOR_H
+
+#include <math.h>
+
+struct vector {
+ double x;
+ double y;
+};
+
+/*
+ * res = a - b
+ */
+static inline void vector_sub(const struct vector *a, const struct vector *b,
+ struct vector *res)
+{
+ res->x = a->x - b->x;
+ res->y = a->y - b->y;
+}
+
+/*
+ * res = a + b
+ */
+static inline void vector_add(const struct vector *a, const struct vector *b,
+ struct vector *res)
+{
+ res->x = a->x + b->x;
+ res->y = a->y + b->y;
+}
+
+static inline double vector_abs(const struct vector *a)
+{
+ return sqrt(a->x * a->x + a->y * a->y);
+}
+
+static inline void vector_scale(const struct vector *a, const double b,
+ struct vector *res)
+{
+ res->x = a->x * b;
+ res->y = a->y * b;
+}
+
+static inline void vector_div(const struct vector *a, const double b,
+ struct vector *res)
+{
+ res->x = a->x / b;
+ res->y = a->y / b;
+}
+
+#endif