]> git.itanic.dy.fi Git - sdl-planets/commitdiff
Merge branch 'master' into quadtree-dev
authorTimo Kokkonen <kaapeli@itanic.dy.fi>
Mon, 5 Apr 2010 13:04:13 +0000 (16:04 +0300)
committerTimo Kokkonen <kaapeli@itanic.dy.fi>
Mon, 5 Apr 2010 13:04:13 +0000 (16:04 +0300)
Makefile
main.c
planet.c

index 4f3207e4b49221df9d4ca6b60c85103fd8bd387c..c4c765204c9c14460cdef19c5e2735f4923f533d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,16 +2,20 @@ SDL_CONFIG=$(shell sdl-config --cflags)
 SDL_LIBS=$(shell sdl-config --libs)
 CFLAGS=$(SDL_CONFIG) -Wall -O2 -g
 
-LIBS=$(SDL_LIBS) -lm
+LIBS=$(SDL_LIBS) -lm -lrt
 
 CC=gcc
 SPARSE=sparse
 CHECKPATCH=/usr/src/linux/scripts/checkpatch.pl
 
-TESTOBJS=main.o random.o vector.o planet.o camera.o
+PLANET_OBJS=main.o random.o vector.o planet.o camera.o
+PLANET_DEBUG_OBJS= $(patsubst %.o,%-debug.o,$(PLANET_OBJS))
 
-sdl-planet: $(TESTOBJS)
-       gcc $(LIBS) -o $@ $(TESTOBJS)
+sdl-planet: $(PLANET_OBJS)
+       gcc $(LIBS) -o $@ $(PLANET_OBJS)
+
+debug-planets: $(PLANET_DEBUG_OBJS)
+       gcc $(LIBS) -o $@ $(PLANET_DEBUG_OBJS) -DDEBUG
 
 .c.o:
        @echo -e "\tCC\t" $@
@@ -23,12 +27,16 @@ ifeq ($(C),2)
        $(CHECKPATCH) -f $<
 endif
 
+%-debug.o: %.c
+       @echo -e "\tCC\t" $@
+       @$(CC) -MMD -MF .$@.d $(CFLAGS) -O0 -c $< -o $@
+
 TAGS:
        @echo -e "\tTAGS\t"
        @etags *.[ch]
 
 clean:
-       rm -rfv $(TESTOBJS) *~ sdl-planet TAGS .*.d
+       rm -rfv $(PLANET_OBJS) $(PLANET_DEBUG_OBJS) *~ sdl-planet TAGS .*.d
 
 .PHONY: all clean TAGS
 
diff --git a/main.c b/main.c
index 6863b18c1970131993e6aaf1e593117f41deeb55..2241d42b6e1f52ee4a3ec849e4e6f8b47b4a5448 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,17 +1,39 @@
 #include <SDL.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <time.h>
 
 #include "random.h"
 #include "planet.h"
 
-static void fade_buf(SDL_Surface *screen, double amount)
+#define MAX_FPS 60
+
+static void fade_buf(SDL_Surface *screen, double fade)
 {
        int i;
-       unsigned char *buf = screen->pixels;
+       unsigned int *buf = screen->pixels;
+       unsigned char *b;
+       unsigned char amount;
+       static double threshold;
+       threshold += fade;
+
+       if (threshold > 1) {
+               amount = threshold;
+               threshold -= amount;
+       } else {
+               return;
+       }
 
-       for (i = 0; i < screen->pitch * screen->h; i++)
-               buf[i] = (buf[i] < amount) ? 0 : buf[i] - amount;
+       for (i = 0; i < screen->pitch * screen->h / sizeof(*buf); i++) {
+               if (!buf[i])
+                       continue;
+               b = (unsigned char *)&buf[i];
+               *b = *b >= amount ? (*b - amount) : *b;
+               b++;
+               *b = *b >= amount ? (*b - amount) : *b;
+               b++;
+               *b = *b >= amount ? (*b - amount) : *b;
+       }
 }
 
 static void clear_buf(SDL_Surface *screen)
