]> git.itanic.dy.fi Git - sdl-planets/commitdiff
Moving colorful planets, whoo!
authorTimo Kokkonen <kaapeli@itanic.dy.fi>
Sun, 31 Jan 2010 15:32:04 +0000 (17:32 +0200)
committerTimo Kokkonen <kaapeli@itanic.dy.fi>
Sun, 31 Jan 2010 15:32:04 +0000 (17:32 +0200)
Signed-off-by: Timo Kokkonen <kaapeli@itanic.dy.fi>
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
main.c [new file with mode: 0644]
planet.c [new file with mode: 0644]
planet.h [new file with mode: 0644]
random.c [new file with mode: 0644]
random.h [new file with mode: 0644]
vector.c [new file with mode: 0644]
vector.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..263fdab
--- /dev/null
@@ -0,0 +1,5 @@
+*.o
+*~
+.*.d
+TAGS
+sdl-planet
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..32fb205
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,27 @@
+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
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..b92c553
--- /dev/null
+++ b/main.c
@@ -0,0 +1,92 @@
+#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;
+}
+
diff --git a/planet.c b/planet.c
new file mode 100644 (file)
index 0000000..261a71d
--- /dev/null
+++ b/planet.c
@@ -0,0 +1,69 @@
+#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);
+}
diff --git a/planet.h b/planet.h
new file mode 100644 (file)
index 0000000..1918ee4
--- /dev/null
+++ b/planet.h
@@ -0,0 +1,21 @@
+#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
diff --git a/random.c b/random.c
new file mode 100644 (file)
index 0000000..f59b0cf
--- /dev/null
+++ b/random.c
@@ -0,0 +1,48 @@
+#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);
+}
diff --git a/random.h b/random.h
new file mode 100644 (file)
index 0000000..89507af
--- /dev/null
+++ b/random.h
@@ -0,0 +1,6 @@
+#ifndef _RANDOM_H
+#define _RANDOM_H
+
+unsigned int get_random(void);
+
+#endif
diff --git a/vector.c b/vector.c
new file mode 100644 (file)
index 0000000..f26d0c4
--- /dev/null
+++ b/vector.c
@@ -0,0 +1,2 @@
+#include "vector.h"
+
diff --git a/vector.h b/vector.h
new file mode 100644 (file)
index 0000000..875cd35
--- /dev/null
+++ b/vector.h
@@ -0,0 +1,50 @@
+#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