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 | /* Simple program: Move N sprites around on the screen as fast as possible */ |
13 | |
14 | #include <stdlib.h> |
15 | #include <stdio.h> |
16 | #include <time.h> |
17 | |
18 | #ifdef __EMSCRIPTEN__ |
19 | #include <emscripten/emscripten.h> |
20 | #endif |
21 | |
22 | #include "SDL_test_common.h" |
23 | |
24 | |
25 | static SDLTest_CommonState *state; |
26 | |
27 | typedef struct { |
28 | SDL_Window *window; |
29 | SDL_Renderer *renderer; |
30 | SDL_Texture *background; |
31 | SDL_Texture *sprite; |
32 | SDL_Rect sprite_rect; |
33 | int scale_direction; |
34 | } DrawState; |
35 | |
36 | DrawState *drawstates; |
37 | int done; |
38 | |
39 | /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ |
40 | static void |
41 | quit(int rc) |
42 | { |
43 | SDLTest_CommonQuit(state); |
44 | exit(rc); |
45 | } |
46 | |
47 | SDL_Texture * |
48 | LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent) |
49 | { |
50 | SDL_Surface *temp; |
51 | SDL_Texture *texture; |
52 | |
53 | /* Load the sprite image */ |
54 | temp = SDL_LoadBMP(file); |
55 | if (temp == NULL) { |
56 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s" , file, SDL_GetError()); |
57 | return NULL; |
58 | } |
59 | |
60 | /* Set transparent pixel as the pixel at (0,0) */ |
61 | if (transparent) { |
62 | if (temp->format->palette) { |
63 | SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels); |
64 | } else { |
65 | switch (temp->format->BitsPerPixel) { |
66 | case 15: |
67 | SDL_SetColorKey(temp, SDL_TRUE, |
68 | (*(Uint16 *) temp->pixels) & 0x00007FFF); |
69 | break; |
70 | case 16: |
71 | SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels); |
72 | break; |
73 | case 24: |
74 | SDL_SetColorKey(temp, SDL_TRUE, |
75 | (*(Uint32 *) temp->pixels) & 0x00FFFFFF); |
76 | break; |
77 | case 32: |
78 | SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels); |
79 | break; |
80 | } |
81 | } |
82 | } |
83 | |
84 | /* Create textures from the image */ |
85 | texture = SDL_CreateTextureFromSurface(renderer, temp); |
86 | if (!texture) { |
87 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n" , SDL_GetError()); |
88 | SDL_FreeSurface(temp); |
89 | return NULL; |
90 | } |
91 | SDL_FreeSurface(temp); |
92 | |
93 | /* We're ready to roll. :) */ |
94 | return texture; |
95 | } |
96 | |
97 | void |
98 | Draw(DrawState *s) |
99 | { |
100 | SDL_Rect viewport; |
101 | SDL_Texture *target; |
102 | SDL_Point *center=NULL; |
103 | SDL_Point origin = {0,0}; |
104 | |
105 | SDL_RenderGetViewport(s->renderer, &viewport); |
106 | |
107 | target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h); |
108 | SDL_SetRenderTarget(s->renderer, target); |
109 | |
110 | /* Draw the background */ |
111 | SDL_RenderCopy(s->renderer, s->background, NULL, NULL); |
112 | |
113 | /* Scale and draw the sprite */ |
114 | s->sprite_rect.w += s->scale_direction; |
115 | s->sprite_rect.h += s->scale_direction; |
116 | if (s->scale_direction > 0) { |
117 | center = &origin; |
118 | if (s->sprite_rect.w >= viewport.w || s->sprite_rect.h >= viewport.h) { |
119 | s->scale_direction = -1; |
120 | } |
121 | } else { |
122 | if (s->sprite_rect.w <= 1 || s->sprite_rect.h <= 1) { |
123 | s->scale_direction = 1; |
124 | } |
125 | } |
126 | s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2; |
127 | s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2; |
128 | |
129 | SDL_RenderCopyEx(s->renderer, s->sprite, NULL, &s->sprite_rect, (double)s->sprite_rect.w, center, (SDL_RendererFlip)s->scale_direction); |
130 | |
131 | SDL_SetRenderTarget(s->renderer, NULL); |
132 | SDL_RenderCopy(s->renderer, target, NULL, NULL); |
133 | SDL_DestroyTexture(target); |
134 | |
135 | /* Update the screen! */ |
136 | SDL_RenderPresent(s->renderer); |
137 | /* SDL_Delay(10); */ |
138 | } |
139 | |
140 | void loop() |
141 | { |
142 | int i; |
143 | SDL_Event event; |
144 | |
145 | /* Check for events */ |
146 | |
147 | while (SDL_PollEvent(&event)) { |
148 | SDLTest_CommonEvent(state, &event, &done); |
149 | } |
150 | for (i = 0; i < state->num_windows; ++i) { |
151 | if (state->windows[i] == NULL) |
152 | continue; |
153 | Draw(&drawstates[i]); |
154 | } |
155 | #ifdef __EMSCRIPTEN__ |
156 | if (done) { |
157 | emscripten_cancel_main_loop(); |
158 | } |
159 | #endif |
160 | } |
161 | |
162 | int |
163 | main(int argc, char *argv[]) |
164 | { |
165 | int i; |
166 | int frames; |
167 | Uint32 then, now; |
168 | |
169 | /* Enable standard application logging */ |
170 | SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); |
171 | |
172 | /* Initialize test framework */ |
173 | state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); |
174 | if (!state) { |
175 | return 1; |
176 | } |
177 | |
178 | if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) { |
179 | SDLTest_CommonQuit(state); |
180 | return 1; |
181 | } |
182 | |
183 | drawstates = SDL_stack_alloc(DrawState, state->num_windows); |
184 | for (i = 0; i < state->num_windows; ++i) { |
185 | DrawState *drawstate = &drawstates[i]; |
186 | |
187 | drawstate->window = state->windows[i]; |
188 | drawstate->renderer = state->renderers[i]; |
189 | drawstate->sprite = LoadTexture(drawstate->renderer, "icon.bmp" , SDL_TRUE); |
190 | drawstate->background = LoadTexture(drawstate->renderer, "sample.bmp" , SDL_FALSE); |
191 | if (!drawstate->sprite || !drawstate->background) { |
192 | quit(2); |
193 | } |
194 | SDL_QueryTexture(drawstate->sprite, NULL, NULL, |
195 | &drawstate->sprite_rect.w, &drawstate->sprite_rect.h); |
196 | drawstate->scale_direction = 1; |
197 | } |
198 | |
199 | /* Main render loop */ |
200 | frames = 0; |
201 | then = SDL_GetTicks(); |
202 | done = 0; |
203 | |
204 | #ifdef __EMSCRIPTEN__ |
205 | emscripten_set_main_loop(loop, 0, 1); |
206 | #else |
207 | while (!done) { |
208 | ++frames; |
209 | loop(); |
210 | } |
211 | #endif |
212 | /* Print out some timing information */ |
213 | now = SDL_GetTicks(); |
214 | if (now > then) { |
215 | double fps = ((double) frames * 1000) / (now - then); |
216 | SDL_Log("%2.2f frames per second\n" , fps); |
217 | } |
218 | |
219 | SDL_stack_free(drawstates); |
220 | |
221 | quit(0); |
222 | return 0; |
223 | } |
224 | |
225 | /* vi: set ts=4 sw=4 expandtab: */ |
226 | |