@@ -23,21 +45,46 @@ static void clear_buf(SDL_Surface *screen)
                buf[i] = 0;
 }
 
-static int poll_events(SDL_Surface **screen, struct camera *cam,
-                      double *time_scale, double time)
+/* Return time in microseconds */
+
+static unsigned long gettime(void)
+{
+       struct timespec tp;
+       unsigned long ret;
+       static unsigned long start;
+
+       clock_gettime(CLOCK_MONOTONIC, &tp);
+
+       ret = tp.tv_sec * 1000 * 1000;
+       ret += tp.tv_nsec / 1000;
+
+       if (!start)
+               start = ret;
+
+       return ret - start;
+}
+
+struct sim_status {
+       SDL_Surface *screen;
+       struct camera *cam;
+       double time_scale;
+       int tracers_enabled;
+};
+
+static int poll_events(struct sim_status *status, double time)
 {
        static double time_scale_rate = 1;
        SDL_Event event;
+       struct camera *cam = status->cam;
 
-       *time_scale *= pow(time_scale_rate, time);
+       status->time_scale *= pow(time_scale_rate, time);
 
        while (SDL_PollEvent(&event)) {
                switch (event.type) {
                case SDL_KEYDOWN:
                        switch (event.key.keysym.sym) {
                        case SDLK_ESCAPE:
-                               printf("\nExiting. Good bye!\n");
-                               return 1;
+                               goto quit;
                        case SDLK_LEFT:
                                cam->speed.x = -CAM_SPEED;
                                break;
@@ -64,6 +111,21 @@ static int poll_events(SDL_Surface **screen, struct camera *cam,
                        case SDLK_a:
                                time_scale_rate = 1 / 1.5;
                                break;
+                       case SDLK_1:
+                               status->time_scale = 1;
+                               break;
+                       case SDLK_2:
+                               status->time_scale = 10;
+                               break;
+                       case SDLK_3:
+                               status->time_scale = 20;
+                               break;
+                       case SDLK_4:
+                               status->time_scale = 30;
+                               break;
+                       case SDLK_t:
+                               status->tracers_enabled =
+                                       !status->tracers_enabled;
                        default:
                                break;
                        }
@@ -101,29 +163,44 @@ static int poll_events(SDL_Surface **screen, struct camera *cam,
                        }
                        break;
                case SDL_VIDEORESIZE:
-                       *screen = SDL_SetVideoMode(event.resize.w,
-                                                  event.resize.h,
-                                                  32,
-                                                  screen[0]->flags);
+                       status->screen =
+                               SDL_SetVideoMode(event.resize.w,
+                                                event.resize.h,
+                                                32,
+                                                status->screen->flags);
                        break;
+               case SDL_QUIT:
+                       goto quit;
                }
        }
 
        return 0;
+quit:
+       printf("\nExiting. Good bye!\n");
+       return 1;
 }
 
 static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
                 double range)
 {
+       struct sim_status status;
        struct planet *planet, *pl1, *pl2;
        struct camera camera;
        int planets;
-       int old_ticks, ticks, framecount = 0, last_fps_time = 0;
-       int last_framecount = 0;
-       double time = 0, last_fps = 0, time_scale = 1;
+       int framecount = 0, last_fps_time = 0;
+       int last_framecount = 0, last_step_count = 0;
+       unsigned long old_ticks, ticks = 0, last_frame_tick = 0;
+       unsigned long step_count = 0;
+       double last_fps = 0, last_sps = 0;
+       double step_time = 0, true_time = 0;
 
        init_camera(&camera);
 
+       status.cam = &camera;
+       status.time_scale = 1;
+       status.screen = screen;
+       status.tracers_enabled = 0;
+
        planet = malloc(sizeof(*planet));
        init_planet(planet);
        create_planets(planet, num_of_planets, total_mass, range);
@@ -137,7 +214,7 @@ static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
                        list_for_each_entry_from(pl2, &planet->list, list) {
                                struct planet *ptmp;
                                if (!gravitize_planets(pl1, pl2,
-                                                      time * time_scale))
+                                                      step_time))
                                        continue;
 
                                ptmp = list_to_planet(pl2->list.prev);
