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