11 static void fade_buf(SDL_Surface *screen, int amount)
14 unsigned int *buf = screen->pixels;
17 for (i = 0; i < screen->pitch * screen->h / sizeof(*buf); i ++) {
20 b = (unsigned char *)&buf[i];
21 *b = *b >= amount ? (*b - amount) : *b;
23 *b = *b >= amount ? (*b - amount) : *b;
25 *b = *b >= amount ? (*b - amount) : *b;
28 static void clear_buf(SDL_Surface *screen)
31 unsigned int *buf = screen->pixels;
33 for (i = 0; i < screen->pitch * screen->h / 4; i++)
37 /* Return time in microseconds */
39 static unsigned long gettime(void)
43 static unsigned long start = 0;
45 clock_gettime(CLOCK_MONOTONIC, &tp);
47 ret = tp.tv_sec * 1000 * 1000;
48 ret += tp.tv_nsec / 1000;
63 static int poll_events(struct sim_status *status, double time)
65 static double time_scale_rate = 1;
67 struct camera *cam = status->cam;
69 status->time_scale *= pow(time_scale_rate, time);
71 while (SDL_PollEvent(&event)) {
74 switch (event.key.keysym.sym) {
78 cam->speed.x = -CAM_SPEED;
81 cam->speed.x = CAM_SPEED;
84 cam->speed.y = -CAM_SPEED;
87 cam->speed.y = CAM_SPEED;
91 cam->zoom_rate = CAM_ZOOM_RATE;
95 cam->zoom_rate = 1 / CAM_ZOOM_RATE;
98 time_scale_rate = 1.5;
101 time_scale_rate = 1 / 1.5;
104 status->time_scale = 1;
107 status->time_scale = 10;
110 status->time_scale = 20;
113 status->time_scale = 30;
116 status->tracers_enabled =
117 !status->tracers_enabled;
123 switch (event.key.keysym.sym) {
154 case SDL_VIDEORESIZE:
155 status->screen = SDL_SetVideoMode(event.resize.w,
158 status->screen->flags);
167 printf("\nExiting. Good bye!\n");
171 static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
174 struct sim_status status;
175 struct planet *planet, *pl1, *pl2;
176 struct camera camera;
178 int framecount = 0, last_fps_time = 0;
179 int last_framecount = 0, last_step_count = 0;
180 unsigned long old_ticks, ticks = 0, last_frame_tick = 0;
181 unsigned long step_count = 0;
182 double last_fps = 0, last_sps = 0;
183 double step_time = 0, true_time = 0;
185 init_camera(&camera);
187 status.cam = &camera;
188 status.time_scale = 1;
189 status.screen = screen;
190 status.tracers_enabled = 0;
192 planet = malloc(sizeof(*planet));
194 create_planets(planet, num_of_planets, total_mass, range);
196 ticks = SDL_GetTicks();
200 list_for_each_entry(pl1, &planet->list, list) {
201 pl2 = list_to_planet(pl1->list.next);
202 list_for_each_entry_from(pl2, &planet->list, list) {
204 if (!gravitize_planets(pl1, pl2,
208 ptmp = list_to_planet(pl2->list.prev);
209 merge_planets(pl1, pl2);
213 move_planet(pl1, step_time);
216 move_camera(&camera, true_time);
218 if (poll_events(&status, true_time))
223 true_time = (ticks - old_ticks) / (1000.0 * 1000.0) ;
224 step_time = true_time * status.time_scale;
225 step_time = MIN(step_time, 0.02);
229 * Do not draw to the screen more often than MAS_FPS
232 if (last_frame_tick + (1000 * 1000) / MAX_FPS > ticks)
235 last_frame_tick = ticks;
237 SDL_LockSurface(screen);
239 if (status.tracers_enabled &&
240 !camera.speed.x && !camera.speed.y &&
241 camera.zoom_rate == 1) {
242 fade_buf(screen, 10 * true_time);
247 list_for_each_entry(pl1, &planet->list, list) {
248 draw_planet(screen, pl1, &camera);
252 SDL_UnlockSurface(screen);
256 if (last_fps_time + (500 * 1000) < ticks) {
257 last_framecount = framecount - last_framecount;
258 last_fps = last_framecount * 1000 * 1000 /
259 (float)(ticks - last_fps_time);
260 last_framecount = framecount;
262 last_step_count = step_count - last_step_count;
263 last_sps = last_step_count * 1000 * 1000 /
264 (float)(ticks - last_fps_time);
265 last_step_count = step_count;
267 last_fps_time = ticks;
271 printf(" \rFrames/s: %.2f, steps/s: %.2f, planets: %d"
272 ", scale %.2f, zoom %.2f, step %ld",
273 last_fps, last_sps, planets, status.time_scale,
274 camera.zoom, step_count);
282 int main(int argc, char *argv[])
285 int flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_RESIZABLE;
286 int planets = 100, xres = 800, yres = 600;
287 double total_mass = 50000;
290 if (SDL_Init(SDL_INIT_VIDEO) != 0) {
291 fprintf(stderr, "Unable to initialize SDL: %s\n",
299 planets = atoi(argv[1]);
302 total_mass = atof(argv[2]);
305 range = atof(argv[3]);
307 screen = SDL_SetVideoMode(xres, yres, 32, flags);
308 if (screen == NULL) {
309 fprintf(stderr, "Unable to set video mode: %s\n",
314 SDL_WM_SetCaption(argv[0], NULL);
316 loop(screen, planets, total_mass, range);