1 | /* |
2 | Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> |
3 | |
4 | This software is provided 'as-is', without any express or implied |
5 | warranty. In no event will the authors be held liable for any damages |
6 | arising from the use of this software. |
7 | |
8 | Permission is granted to anyone to use this software for any purpose, |
9 | including commercial applications, and to alter it and redistribute it |
10 | freely. |
11 | */ |
12 | |
13 | /* Simple program: draw as many random objects on the screen as possible */ |
14 | |
15 | #include <stdlib.h> |
16 | #include <stdio.h> |
17 | #include <time.h> |
18 | |
19 | #ifdef __EMSCRIPTEN__ |
20 | #include <emscripten/emscripten.h> |
21 | #endif |
22 | |
23 | #include "SDL_test_common.h" |
24 | |
25 | #define SWAP(typ,a,b) do{typ t=a;a=b;b=t;}while(0) |
26 | #define NUM_OBJECTS 100 |
27 | |
28 | static SDLTest_CommonState *state; |
29 | static int num_objects; |
30 | static SDL_bool cycle_color; |
31 | static SDL_bool cycle_alpha; |
32 | static int cycle_direction = 1; |
33 | static int current_alpha = 255; |
34 | static int current_color = 255; |
35 | static SDL_BlendMode blendMode = SDL_BLENDMODE_NONE; |
36 | |
37 | int mouse_begin_x = -1, mouse_begin_y = -1; |
38 | int done; |
39 | |
40 | void |
41 | DrawPoints(SDL_Renderer * renderer) |
42 | { |
43 | int i; |
44 | int x, y; |
45 | SDL_Rect viewport; |
46 | |
47 | /* Query the sizes */ |
48 | SDL_RenderGetViewport(renderer, &viewport); |
49 | |
50 | for (i = 0; i < num_objects * 4; ++i) { |
51 | /* Cycle the color and alpha, if desired */ |
52 | if (cycle_color) { |
53 | current_color += cycle_direction; |
54 | if (current_color < 0) { |
55 | current_color = 0; |
56 | cycle_direction = -cycle_direction; |
57 | } |
58 | if (current_color > 255) { |
59 | current_color = 255; |
60 | cycle_direction = -cycle_direction; |
61 | } |
62 | } |
63 | if (cycle_alpha) { |
64 | current_alpha += cycle_direction; |
65 | if (current_alpha < 0) { |
66 | current_alpha = 0; |
67 | cycle_direction = -cycle_direction; |
68 | } |
69 | if (current_alpha > 255) { |
70 | current_alpha = 255; |
71 | cycle_direction = -cycle_direction; |
72 | } |
73 | } |
74 | SDL_SetRenderDrawColor(renderer, 255, (Uint8) current_color, |
75 | (Uint8) current_color, (Uint8) current_alpha); |
76 | |
77 | x = rand() % viewport.w; |
78 | y = rand() % viewport.h; |
79 | SDL_RenderDrawPoint(renderer, x, y); |
80 | } |
81 | } |
82 | |
83 | #define MAX_LINES 16 |
84 | int num_lines = 0; |
85 | SDL_Rect lines[MAX_LINES]; |
86 | static int |
87 | add_line(int x1, int y1, int x2, int y2) |
88 | { |
89 | if (num_lines >= MAX_LINES) |
90 | return 0; |
91 | if ((x1 == x2) && (y1 == y2)) |
92 | return 0; |
93 | |
94 | SDL_Log("adding line (%d, %d), (%d, %d)\n" , x1, y1, x2, y2); |
95 | lines[num_lines].x = x1; |
96 | lines[num_lines].y = y1; |
97 | lines[num_lines].w = x2; |
98 | lines[num_lines].h = y2; |
99 | |
100 | return ++num_lines; |
101 | } |
102 | |
103 | |
104 | void |
105 | DrawLines(SDL_Renderer * renderer) |
106 | { |
107 | int i; |
108 | SDL_Rect viewport; |
109 | |
110 | /* Query the sizes */ |
111 | SDL_RenderGetViewport(renderer, &viewport); |
112 | |
113 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); |
114 | |
115 | for (i = 0; i < num_lines; ++i) { |
116 | if (i == -1) { |
117 | SDL_RenderDrawLine(renderer, 0, 0, viewport.w - 1, viewport.h - 1); |
118 | SDL_RenderDrawLine(renderer, 0, viewport.h - 1, viewport.w - 1, 0); |
119 | SDL_RenderDrawLine(renderer, 0, viewport.h / 2, viewport.w - 1, viewport.h / 2); |
120 | SDL_RenderDrawLine(renderer, viewport.w / 2, 0, viewport.w / 2, viewport.h - 1); |
121 | } else { |
122 | SDL_RenderDrawLine(renderer, lines[i].x, lines[i].y, lines[i].w, lines[i].h); |
123 | } |
124 | } |
125 | } |
126 | |
127 | #define MAX_RECTS 16 |
128 | int num_rects = 0; |
129 | SDL_Rect rects[MAX_RECTS]; |
130 | static int |
131 | add_rect(int x1, int y1, int x2, int y2) |
132 | { |
133 | if (num_rects >= MAX_RECTS) |
134 | return 0; |
135 | if ((x1 == x2) || (y1 == y2)) |
136 | return 0; |
137 | |
138 | if (x1 > x2) |
139 | SWAP(int, x1, x2); |
140 | if (y1 > y2) |
141 | SWAP(int, y1, y2); |
142 | |
143 | SDL_Log("adding rect (%d, %d), (%d, %d) [%dx%d]\n" , x1, y1, x2, y2, |
144 | x2 - x1, y2 - y1); |
145 | |
146 | rects[num_rects].x = x1; |
147 | rects[num_rects].y = y1; |
148 | rects[num_rects].w = x2 - x1; |
149 | rects[num_rects].h = y2 - y1; |
150 | |
151 | return ++num_rects; |
152 | } |
153 | |
154 | static void |
155 | DrawRects(SDL_Renderer * renderer) |
156 | { |
157 | SDL_SetRenderDrawColor(renderer, 255, 127, 0, 255); |
158 | SDL_RenderFillRects(renderer, rects, num_rects); |
159 | } |
160 | |
161 | static void |
162 | DrawRectLineIntersections(SDL_Renderer * renderer) |
163 | { |
164 | int i, j; |
165 | |
166 | SDL_SetRenderDrawColor(renderer, 0, 255, 55, 255); |
167 | |
168 | for (i = 0; i < num_rects; i++) |
169 | for (j = 0; j < num_lines; j++) { |
170 | int x1, y1, x2, y2; |
171 | SDL_Rect r; |
172 | |
173 | r = rects[i]; |
174 | x1 = lines[j].x; |
175 | y1 = lines[j].y; |
176 | x2 = lines[j].w; |
177 | y2 = lines[j].h; |
178 | |
179 | if (SDL_IntersectRectAndLine(&r, &x1, &y1, &x2, &y2)) { |
180 | SDL_RenderDrawLine(renderer, x1, y1, x2, y2); |
181 | } |
182 | } |
183 | } |
184 | |
185 | static void |
186 | DrawRectRectIntersections(SDL_Renderer * renderer) |
187 | { |
188 | int i, j; |
189 | |
190 | SDL_SetRenderDrawColor(renderer, 255, 200, 0, 255); |
191 | |
192 | for (i = 0; i < num_rects; i++) |
193 | for (j = i + 1; j < num_rects; j++) { |
194 | SDL_Rect r; |
195 | if (SDL_IntersectRect(&rects[i], &rects[j], &r)) { |
196 | SDL_RenderFillRect(renderer, &r); |
197 | } |
198 | } |
199 | } |
200 | |
201 | void |
202 | loop() |
203 | { |
204 | int i; |
205 | SDL_Event event; |
206 | |
207 | /* Check for events */ |
208 | while (SDL_PollEvent(&event)) { |
209 | SDLTest_CommonEvent(state, &event, &done); |
210 | switch (event.type) { |
211 | case SDL_MOUSEBUTTONDOWN: |
212 | mouse_begin_x = event.button.x; |
213 | mouse_begin_y = event.button.y; |
214 | break; |
215 | case SDL_MOUSEBUTTONUP: |
216 | if (event.button.button == 3) |
217 | add_line(mouse_begin_x, mouse_begin_y, event.button.x, |
218 | event.button.y); |
219 | if (event.button.button == 1) |
220 | add_rect(mouse_begin_x, mouse_begin_y, event.button.x, |
221 | event.button.y); |
222 | break; |
223 | case SDL_KEYDOWN: |
224 | switch (event.key.keysym.sym) { |
225 | case 'l': |
226 | if (event.key.keysym.mod & KMOD_SHIFT) |
227 | num_lines = 0; |
228 | else |
229 | add_line(rand() % 640, rand() % 480, rand() % 640, |
230 | rand() % 480); |
231 | break; |
232 | case 'r': |
233 | if (event.key.keysym.mod & KMOD_SHIFT) |
234 | num_rects = 0; |
235 | else |
236 | add_rect(rand() % 640, rand() % 480, rand() % 640, |
237 | rand() % 480); |
238 | break; |
239 | } |
240 | break; |
241 | default: |
242 | break; |
243 | } |
244 | } |
245 | for (i = 0; i < state->num_windows; ++i) { |
246 | SDL_Renderer *renderer = state->renderers[i]; |
247 | if (state->windows[i] == NULL) |
248 | continue; |
249 | SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); |
250 | SDL_RenderClear(renderer); |
251 | |
252 | DrawRects(renderer); |
253 | DrawPoints(renderer); |
254 | DrawRectRectIntersections(renderer); |
255 | DrawLines(renderer); |
256 | DrawRectLineIntersections(renderer); |
257 | |
258 | SDL_RenderPresent(renderer); |
259 | } |
260 | #ifdef __EMSCRIPTEN__ |
261 | if (done) { |
262 | emscripten_cancel_main_loop(); |
263 | } |
264 | #endif |
265 | } |
266 | |
267 | int |
268 | main(int argc, char *argv[]) |
269 | { |
270 | int i; |
271 | Uint32 then, now, frames; |
272 | |
273 | /* Enable standard application logging */ |
274 | SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); |
275 | |
276 | /* Initialize parameters */ |
277 | num_objects = NUM_OBJECTS; |
278 | |
279 | /* Initialize test framework */ |
280 | state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); |
281 | if (!state) { |
282 | return 1; |
283 | } |
284 | for (i = 1; i < argc;) { |
285 | int consumed; |
286 | |
287 | consumed = SDLTest_CommonArg(state, i); |
288 | if (consumed == 0) { |
289 | consumed = -1; |
290 | if (SDL_strcasecmp(argv[i], "--blend" ) == 0) { |
291 | if (argv[i + 1]) { |
292 | if (SDL_strcasecmp(argv[i + 1], "none" ) == 0) { |
293 | blendMode = SDL_BLENDMODE_NONE; |
294 | consumed = 2; |
295 | } else if (SDL_strcasecmp(argv[i + 1], "blend" ) == 0) { |
296 | blendMode = SDL_BLENDMODE_BLEND; |
297 | consumed = 2; |
298 | } else if (SDL_strcasecmp(argv[i + 1], "add" ) == 0) { |
299 | blendMode = SDL_BLENDMODE_ADD; |
300 | consumed = 2; |
301 | } else if (SDL_strcasecmp(argv[i + 1], "mod" ) == 0) { |
302 | blendMode = SDL_BLENDMODE_MOD; |
303 | consumed = 2; |
304 | } |
305 | } |
306 | } else if (SDL_strcasecmp(argv[i], "--cyclecolor" ) == 0) { |
307 | cycle_color = SDL_TRUE; |
308 | consumed = 1; |
309 | } else if (SDL_strcasecmp(argv[i], "--cyclealpha" ) == 0) { |
310 | cycle_alpha = SDL_TRUE; |
311 | consumed = 1; |
312 | } else if (SDL_isdigit(*argv[i])) { |
313 | num_objects = SDL_atoi(argv[i]); |
314 | consumed = 1; |
315 | } |
316 | } |
317 | if (consumed < 0) { |
318 | static const char *options[] = { "[--blend none|blend|add|mod]" , "[--cyclecolor]" , "[--cyclealpha]" , NULL }; |
319 | SDLTest_CommonLogUsage(state, argv[0], options); |
320 | return 1; |
321 | } |
322 | i += consumed; |
323 | } |
324 | if (!SDLTest_CommonInit(state)) { |
325 | return 2; |
326 | } |
327 | |
328 | /* Create the windows and initialize the renderers */ |
329 | for (i = 0; i < state->num_windows; ++i) { |
330 | SDL_Renderer *renderer = state->renderers[i]; |
331 | SDL_SetRenderDrawBlendMode(renderer, blendMode); |
332 | SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); |
333 | SDL_RenderClear(renderer); |
334 | } |
335 | |
336 | srand(time(NULL)); |
337 | |
338 | /* Main render loop */ |
339 | frames = 0; |
340 | then = SDL_GetTicks(); |
341 | done = 0; |
342 | |
343 | #ifdef __EMSCRIPTEN__ |
344 | emscripten_set_main_loop(loop, 0, 1); |
345 | #else |
346 | while (!done) { |
347 | ++frames; |
348 | loop(); |
349 | } |
350 | #endif |
351 | |
352 | SDLTest_CommonQuit(state); |
353 | |
354 | /* Print out some timing information */ |
355 | now = SDL_GetTicks(); |
356 | if (now > then) { |
357 | double fps = ((double) frames * 1000) / (now - then); |
358 | SDL_Log("%2.2f frames per second\n" , fps); |
359 | } |
360 | return 0; |
361 | } |
362 | |
363 | /* vi: set ts=4 sw=4 expandtab: */ |
364 | |