#include #include #include #include "random.h" #include "planet.h" 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 clear_buf(SDL_Surface *screen) { int i; unsigned int *buf = screen->pixels; for (i = 0; i < screen->pitch * screen->h / 4; i++) buf[i] = 0; } static int poll_events(SDL_Surface **screen, struct camera *cam, double *time_scale, double time) { static double time_scale_rate = 1; SDL_Event event; *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; case SDLK_LEFT: cam->speed.x = -CAM_SPEED; break; case SDLK_RIGHT: cam->speed.x = CAM_SPEED; break; case SDLK_UP: cam->speed.y = -CAM_SPEED; break; case SDLK_DOWN: cam->speed.y = CAM_SPEED; break; case SDLK_PLUS: case SDLK_q: cam->zoom_rate = CAM_ZOOM_RATE; break; case SDLK_MINUS: case SDLK_w: cam->zoom_rate = 1 / CAM_ZOOM_RATE; break; case SDLK_s: time_scale_rate = 1.5; break; case SDLK_a: time_scale_rate = 1 / 1.5; break; default: break; } break; case SDL_KEYUP: switch (event.key.keysym.sym) { case SDLK_LEFT: cam->speed.x = 0; break; case SDLK_RIGHT: cam->speed.x = 0; break; case SDLK_UP: cam->speed.y = 0; break; case SDLK_DOWN: cam->speed.y = 0; break; case SDLK_PLUS: case SDLK_q: cam->zoom_rate = 1; break; case SDLK_MINUS: case SDLK_w: cam->zoom_rate = 1; break; case SDLK_s: time_scale_rate = 1; break; case SDLK_a: time_scale_rate = 1; break; default: break; } break; case SDL_VIDEORESIZE: *screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 32, screen[0]->flags); break; } } return 0; } static void loop(SDL_Surface *screen, int num_of_planets, double total_mass, double range) { 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; init_camera(&camera); planet = malloc(sizeof(*planet)); init_planet(planet); create_planets(planet, num_of_planets, total_mass, range); ticks = SDL_GetTicks(); while (1) { planets = 0; list_for_each_entry(pl1, &planet->list, list) { pl2 = list_to_planet(pl1->list.next); list_for_each_entry_from(pl2, &planet->list, list) { struct planet *ptmp; if (!gravitize_planets(pl1, pl2, time * time_scale)) continue; ptmp = list_to_planet(pl2->list.prev); merge_planets(pl1, pl2); pl2 = ptmp; } move_planet(pl1, time * time_scale); } SDL_LockSurface(screen); clear_buf(screen); list_for_each_entry(pl1, &planet->list, list) { draw_planet(screen, pl1, &camera); planets++; } SDL_UnlockSurface(screen); 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) { last_framecount = framecount - last_framecount; last_fps = last_framecount * 1000 / (float)(ticks - last_fps_time); last_framecount = framecount; last_fps_time = ticks; } printf(" \rFrames/s: %.2f, Frame: %d, planets: %d" ", scale %.2f, zoom %.2f", last_fps, framecount++, planets, time_scale, camera.zoom); } } int main(int argc, char *argv[]) { SDL_Surface *screen; int flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_RESIZABLE; int planets = 100, xres = 800, yres = 600; double total_mass = 50000; double range = 500; if (SDL_Init(SDL_INIT_VIDEO) != 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } atexit(SDL_Quit); if (argc >= 2) planets = atoi(argv[1]); if (argc >= 3) total_mass = atof(argv[2]); if (argc >= 4) range = atof(argv[3]); screen = SDL_SetVideoMode(xres, yres, 32, flags); if (screen == NULL) { fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError()); return 2; } SDL_WM_SetCaption(argv[0], NULL); loop(screen, planets, total_mass, range); return 0; }