test/testsprite2.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 19 Sep 2009 05:45:49 +0000
changeset 3266 7856dfe3a44f
parent 3265 8f534bf37bef
child 3285 0d7b20a4a629
permissions -rw-r--r--
More test coverage
     1 /* Simple program:  Move N sprites around on the screen as fast as possible */
     2 
     3 #include <stdlib.h>
     4 #include <stdio.h>
     5 #include <time.h>
     6 
     7 #include "common.h"
     8 
     9 #define NUM_SPRITES	100
    10 #define MAX_SPEED 	1
    11 
    12 static CommonState *state;
    13 static int num_sprites;
    14 static SDL_TextureID *sprites;
    15 static SDL_bool cycle_color;
    16 static SDL_bool cycle_alpha;
    17 static int cycle_direction = 1;
    18 static int current_alpha = 0;
    19 static int current_color = 0;
    20 static SDL_Rect *positions;
    21 static SDL_Rect *velocities;
    22 static int sprite_w, sprite_h;
    23 static SDL_BlendMode blendMode = SDL_BLENDMODE_MASK;
    24 static SDL_TextureScaleMode scaleMode = SDL_TEXTURESCALEMODE_NONE;
    25 
    26 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    27 static void
    28 quit(int rc)
    29 {
    30     if (sprites) {
    31         SDL_free(sprites);
    32     }
    33     if (positions) {
    34         SDL_free(positions);
    35     }
    36     if (velocities) {
    37         SDL_free(velocities);
    38     }
    39     CommonQuit(state);
    40     exit(rc);
    41 }
    42 
    43 int
    44 LoadSprite(char *file)
    45 {
    46     int i;
    47     SDL_Surface *temp;
    48 
    49     /* Load the sprite image */
    50     temp = SDL_LoadBMP(file);
    51     if (temp == NULL) {
    52         fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
    53         return (-1);
    54     }
    55     sprite_w = temp->w;
    56     sprite_h = temp->h;
    57 
    58     /* Set transparent pixel as the pixel at (0,0) */
    59     if (temp->format->palette) {
    60         SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint8 *) temp->pixels);
    61     } else {
    62         switch (temp->format->BitsPerPixel) {
    63         case 15:
    64             SDL_SetColorKey(temp, SDL_SRCCOLORKEY,
    65                             (*(Uint16 *) temp->pixels) & 0x00007FFF);
    66             break;
    67         case 16:
    68             SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint16 *) temp->pixels);
    69             break;
    70         case 24:
    71             SDL_SetColorKey(temp, SDL_SRCCOLORKEY,
    72                             (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
    73             break;
    74         case 32:
    75             SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint32 *) temp->pixels);
    76             break;
    77         }
    78     }
    79 
    80     /* Create textures from the image */
    81     for (i = 0; i < state->num_windows; ++i) {
    82         SDL_SelectRenderer(state->windows[i]);
    83         sprites[i] = SDL_CreateTextureFromSurface(0, temp);
    84         if (!sprites[i]) {
    85             fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
    86             SDL_FreeSurface(temp);
    87             return (-1);
    88         }
    89         SDL_SetTextureBlendMode(sprites[i], blendMode);
    90         SDL_SetTextureScaleMode(sprites[i], scaleMode);
    91     }
    92     SDL_FreeSurface(temp);
    93 
    94     /* We're ready to roll. :) */
    95     return (0);
    96 }
    97 
    98 void
    99 MoveSprites(SDL_WindowID window, SDL_TextureID sprite)
   100 {
   101     int i, n;
   102     int window_w, window_h;
   103     SDL_Rect temp;
   104     SDL_Rect *position, *velocity;
   105 
   106     SDL_SelectRenderer(window);
   107 
   108     /* Query the sizes */
   109     SDL_GetWindowSize(window, &window_w, &window_h);
   110 
   111     /* Cycle the color and alpha, if desired */
   112     if (cycle_color) {
   113         current_color += cycle_direction;
   114         if (current_color < 0) {
   115             current_color = 0;
   116             cycle_direction = -cycle_direction;
   117         }
   118         if (current_color > 255) {
   119             current_color = 255;
   120             cycle_direction = -cycle_direction;
   121         }
   122         SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color,
   123                                (Uint8) current_color);
   124     }
   125     if (cycle_alpha) {
   126         current_alpha += cycle_direction;
   127         if (current_alpha < 0) {
   128             current_alpha = 0;
   129             cycle_direction = -cycle_direction;
   130         }
   131         if (current_alpha > 255) {
   132             current_alpha = 255;
   133             cycle_direction = -cycle_direction;
   134         }
   135         SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha);
   136     }
   137 
   138     /* Draw a gray background */
   139     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
   140     SDL_RenderFill(NULL);
   141 
   142     /* Test points */
   143     SDL_SetRenderDrawColor(0xFF, 0x00, 0x00, 0xFF);
   144     SDL_RenderPoint(0, 0);
   145     SDL_RenderPoint(window_w-1, 0);
   146     SDL_RenderPoint(0, window_h-1);
   147     SDL_RenderPoint(window_w-1, window_h-1);
   148 
   149     /* Test horizontal and vertical lines */
   150     SDL_SetRenderDrawColor(0x00, 0xFF, 0x00, 0xFF);
   151     SDL_RenderLine(1, 0, window_w-2, 0);
   152     SDL_RenderLine(1, window_h-1, window_w-2, window_h-1);
   153     SDL_RenderLine(0, 1, 0, window_h-2);
   154     SDL_RenderLine(window_w-1, 1, window_w-1, window_h-2);
   155 
   156     /* Test fill and copy */
   157     SDL_SetRenderDrawColor(0xFF, 0xFF, 0xFF, 0xFF);
   158     temp.x = 1;
   159     temp.y = 1;
   160     temp.w = sprite_w;
   161     temp.h = sprite_h;
   162     SDL_RenderFill(&temp);
   163     SDL_RenderCopy(sprite, NULL, &temp);
   164     temp.x = window_w-sprite_w-1;
   165     temp.y = 1;
   166     temp.w = sprite_w;
   167     temp.h = sprite_h;
   168     SDL_RenderFill(&temp);
   169     SDL_RenderCopy(sprite, NULL, &temp);
   170     temp.x = 1;
   171     temp.y = window_h-sprite_h-1;
   172     temp.w = sprite_w;
   173     temp.h = sprite_h;
   174     SDL_RenderFill(&temp);
   175     SDL_RenderCopy(sprite, NULL, &temp);
   176     temp.x = window_w-sprite_w-1;
   177     temp.y = window_h-sprite_h-1;
   178     temp.w = sprite_w;
   179     temp.h = sprite_h;
   180     SDL_RenderFill(&temp);
   181     SDL_RenderCopy(sprite, NULL, &temp);
   182 
   183     /* Test diagonal lines */
   184     SDL_SetRenderDrawColor(0x00, 0xFF, 0x00, 0xFF);
   185     SDL_RenderLine(sprite_w, sprite_h,
   186                    window_w-sprite_w-2, window_h-sprite_h-2);
   187     SDL_RenderLine(window_w-sprite_w-2, sprite_h,
   188                    sprite_w, window_h-sprite_h-2);
   189 
   190     /* Move the sprite, bounce at the wall, and draw */
   191     n = 0;
   192     for (i = 0; i < num_sprites; ++i) {
   193         position = &positions[i];
   194         velocity = &velocities[i];
   195         position->x += velocity->x;
   196         if ((position->x < 0) || (position->x >= (window_w - sprite_w))) {
   197             velocity->x = -velocity->x;
   198             position->x += velocity->x;
   199         }
   200         position->y += velocity->y;
   201         if ((position->y < 0) || (position->y >= (window_h - sprite_h))) {
   202             velocity->y = -velocity->y;
   203             position->y += velocity->y;
   204         }
   205 
   206         /* Blit the sprite onto the screen */
   207         SDL_RenderCopy(sprite, NULL, position);
   208     }
   209 
   210     /* Update the screen! */
   211     SDL_RenderPresent();
   212 }
   213 
   214 int
   215 main(int argc, char *argv[])
   216 {
   217     int i, done;
   218     SDL_Event event;
   219     Uint32 then, now, frames;
   220 
   221     /* Initialize parameters */
   222     num_sprites = NUM_SPRITES;
   223 
   224     /* Initialize test framework */
   225     state = CommonCreateState(argv, SDL_INIT_VIDEO);
   226     if (!state) {
   227         return 1;
   228     }
   229     for (i = 1; i < argc;) {
   230         int consumed;
   231 
   232         consumed = CommonArg(state, i);
   233         if (consumed == 0) {
   234             consumed = -1;
   235             if (SDL_strcasecmp(argv[i], "--blend") == 0) {
   236                 if (argv[i + 1]) {
   237                     if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
   238                         blendMode = SDL_BLENDMODE_NONE;
   239                         consumed = 2;
   240                     } else if (SDL_strcasecmp(argv[i + 1], "mask") == 0) {
   241                         blendMode = SDL_BLENDMODE_MASK;
   242                         consumed = 2;
   243                     } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
   244                         blendMode = SDL_BLENDMODE_BLEND;
   245                         consumed = 2;
   246                     } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
   247                         blendMode = SDL_BLENDMODE_ADD;
   248                         consumed = 2;
   249                     } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
   250                         blendMode = SDL_BLENDMODE_MOD;
   251                         consumed = 2;
   252                     }
   253                 }
   254             } else if (SDL_strcasecmp(argv[i], "--scale") == 0) {
   255                 if (argv[i + 1]) {
   256                     if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
   257                         scaleMode = SDL_TEXTURESCALEMODE_NONE;
   258                         consumed = 2;
   259                     } else if (SDL_strcasecmp(argv[i + 1], "fast") == 0) {
   260                         scaleMode = SDL_TEXTURESCALEMODE_FAST;
   261                         consumed = 2;
   262                     } else if (SDL_strcasecmp(argv[i + 1], "slow") == 0) {
   263                         scaleMode = SDL_TEXTURESCALEMODE_SLOW;
   264                         consumed = 2;
   265                     } else if (SDL_strcasecmp(argv[i + 1], "best") == 0) {
   266                         scaleMode = SDL_TEXTURESCALEMODE_BEST;
   267                         consumed = 2;
   268                     }
   269                 }
   270             } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
   271                 cycle_color = SDL_TRUE;
   272                 consumed = 1;
   273             } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
   274                 cycle_alpha = SDL_TRUE;
   275                 consumed = 1;
   276             } else if (SDL_isdigit(*argv[i])) {
   277                 num_sprites = SDL_atoi(argv[i]);
   278                 consumed = 1;
   279             }
   280         }
   281         if (consumed < 0) {
   282             fprintf(stderr,
   283                     "Usage: %s %s [--blend none|mask|blend|add|mod] [--scale none|fast|slow|best] [--cyclecolor] [--cyclealpha]\n",
   284                     argv[0], CommonUsage(state));
   285             quit(1);
   286         }
   287         i += consumed;
   288     }
   289     if (!CommonInit(state)) {
   290         quit(2);
   291     }
   292 
   293     /* Create the windows, initialize the renderers, and load the textures */
   294     sprites =
   295         (SDL_TextureID *) SDL_malloc(state->num_windows * sizeof(*sprites));
   296     if (!sprites) {
   297         fprintf(stderr, "Out of memory!\n");
   298         quit(2);
   299     }
   300     for (i = 0; i < state->num_windows; ++i) {
   301         SDL_SelectRenderer(state->windows[i]);
   302         SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
   303         SDL_RenderFill(NULL);
   304     }
   305     if (LoadSprite("icon.bmp") < 0) {
   306         quit(2);
   307     }
   308 
   309     /* Allocate memory for the sprite info */
   310     positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
   311     velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
   312     if (!positions || !velocities) {
   313         fprintf(stderr, "Out of memory!\n");
   314         quit(2);
   315     }
   316     srand(time(NULL));
   317     if (scaleMode != SDL_TEXTURESCALEMODE_NONE) {
   318         sprite_w += sprite_w / 2;
   319         sprite_h += sprite_h / 2;
   320     }
   321     for (i = 0; i < num_sprites; ++i) {
   322         positions[i].x = rand() % (state->window_w - sprite_w);
   323         positions[i].y = rand() % (state->window_h - sprite_h);
   324         positions[i].w = sprite_w;
   325         positions[i].h = sprite_h;
   326         velocities[i].x = 0;
   327         velocities[i].y = 0;
   328         while (!velocities[i].x && !velocities[i].y) {
   329             velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
   330             velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
   331         }
   332     }
   333 
   334     /* Main render loop */
   335     frames = 0;
   336     then = SDL_GetTicks();
   337     done = 0;
   338     while (!done) {
   339         /* Check for events */
   340         ++frames;
   341         while (SDL_PollEvent(&event)) {
   342             CommonEvent(state, &event, &done);
   343             switch (event.type) {
   344             case SDL_WINDOWEVENT:
   345                 switch (event.window.event) {
   346                 case SDL_WINDOWEVENT_EXPOSED:
   347                     SDL_SelectRenderer(event.window.windowID);
   348                     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
   349                     SDL_RenderFill(NULL);
   350                     break;
   351                 }
   352                 break;
   353             default:
   354                 break;
   355             }
   356         }
   357         for (i = 0; i < state->num_windows; ++i) {
   358             MoveSprites(state->windows[i], sprites[i]);
   359         }
   360     }
   361 
   362     /* Print out some timing information */
   363     now = SDL_GetTicks();
   364     if (now > then) {
   365         double fps = ((double) frames * 1000) / (now - then);
   366         printf("%2.2f frames per second\n", fps);
   367     }
   368     quit(0);
   369 }
   370 
   371 /* vi: set ts=4 sw=4 expandtab: */