11 static void fade_buf(SDL_Surface *screen, double fade)
14 unsigned int *buf = screen->pixels;
17 static double threshold;
27 for (i = 0; i < screen->pitch * screen->h / sizeof(*buf); i++) {
30 b = (unsigned char *)&buf[i];
31 *b = *b >= amount ? (*b - amount) : *b;
33 *b = *b >= amount ? (*b - amount) : *b;
35 *b = *b >= amount ? (*b - amount) : *b;
39 static void clear_buf(SDL_Surface *screen)
42 unsigned int *buf = screen->pixels;
44 for (i = 0; i < screen->pitch * screen->h / 4; i++)
48 /* Return time in microseconds */
50 static unsigned long gettime(void)
54 static unsigned long start;
56 clock_gettime(CLOCK_MONOTONIC, &tp);
58 ret = tp.tv_sec * 1000 * 1000;
59 ret += tp.tv_nsec / 1000;
74 static int poll_events(struct sim_status *status, double time)
76 static double time_scale_rate = 1;
78 struct camera *cam = status->cam;
80 status->time_scale *= pow(time_scale_rate, time);
82 while (SDL_PollEvent(&event)) {
85 switch (event.key.keysym.sym) {
89 cam->speed.x = -CAM_SPEED;
92 cam->speed.x = CAM_SPEED;
95 cam->speed.y = -CAM_SPEED;
98 cam->speed.y = CAM_SPEED;
102 cam->zoom_rate = CAM_ZOOM_RATE;
106 cam->zoom_rate = 1 / CAM_ZOOM_RATE;
109 time_scale_rate = 1.5;
112 time_scale_rate = 1 / 1.5;
115 status->time_scale = 1;
118 status->time_scale = 10;
121 status->time_scale = 20;
124 status->time_scale = 30;
127 status->time_scale = 0;
130 status->tracers_enabled =
131 !status->tracers_enabled;
137 switch (event.key.keysym.sym) {
168 case SDL_VIDEORESIZE:
170 SDL_SetVideoMode(event.resize.w,
173 status->screen->flags);
182 printf("\nExiting. Good bye!\n");
186 static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
189 struct sim_status status;
190 struct planet *planet, *pl1, *pl2, *planet_root;
191 struct camera camera;
192 struct planet_search_iterator itr;
196 int framecount = 0, last_fps_time = 0;
197 int last_framecount = 0, last_step_count = 0;
198 unsigned long old_ticks, ticks = 0, last_frame_tick = 0;
199 unsigned long step_count = 0;
200 double last_fps = 0, last_sps = 0, fade_amount;
201 double step_time = 0, true_time = 0;
204 init_camera(&camera);
206 status.cam = &camera;
207 status.time_scale = 1;
208 status.screen = screen;
209 status.tracers_enabled = 0;
213 itr.qt_iterator.direction = planet_search_rectangular;
214 itr.qt_iterator.callback = planet_draw_iterator;
216 planet = malloc(sizeof(*planet));
218 create_planets(planet, num_of_planets, total_mass, range);
220 ticks = SDL_GetTicks();
224 if (status.time_scale > 0) {
225 list_for_each_entry(pl1, &planet->list, list) {
226 pl2 = list_to_planet(pl1->list.next);
227 list_for_each_entry_from(pl2, &planet->list,
230 if (!gravitize_planets(pl1, pl2,
234 ptmp = list_to_planet(pl2->list.prev);
235 merge_planets(pl1, pl2);
239 planet_root = move_planet(pl1, step_time);
243 move_camera(&camera, true_time);
245 if (poll_events(&status, true_time))
250 true_time = (ticks - old_ticks) / (1000.0 * 1000.0) ;
251 step_time = true_time * status.time_scale;
252 step_time = MIN(step_time, 0.02);
256 * Do not draw to the screen more often than MAX_FPS
259 if (last_frame_tick + (1000 * 1000) / MAX_FPS > ticks)
262 SDL_LockSurface(screen);
264 if (status.tracers_enabled &&
265 !camera.speed.x && !camera.speed.y &&
266 camera.zoom_rate == 1) {
267 fade_amount = (ticks - last_frame_tick) /
268 (1000 * 1000.0) * 20;
269 fade_buf(screen, fade_amount);
274 itr.limit[0] = camera.pos;
275 vect.x = screen->w / 2;
276 vect.y = screen->h / 2;
277 vector_scale(&vect, 1 / camera.zoom, &vect);
278 vector_add(&itr.limit[0], &vect, &itr.limit[1]);
279 vector_sub(&itr.limit[0], &vect, &itr.limit[0]);
281 itr.qt_iterator.head = &planet_root->tree;
283 visible_planets = walk_quadtree(&itr.qt_iterator);
285 SDL_UnlockSurface(screen);
289 last_frame_tick = ticks;
291 if (last_fps_time + (500 * 1000) < ticks) {
292 last_framecount = framecount - last_framecount;
293 last_fps = last_framecount * 1000 * 1000 /
294 (float)(ticks - last_fps_time);
295 last_framecount = framecount;
297 last_step_count = step_count - last_step_count;
298 last_sps = last_step_count * 1000 * 1000 /
299 (float)(ticks - last_fps_time);
300 last_step_count = step_count;
302 last_fps_time = ticks;
305 printf(" \rfps: %.2f, steps/s: %.2f, planets: %d"
306 ", scale %.2f, zoom %.2f, step %ld, visible %d,"
308 last_fps, last_sps, planets, status.time_scale,
309 camera.zoom, step_count, visible_planets,
310 planet_root->tree.depth, planet_root->tree.children);
318 int main(int argc, char *argv[])
321 int flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_RESIZABLE;
322 int planets = 100, xres = 800, yres = 600;
323 double total_mass = 50000;
326 if (SDL_Init(SDL_INIT_VIDEO) != 0) {
327 fprintf(stderr, "Unable to initialize SDL: %s\n",
335 planets = atoi(argv[1]);
342 total_mass = atof(argv[2]);
345 range = atof(argv[3]);
347 screen = SDL_SetVideoMode(xres, yres, 32, flags);
348 if (screen == NULL) {
349 fprintf(stderr, "Unable to set video mode: %s\n",
354 SDL_WM_SetCaption(argv[0], NULL);
356 loop(screen, planets, total_mass, range);