11 static void fade_buf(SDL_Surface *screen, double amount)
14 unsigned char *buf = screen->pixels;
16 for (i = 0; i < screen->pitch * screen->h; i++)
17 buf[i] = (buf[i] < amount) ? 0 : buf[i] - amount;
20 static void clear_buf(SDL_Surface *screen)
23 unsigned int *buf = screen->pixels;
25 for (i = 0; i < screen->pitch * screen->h / 4; i++)
29 /* Return time in microseconds */
31 static unsigned long gettime(void)
35 static unsigned long start = 0;
37 clock_gettime(CLOCK_MONOTONIC, &tp);
39 ret = tp.tv_sec * 1000 * 1000;
40 ret += tp.tv_nsec / 1000;
54 static int poll_events(struct sim_status *status, double time)
56 static double time_scale_rate = 1;
58 struct camera *cam = status->cam;
60 status->time_scale *= pow(time_scale_rate, time);
62 while (SDL_PollEvent(&event)) {
65 switch (event.key.keysym.sym) {
69 cam->speed.x = -CAM_SPEED;
72 cam->speed.x = CAM_SPEED;
75 cam->speed.y = -CAM_SPEED;
78 cam->speed.y = CAM_SPEED;
82 cam->zoom_rate = CAM_ZOOM_RATE;
86 cam->zoom_rate = 1 / CAM_ZOOM_RATE;
89 time_scale_rate = 1.5;
92 time_scale_rate = 1 / 1.5;
99 switch (event.key.keysym.sym) {
130 case SDL_VIDEORESIZE:
131 status->screen = SDL_SetVideoMode(event.resize.w,
134 status->screen->flags);
143 printf("\nExiting. Good bye!\n");
147 static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
150 struct sim_status status;
151 struct planet *planet, *pl1, *pl2;
152 struct camera camera;
154 int framecount = 0, last_fps_time = 0;
155 int last_framecount = 0, last_step_count = 0;
156 unsigned long old_ticks, ticks = 0, last_frame_tick = 0;
157 unsigned long step_count = 0;
158 double last_fps = 0, last_sps = 0;
159 double step_time = 0, true_time = 0;
161 init_camera(&camera);
163 status.cam = &camera;
164 status.time_scale = 1;
165 status.screen = screen;
167 planet = malloc(sizeof(*planet));
169 create_planets(planet, num_of_planets, total_mass, range);
171 ticks = SDL_GetTicks();
175 list_for_each_entry(pl1, &planet->list, list) {
176 pl2 = list_to_planet(pl1->list.next);
177 list_for_each_entry_from(pl2, &planet->list, list) {
179 if (!gravitize_planets(pl1, pl2,
183 ptmp = list_to_planet(pl2->list.prev);
184 merge_planets(pl1, pl2);
188 move_planet(pl1, step_time);
191 move_camera(&camera, true_time);
193 if (poll_events(&status, true_time))
198 true_time = (ticks - old_ticks) / (1000.0 * 1000.0) ;
199 step_time = true_time * status.time_scale;
200 step_time = MIN(step_time, 0.02);
204 * Do not draw to the screen more often than MAS_FPS
207 if (last_frame_tick + (1000 * 1000) / MAX_FPS > ticks)
210 last_frame_tick = ticks;
212 SDL_LockSurface(screen);
215 list_for_each_entry(pl1, &planet->list, list) {
216 draw_planet(screen, pl1, &camera);
220 SDL_UnlockSurface(screen);
224 if (last_fps_time + (500 * 1000) < ticks) {
225 last_framecount = framecount - last_framecount;
226 last_fps = last_framecount * 1000 * 1000 /
227 (float)(ticks - last_fps_time);
228 last_framecount = framecount;
230 last_step_count = step_count - last_step_count;
231 last_sps = last_step_count * 1000 * 1000 /
232 (float)(ticks - last_fps_time);
233 last_step_count = step_count;
235 last_fps_time = ticks;
239 printf(" \rFrames/s: %.2f, steps/s: %.2f, planets: %d"
240 ", scale %.2f, zoom %.2f, step %d",
241 last_fps, last_sps, planets, status.time_scale,
242 camera.zoom, step_count);
250 int main(int argc, char *argv[])
253 int flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_RESIZABLE;
254 int planets = 100, xres = 800, yres = 600;
255 double total_mass = 50000;
258 if (SDL_Init(SDL_INIT_VIDEO) != 0) {
259 fprintf(stderr, "Unable to initialize SDL: %s\n",
267 planets = atoi(argv[1]);
270 total_mass = atof(argv[2]);
273 range = atof(argv[3]);
275 screen = SDL_SetVideoMode(xres, yres, 32, flags);
276 if (screen == NULL) {
277 fprintf(stderr, "Unable to set video mode: %s\n",
282 SDL_WM_SetCaption(argv[0], NULL);
284 loop(screen, planets, total_mass, range);