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;
48 static int poll_events(SDL_Surface **screen, struct camera *cam,
49 double *time_scale, double time)
51 static double time_scale_rate = 1;
54 *time_scale *= pow(time_scale_rate, time);
56 while (SDL_PollEvent(&event)) {
59 switch (event.key.keysym.sym) {
63 cam->speed.x = -CAM_SPEED;
66 cam->speed.x = CAM_SPEED;
69 cam->speed.y = -CAM_SPEED;
72 cam->speed.y = CAM_SPEED;
76 cam->zoom_rate = CAM_ZOOM_RATE;
80 cam->zoom_rate = 1 / CAM_ZOOM_RATE;
83 time_scale_rate = 1.5;
86 time_scale_rate = 1 / 1.5;
93 switch (event.key.keysym.sym) {
124 case SDL_VIDEORESIZE:
125 *screen = SDL_SetVideoMode(event.resize.w,
137 printf("\nExiting. Good bye!\n");
141 static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
144 struct planet *planet, *pl1, *pl2;
145 struct camera camera;
147 int framecount = 0, last_fps_time = 0;
148 int last_framecount = 0, last_step_count = 0;
149 unsigned long old_ticks, ticks = 0, last_frame_tick = 0;
150 unsigned long step_count = 0;
151 double last_fps = 0, time_scale = 1, last_sps = 0;
152 double step_time = 0, true_time = 0;
154 init_camera(&camera);
156 planet = malloc(sizeof(*planet));
158 create_planets(planet, num_of_planets, total_mass, range);
160 ticks = SDL_GetTicks();
164 list_for_each_entry(pl1, &planet->list, list) {
165 pl2 = list_to_planet(pl1->list.next);
166 list_for_each_entry_from(pl2, &planet->list, list) {
168 if (!gravitize_planets(pl1, pl2,
172 ptmp = list_to_planet(pl2->list.prev);
173 merge_planets(pl1, pl2);
177 move_planet(pl1, step_time);
180 move_camera(&camera, true_time);
182 if (poll_events(&screen, &camera, &time_scale, true_time))
187 true_time = (ticks - old_ticks) / (1000.0 * 1000.0) ;
188 step_time = true_time * time_scale;
189 step_time = MIN(step_time, 0.02);
193 * Do not draw to the screen more often than MAS_FPS
196 if (last_frame_tick + (1000 * 1000) / MAX_FPS > ticks)
199 last_frame_tick = ticks;
201 SDL_LockSurface(screen);
204 list_for_each_entry(pl1, &planet->list, list) {
205 draw_planet(screen, pl1, &camera);
209 SDL_UnlockSurface(screen);
213 if (last_fps_time + (500 * 1000) < ticks) {
214 last_framecount = framecount - last_framecount;
215 last_fps = last_framecount * 1000 * 1000 /
216 (float)(ticks - last_fps_time);
217 last_framecount = framecount;
219 last_step_count = step_count - last_step_count;
220 last_sps = last_step_count * 1000 * 1000 /
221 (float)(ticks - last_fps_time);
222 last_step_count = step_count;
224 last_fps_time = ticks;
228 printf(" \rFrames/s: %.2f, steps/s: %.2f, planets: %d"
229 ", scale %.2f, zoom %.2f, step %d",
230 last_fps, last_sps, planets, time_scale,
231 camera.zoom, step_count);
239 int main(int argc, char *argv[])
242 int flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_RESIZABLE;
243 int planets = 100, xres = 800, yres = 600;
244 double total_mass = 50000;
247 if (SDL_Init(SDL_INIT_VIDEO) != 0) {
248 fprintf(stderr, "Unable to initialize SDL: %s\n",
256 planets = atoi(argv[1]);
259 total_mass = atof(argv[2]);
262 range = atof(argv[3]);
264 screen = SDL_SetVideoMode(xres, yres, 32, flags);
265 if (screen == NULL) {
266 fprintf(stderr, "Unable to set video mode: %s\n",
271 SDL_WM_SetCaption(argv[0], NULL);
273 loop(screen, planets, total_mass, range);