testsprite2.c (12305B)
1/* 2 Copyright (C) 1997-2014 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#include "SDL_test.h" 19#include "SDL_test_common.h" 20 21#define NUM_SPRITES 100 22#define MAX_SPEED 1 23 24static SDLTest_CommonState *state; 25static int num_sprites; 26static SDL_Texture **sprites; 27static SDL_bool cycle_color; 28static SDL_bool cycle_alpha; 29static int cycle_direction = 1; 30static int current_alpha = 0; 31static int current_color = 0; 32static SDL_Rect *positions; 33static SDL_Rect *velocities; 34static int sprite_w, sprite_h; 35static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND; 36 37/* Number of iterations to move sprites - used for visual tests. */ 38/* -1: infinite random moves (default); >=0: enables N deterministic moves */ 39static int iterations = -1; 40 41/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ 42static void 43quit(int rc) 44{ 45 SDL_free(sprites); 46 SDL_free(positions); 47 SDL_free(velocities); 48 SDLTest_CommonQuit(state); 49 exit(rc); 50} 51 52int 53LoadSprite(const char *file) 54{ 55 int i; 56 SDL_Surface *temp; 57 58 /* Load the sprite image */ 59 temp = SDL_LoadBMP(file); 60 if (temp == NULL) { 61 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError()); 62 return (-1); 63 } 64 sprite_w = temp->w; 65 sprite_h = temp->h; 66 67 /* Set transparent pixel as the pixel at (0,0) */ 68 if (temp->format->palette) { 69 SDL_SetColorKey(temp, 1, *(Uint8 *) temp->pixels); 70 } else { 71 switch (temp->format->BitsPerPixel) { 72 case 15: 73 SDL_SetColorKey(temp, 1, (*(Uint16 *) temp->pixels) & 0x00007FFF); 74 break; 75 case 16: 76 SDL_SetColorKey(temp, 1, *(Uint16 *) temp->pixels); 77 break; 78 case 24: 79 SDL_SetColorKey(temp, 1, (*(Uint32 *) temp->pixels) & 0x00FFFFFF); 80 break; 81 case 32: 82 SDL_SetColorKey(temp, 1, *(Uint32 *) temp->pixels); 83 break; 84 } 85 } 86 87 /* Create textures from the image */ 88 for (i = 0; i < state->num_windows; ++i) { 89 SDL_Renderer *renderer = state->renderers[i]; 90 sprites[i] = SDL_CreateTextureFromSurface(renderer, temp); 91 if (!sprites[i]) { 92 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError()); 93 SDL_FreeSurface(temp); 94 return (-1); 95 } 96 SDL_SetTextureBlendMode(sprites[i], blendMode); 97 } 98 SDL_FreeSurface(temp); 99 100 /* We're ready to roll. :) */ 101 return (0); 102} 103 104void 105MoveSprites(SDL_Renderer * renderer, SDL_Texture * sprite) 106{ 107 int i; 108 SDL_Rect viewport, temp; 109 SDL_Rect *position, *velocity; 110 111 /* Query the sizes */ 112 SDL_RenderGetViewport(renderer, &viewport); 113 114 /* Cycle the color and alpha, if desired */ 115 if (cycle_color) { 116 current_color += cycle_direction; 117 if (current_color < 0) { 118 current_color = 0; 119 cycle_direction = -cycle_direction; 120 } 121 if (current_color > 255) { 122 current_color = 255; 123 cycle_direction = -cycle_direction; 124 } 125 SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color, 126 (Uint8) current_color); 127 } 128 if (cycle_alpha) { 129 current_alpha += cycle_direction; 130 if (current_alpha < 0) { 131 current_alpha = 0; 132 cycle_direction = -cycle_direction; 133 } 134 if (current_alpha > 255) { 135 current_alpha = 255; 136 cycle_direction = -cycle_direction; 137 } 138 SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha); 139 } 140 141 /* Draw a gray background */ 142 SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); 143 SDL_RenderClear(renderer); 144 145 /* Test points */ 146 SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF); 147 SDL_RenderDrawPoint(renderer, 0, 0); 148 SDL_RenderDrawPoint(renderer, viewport.w-1, 0); 149 SDL_RenderDrawPoint(renderer, 0, viewport.h-1); 150 SDL_RenderDrawPoint(renderer, viewport.w-1, viewport.h-1); 151 152 /* Test horizontal and vertical lines */ 153 SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF); 154 SDL_RenderDrawLine(renderer, 1, 0, viewport.w-2, 0); 155 SDL_RenderDrawLine(renderer, 1, viewport.h-1, viewport.w-2, viewport.h-1); 156 SDL_RenderDrawLine(renderer, 0, 1, 0, viewport.h-2); 157 SDL_RenderDrawLine(renderer, viewport.w-1, 1, viewport.w-1, viewport.h-2); 158 159 /* Test fill and copy */ 160 SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); 161 temp.x = 1; 162 temp.y = 1; 163 temp.w = sprite_w; 164 temp.h = sprite_h; 165 SDL_RenderFillRect(renderer, &temp); 166 SDL_RenderCopy(renderer, sprite, NULL, &temp); 167 temp.x = viewport.w-sprite_w-1; 168 temp.y = 1; 169 temp.w = sprite_w; 170 temp.h = sprite_h; 171 SDL_RenderFillRect(renderer, &temp); 172 SDL_RenderCopy(renderer, sprite, NULL, &temp); 173 temp.x = 1; 174 temp.y = viewport.h-sprite_h-1; 175 temp.w = sprite_w; 176 temp.h = sprite_h; 177 SDL_RenderFillRect(renderer, &temp); 178 SDL_RenderCopy(renderer, sprite, NULL, &temp); 179 temp.x = viewport.w-sprite_w-1; 180 temp.y = viewport.h-sprite_h-1; 181 temp.w = sprite_w; 182 temp.h = sprite_h; 183 SDL_RenderFillRect(renderer, &temp); 184 SDL_RenderCopy(renderer, sprite, NULL, &temp); 185 186 /* Test diagonal lines */ 187 SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF); 188 SDL_RenderDrawLine(renderer, sprite_w, sprite_h, 189 viewport.w-sprite_w-2, viewport.h-sprite_h-2); 190 SDL_RenderDrawLine(renderer, viewport.w-sprite_w-2, sprite_h, 191 sprite_w, viewport.h-sprite_h-2); 192 193 /* Conditionally move the sprites, bounce at the wall */ 194 if (iterations == -1 || iterations > 0) { 195 for (i = 0; i < num_sprites; ++i) { 196 position = &positions[i]; 197 velocity = &velocities[i]; 198 position->x += velocity->x; 199 if ((position->x < 0) || (position->x >= (viewport.w - sprite_w))) { 200 velocity->x = -velocity->x; 201 position->x += velocity->x; 202 } 203 position->y += velocity->y; 204 if ((position->y < 0) || (position->y >= (viewport.h - sprite_h))) { 205 velocity->y = -velocity->y; 206 position->y += velocity->y; 207 } 208 209 } 210 211 /* Countdown sprite-move iterations and disable color changes at iteration end - used for visual tests. */ 212 if (iterations > 0) { 213 iterations--; 214 if (iterations == 0) { 215 cycle_alpha = SDL_FALSE; 216 cycle_color = SDL_FALSE; 217 } 218 } 219 } 220 221 /* Draw sprites */ 222 for (i = 0; i < num_sprites; ++i) { 223 position = &positions[i]; 224 225 /* Blit the sprite onto the screen */ 226 SDL_RenderCopy(renderer, sprite, NULL, position); 227 } 228 229 /* Update the screen! */ 230 SDL_RenderPresent(renderer); 231} 232 233int 234main(int argc, char *argv[]) 235{ 236 int i, done; 237 SDL_Event event; 238 Uint32 then, now, frames; 239 Uint64 seed; 240 const char *icon = "icon.bmp"; 241 242 /* Initialize parameters */ 243 num_sprites = NUM_SPRITES; 244 245 /* Initialize test framework */ 246 state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); 247 if (!state) { 248 return 1; 249 } 250 251 for (i = 1; i < argc;) { 252 int consumed; 253 254 consumed = SDLTest_CommonArg(state, i); 255 if (consumed == 0) { 256 consumed = -1; 257 if (SDL_strcasecmp(argv[i], "--blend") == 0) { 258 if (argv[i + 1]) { 259 if (SDL_strcasecmp(argv[i + 1], "none") == 0) { 260 blendMode = SDL_BLENDMODE_NONE; 261 consumed = 2; 262 } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) { 263 blendMode = SDL_BLENDMODE_BLEND; 264 consumed = 2; 265 } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) { 266 blendMode = SDL_BLENDMODE_ADD; 267 consumed = 2; 268 } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) { 269 blendMode = SDL_BLENDMODE_MOD; 270 consumed = 2; 271 } 272 } 273 } else if (SDL_strcasecmp(argv[i], "--iterations") == 0) { 274 if (argv[i + 1]) { 275 iterations = SDL_atoi(argv[i + 1]); 276 if (iterations < -1) iterations = -1; 277 consumed = 2; 278 } 279 } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) { 280 cycle_color = SDL_TRUE; 281 consumed = 1; 282 } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) { 283 cycle_alpha = SDL_TRUE; 284 consumed = 1; 285 } else if (SDL_isdigit(*argv[i])) { 286 num_sprites = SDL_atoi(argv[i]); 287 consumed = 1; 288 } else if (argv[i][0] != '-') { 289 icon = argv[i]; 290 consumed = 1; 291 } 292 } 293 if (consumed < 0) { 294 SDL_Log("Usage: %s %s [--blend none|blend|add|mod] [--cyclecolor] [--cyclealpha] [--iterations N] [num_sprites] [icon.bmp]\n", 295 argv[0], SDLTest_CommonUsage(state)); 296 quit(1); 297 } 298 i += consumed; 299 } 300 if (!SDLTest_CommonInit(state)) { 301 quit(2); 302 } 303 304 /* Create the windows, initialize the renderers, and load the textures */ 305 sprites = 306 (SDL_Texture **) SDL_malloc(state->num_windows * sizeof(*sprites)); 307 if (!sprites) { 308 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); 309 quit(2); 310 } 311 for (i = 0; i < state->num_windows; ++i) { 312 SDL_Renderer *renderer = state->renderers[i]; 313 SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); 314 SDL_RenderClear(renderer); 315 } 316 if (LoadSprite(icon) < 0) { 317 quit(2); 318 } 319 320 /* Allocate memory for the sprite info */ 321 positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect)); 322 velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect)); 323 if (!positions || !velocities) { 324 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); 325 quit(2); 326 } 327 328 /* Position sprites and set their velocities using the fuzzer */ 329 if (iterations >= 0) { 330 /* Deterministic seed - used for visual tests */ 331 seed = (Uint64)iterations; 332 } else { 333 /* Pseudo-random seed generated from the time */ 334 seed = (Uint64)time(NULL); 335 } 336 SDLTest_FuzzerInit(seed); 337 for (i = 0; i < num_sprites; ++i) { 338 positions[i].x = SDLTest_RandomIntegerInRange(0, state->window_w - sprite_w); 339 positions[i].y = SDLTest_RandomIntegerInRange(0, state->window_h - sprite_h); 340 positions[i].w = sprite_w; 341 positions[i].h = sprite_h; 342 velocities[i].x = 0; 343 velocities[i].y = 0; 344 while (!velocities[i].x && !velocities[i].y) { 345 velocities[i].x = SDLTest_RandomIntegerInRange(-MAX_SPEED, MAX_SPEED); 346 velocities[i].y = SDLTest_RandomIntegerInRange(-MAX_SPEED, MAX_SPEED); 347 } 348 } 349 350 /* Main render loop */ 351 frames = 0; 352 then = SDL_GetTicks(); 353 done = 0; 354 while (!done) { 355 /* Check for events */ 356 ++frames; 357 while (SDL_PollEvent(&event)) { 358 SDLTest_CommonEvent(state, &event, &done); 359 } 360 for (i = 0; i < state->num_windows; ++i) { 361 if (state->windows[i] == NULL) 362 continue; 363 MoveSprites(state->renderers[i], sprites[i]); 364 } 365 } 366 367 /* Print out some timing information */ 368 now = SDL_GetTicks(); 369 if (now > then) { 370 double fps = ((double) frames * 1000) / (now - then); 371 SDL_Log("%2.2f frames per second\n", fps); 372 } 373 quit(0); 374 return 0; 375} 376 377/* vi: set ts=4 sw=4 expandtab: */