]> git.itanic.dy.fi Git - sdl-planets/blob - main.c
quadtree: Add missing function definition to the header
[sdl-planets] / main.c
1 #include <SDL.h>
2 #include <unistd.h>
3 #include <stdio.h>
4
5 #include "random.h"
6 #include "planet.h"
7
8 static void fade_buf(SDL_Surface *screen, double amount)
9 {
10         int i;
11         unsigned char *buf = screen->pixels;
12
13         for (i = 0; i < screen->pitch * screen->h; i++)
14                 buf[i] = (buf[i] < amount) ? 0 : buf[i] - amount;
15 }
16
17 static void clear_buf(SDL_Surface *screen)
18 {
19         int i;
20         unsigned int *buf = screen->pixels;
21
22         for (i = 0; i < screen->pitch * screen->h / 4; i++)
23                 buf[i] = 0;
24 }
25
26 static int poll_events(SDL_Surface **screen, struct camera *cam,
27                        double *time_scale, double time)
28 {
29         static double time_scale_rate = 1;
30         SDL_Event event;
31
32         *time_scale *= pow(time_scale_rate, time);
33
34         while (SDL_PollEvent(&event)) {
35                 switch (event.type) {
36                 case SDL_KEYDOWN:
37                         switch (event.key.keysym.sym) {
38                         case SDLK_ESCAPE:
39                                 printf("\nExiting. Good bye!\n");
40                                 return 1;
41                         case SDLK_LEFT:
42                                 cam->speed.x = -CAM_SPEED;
43                                 break;
44                         case SDLK_RIGHT:
45                                 cam->speed.x = CAM_SPEED;
46                                 break;
47                         case SDLK_UP:
48                                 cam->speed.y = -CAM_SPEED;
49                                 break;
50                         case SDLK_DOWN:
51                                 cam->speed.y = CAM_SPEED;
52                                 break;
53                         case SDLK_PLUS:
54                         case SDLK_q:
55                                 cam->zoom_rate = CAM_ZOOM_RATE;
56                                 break;
57                         case SDLK_MINUS:
58                         case SDLK_w:
59                                 cam->zoom_rate = 1 / CAM_ZOOM_RATE;
60                                 break;
61                         case SDLK_s:
62                                 time_scale_rate = 1.5;
63                                 break;
64                         case SDLK_a:
65                                 time_scale_rate = 1 / 1.5;
66                                 break;
67                         default:
68                                 break;
69                         }
70                         break;
71                 case SDL_KEYUP:
72                         switch (event.key.keysym.sym) {
73                         case SDLK_LEFT:
74                                 cam->speed.x = 0;
75                                 break;
76                         case SDLK_RIGHT:
77                                 cam->speed.x = 0;
78                                 break;
79                         case SDLK_UP:
80                                 cam->speed.y = 0;
81                                 break;
82                         case SDLK_DOWN:
83                                 cam->speed.y = 0;
84                                 break;
85                         case SDLK_PLUS:
86                         case SDLK_q:
87                                 cam->zoom_rate = 1;
88                                 break;
89                         case SDLK_MINUS:
90                         case SDLK_w:
91                                 cam->zoom_rate = 1;
92                                 break;
93                         case SDLK_s:
94                                 time_scale_rate = 1;
95                                 break;
96                         case SDLK_a:
97                                 time_scale_rate = 1;
98                                 break;
99                         default:
100                                 break;
101                         }
102                         break;
103                 case SDL_VIDEORESIZE:
104                         *screen = SDL_SetVideoMode(event.resize.w,
105                                                    event.resize.h,
106                                                    32,
107                                                    screen[0]->flags);
108                         break;
109                 }
110         }
111
112         return 0;
113 }
114
115 static void loop(SDL_Surface *screen, int num_of_planets, double total_mass,
116                  double range)
117 {
118         struct planet *planet, *pl1, *pl2;
119         struct camera camera;
120         int planets;
121         int old_ticks, ticks, framecount = 0, last_fps_time = 0;
122         int last_framecount = 0;
123         double time = 0, last_fps = 0, time_scale = 1;
124
125         init_camera(&camera);
126
127         planet = malloc(sizeof(*planet));
128         init_planet(planet);
129         create_planets(planet, num_of_planets, total_mass, range);
130
131         ticks = SDL_GetTicks();
132         while (1) {
133                 planets = 0;
134
135                 list_for_each_entry(pl1, &planet->list, list) {
136                         pl2 = list_to_planet(pl1->list.next);
137                         list_for_each_entry_from(pl2, &planet->list, list) {
138                                 struct planet *ptmp;
139                                 if (!gravitize_planets(pl1, pl2,
140                                                        time * time_scale))
141                                         continue;
142
143                                 ptmp = list_to_planet(pl2->list.prev);
144                                 merge_planets(pl1, pl2);
145                                 pl2 = ptmp;
146                         }
147
148                         move_planet(pl1, time * time_scale);
149                 }
150
151                 SDL_LockSurface(screen);
152
153                 clear_buf(screen);
154
155                 list_for_each_entry(pl1, &planet->list, list) {
156                         draw_planet(screen, pl1, &camera);
157                         planets++;
158                 }
159
160                 SDL_UnlockSurface(screen);
161
162                 SDL_Flip(screen);
163
164                 move_camera(&camera, time);
165
166                 if (poll_events(&screen, &camera, &time_scale, time))
167                         return;
168
169                 old_ticks = ticks;
170                 ticks = SDL_GetTicks();
171                 time = (ticks - old_ticks) / 1000.0;
172                 time = MIN(time, 0.02);
173
174                 if (last_fps_time + 500 < ticks) {
175                         last_framecount = framecount - last_framecount;
176                         last_fps = last_framecount * 1000 /
177                                 (float)(ticks - last_fps_time);
178                         last_framecount = framecount;
179                         last_fps_time = ticks;
180                 }
181                 printf("  \rFrames/s: %.2f, Frame: %d, planets: %d"
182                        ", scale %.2f, zoom %.2f",
183                        last_fps, framecount++, planets, time_scale,
184                        camera.zoom);
185         }
186 }
187
188 int main(int argc, char *argv[])
189 {
190         SDL_Surface *screen;
191         int flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_RESIZABLE;
192         int planets = 100, xres = 800, yres = 600;
193         double total_mass = 50000;
194         double range = 500;
195
196         if (SDL_Init(SDL_INIT_VIDEO) != 0) {
197                 fprintf(stderr, "Unable to initialize SDL: %s\n",
198                         SDL_GetError());
199
200                 return 1;
201         }
202         atexit(SDL_Quit);
203
204         if (argc >= 2)
205                 planets = atoi(argv[1]);
206
207         if (argc >= 3)
208                 total_mass = atof(argv[2]);
209
210         if (argc >= 4)
211                 range = atof(argv[3]);
212
213         screen = SDL_SetVideoMode(xres, yres, 32, flags);
214         if (screen == NULL) {
215                 fprintf(stderr, "Unable to set video mode: %s\n",
216                         SDL_GetError());
217                 return 2;
218         }
219
220         SDL_WM_SetCaption(argv[0], NULL);
221
222         loop(screen, planets, total_mass, range);
223
224         return 0;
225 }
226