@@ -145,12 +222,39 @@ static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
                                pl2 = ptmp;
                        }
 
-                       move_planet(pl1, time * time_scale);
+                       move_planet(pl1, step_time);
                }
 
+               move_camera(&camera, true_time);
+
+               if (poll_events(&status, true_time))
+                       return;
+
+               old_ticks = ticks;
+               ticks = gettime();
+               true_time = (ticks - old_ticks) / (1000.0 * 1000.0) ;
+               step_time = true_time * status.time_scale;
+               step_time = MIN(step_time, 0.02);
+               step_count++;
+
+               /*
+                * Do not draw to the screen more often than MAX_FPS
+                * per second
+                */
+               if (last_frame_tick + (1000 * 1000) / MAX_FPS > ticks)
+                       continue;
+
+               last_frame_tick = ticks;
+
                SDL_LockSurface(screen);
 
-               clear_buf(screen);
+               if (status.tracers_enabled &&
+                   !camera.speed.x && !camera.speed.y &&
+                   camera.zoom_rate == 1) {
+                       fade_buf(screen, 10 * true_time);
+               } else {
+                       clear_buf(screen);
+               }
 
                list_for_each_entry(pl1, &planet->list, list) {
                        draw_planet(screen, pl1, &camera);
@@ -161,27 +265,29 @@ static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
 
                SDL_Flip(screen);
 
-               move_camera(&camera, time);
-
-               if (poll_events(&screen, &camera, &time_scale, time))
-                       return;
-
-               old_ticks = ticks;
-               ticks = SDL_GetTicks();
-               time = (ticks - old_ticks) / 1000.0;
-               time = MIN(time, 0.02);
-
-               if (last_fps_time + 500 < ticks) {
+               if (last_fps_time + (500 * 1000) < ticks) {
                        last_framecount = framecount - last_framecount;
-                       last_fps = last_framecount * 1000 /
+                       last_fps = last_framecount * 1000 * 1000 /
                                (float)(ticks - last_fps_time);
                        last_framecount = framecount;
+
+                       last_step_count = step_count - last_step_count;
+                       last_sps = last_step_count * 1000 * 1000 /
+                               (float)(ticks - last_fps_time);
+                       last_step_count = step_count;
+
                        last_fps_time = ticks;
                }
-               printf("  \rFrames/s: %.2f, Frame: %d, planets: %d"
-                      ", scale %.2f, zoom %.2f",
-                      last_fps, framecount++, planets, time_scale,
-                      camera.zoom);
+
+
+               printf("  \rFrames/s: %.2f, steps/s: %.2f, planets: %d"
+                      ", scale %.2f, zoom %.2f, step %ld",
+                      last_fps, last_sps, planets, status.time_scale,
+                      camera.zoom, step_count);
+               fflush(stdout);
+
+
+               framecount++;
        }
 }
 
index 1cf5d1ef50251cf947edf7f58f5b19156a8291d5..f72b1b0087a523fe76e0f10979fe5cd8d842d7de 100644 (file)
--- a/planet.c
+++ b/planet.c
@@ -51,7 +51,7 @@ static void setup_planet(struct planet *p, double mass, double total_mass,
        double velocity;
        double distance;
 
-       distance = radius * get_random_double();
+       distance = radius * pow(get_random_double(), 2);
        velocity = sqrt(total_mass / radius);
 
        velocity *= pow(distance / radius, 0.2);
@@ -73,7 +73,12 @@ void create_planets(struct planet *p, int num, double total_mass, double radius)
        double sum = 0;
        struct planet *new_planet;
 
-       for (i = 1; i < num; i++) {
+       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);