test/testsprite2.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 28 Aug 2006 03:17:39 +0000
changeset 1985 8055185ae4ed
parent 1965 a788656ca29a
child 2222 926294b2bb4e
permissions -rw-r--r--
Added source color and alpha modulation support.
Added perl script to generate optimized render copy functions.
     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_TextureBlendMode blendMode = SDL_TEXTUREBLENDMODE_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     }
    62 
    63     /* Create textures from the image */
    64     for (i = 0; i < state->num_windows; ++i) {
    65         SDL_SelectRenderer(state->windows[i]);
    66         sprites[i] =
    67             SDL_CreateTextureFromSurface(0, SDL_TEXTUREACCESS_REMOTE, temp);
    68         if (!sprites[i]) {
    69             fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
    70             SDL_FreeSurface(temp);
    71             return (-1);
    72         }
    73         SDL_SetTextureBlendMode(sprites[i], blendMode);
    74         SDL_SetTextureScaleMode(sprites[i], scaleMode);
    75     }
    76     SDL_FreeSurface(temp);
    77 
    78     /* We're ready to roll. :) */
    79     return (0);
    80 }
    81 
    82 void
    83 MoveSprites(SDL_WindowID window, SDL_TextureID sprite)
    84 {
    85     int i, n;
    86     int window_w, window_h;
    87     SDL_Rect area, *position, *velocity;
    88 
    89     SDL_SelectRenderer(window);
    90 
    91     /* Query the sizes */
    92     SDL_GetWindowSize(window, &window_w, &window_h);
    93 
    94     /* Cycle the color and alpha, if desired */
    95     if (cycle_color) {
    96         current_color += cycle_direction;
    97         if (current_color < 0) {
    98             current_color = 0;
    99             cycle_direction = -cycle_direction;
   100         }
   101         if (current_color > 255) {
   102             current_color = 255;
   103             cycle_direction = -cycle_direction;
   104         }
   105         SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color,
   106                                (Uint8) current_color);
   107     }
   108     if (cycle_alpha) {
   109         current_alpha += cycle_direction;
   110         if (current_alpha < 0) {
   111             current_alpha = 0;
   112             cycle_direction = -cycle_direction;
   113         }
   114         if (current_alpha > 255) {
   115             current_alpha = 255;
   116             cycle_direction = -cycle_direction;
   117         }
   118         SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha);
   119     }
   120 
   121     /* Move the sprite, bounce at the wall, and draw */
   122     n = 0;
   123     SDL_RenderFill(0xA0, 0xA0, 0xA0, 0xFF, NULL);
   124     for (i = 0; i < num_sprites; ++i) {
   125         position = &positions[i];
   126         velocity = &velocities[i];
   127         position->x += velocity->x;
   128         if ((position->x < 0) || (position->x >= (window_w - sprite_w))) {
   129             velocity->x = -velocity->x;
   130             position->x += velocity->x;
   131         }
   132         position->y += velocity->y;
   133         if ((position->y < 0) || (position->y >= (window_h - sprite_w))) {
   134             velocity->y = -velocity->y;
   135             position->y += velocity->y;
   136         }
   137 
   138         /* Blit the sprite onto the screen */
   139         SDL_RenderCopy(sprite, NULL, position);
   140     }
   141 
   142     /* Update the screen! */
   143     SDL_RenderPresent();
   144 }
   145 
   146 int
   147 main(int argc, char *argv[])
   148 {
   149     int i, done;
   150     SDL_Event event;
   151     Uint32 then, now, frames;
   152 
   153     /* Initialize parameters */
   154     num_sprites = NUM_SPRITES;
   155 
   156     /* Initialize test framework */
   157     state = CommonCreateState(argv, SDL_INIT_VIDEO);
   158     if (!state) {
   159         return 1;
   160     }
   161     for (i = 1; i < argc;) {
   162         int consumed;
   163 
   164         consumed = CommonArg(state, i);
   165         if (consumed == 0) {
   166             consumed = -1;
   167             if (SDL_strcasecmp(argv[i], "--blend") == 0) {
   168                 if (argv[i + 1]) {
   169                     if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
   170                         blendMode = SDL_TEXTUREBLENDMODE_NONE;
   171                         consumed = 2;
   172                     } else if (SDL_strcasecmp(argv[i + 1], "mask") == 0) {
   173                         blendMode = SDL_TEXTUREBLENDMODE_MASK;
   174                         consumed = 2;
   175                     } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
   176                         blendMode = SDL_TEXTUREBLENDMODE_BLEND;
   177                         consumed = 2;
   178                     } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
   179                         blendMode = SDL_TEXTUREBLENDMODE_ADD;
   180                         consumed = 2;
   181                     } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
   182                         blendMode = SDL_TEXTUREBLENDMODE_MOD;
   183                         consumed = 2;
   184                     }
   185                 }
   186             } else if (SDL_strcasecmp(argv[i], "--scale") == 0) {
   187                 if (argv[i + 1]) {
   188                     if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
   189                         scaleMode = SDL_TEXTURESCALEMODE_NONE;
   190                         consumed = 2;
   191                     } else if (SDL_strcasecmp(argv[i + 1], "fast") == 0) {
   192                         scaleMode = SDL_TEXTURESCALEMODE_FAST;
   193                         consumed = 2;
   194                     } else if (SDL_strcasecmp(argv[i + 1], "slow") == 0) {
   195                         scaleMode = SDL_TEXTURESCALEMODE_SLOW;
   196                         consumed = 2;
   197                     } else if (SDL_strcasecmp(argv[i + 1], "best") == 0) {
   198                         scaleMode = SDL_TEXTURESCALEMODE_BEST;
   199                         consumed = 2;
   200                     }
   201                 }
   202             } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
   203                 cycle_color = SDL_TRUE;
   204                 consumed = 1;
   205             } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
   206                 cycle_alpha = SDL_TRUE;
   207                 consumed = 1;
   208             } else if (SDL_isdigit(*argv[i])) {
   209                 num_sprites = SDL_atoi(argv[i]);
   210                 consumed = 1;
   211             }
   212         }
   213         if (consumed < 0) {
   214             fprintf(stderr,
   215                     "Usage: %s %s [--blend none|mask|blend|add|mod] [--scale none|fast|slow|best] [--cyclecolor] [--cyclealpha]\n",
   216                     argv[0], CommonUsage(state));
   217             quit(1);
   218         }
   219         i += consumed;
   220     }
   221     if (!CommonInit(state)) {
   222         quit(2);
   223     }
   224 
   225     /* Create the windows, initialize the renderers, and load the textures */
   226     sprites =
   227         (SDL_TextureID *) SDL_malloc(state->num_windows * sizeof(*sprites));
   228     if (!sprites) {
   229         fprintf(stderr, "Out of memory!\n");
   230         quit(2);
   231     }
   232     for (i = 0; i < state->num_windows; ++i) {
   233         SDL_SelectRenderer(state->windows[i]);
   234         SDL_RenderFill(0xA0, 0xA0, 0xA0, 0xFF, NULL);
   235     }
   236     if (LoadSprite("icon.bmp") < 0) {
   237         quit(2);
   238     }
   239 
   240     /* Allocate memory for the sprite info */
   241     positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
   242     velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
   243     if (!positions || !velocities) {
   244         fprintf(stderr, "Out of memory!\n");
   245         quit(2);
   246     }
   247     srand(time(NULL));
   248     if (scaleMode != SDL_TEXTURESCALEMODE_NONE) {
   249         sprite_w += sprite_w / 2;
   250         sprite_h += sprite_h / 2;
   251     }
   252     for (i = 0; i < num_sprites; ++i) {
   253         positions[i].x = rand() % (state->window_w - sprite_w);
   254         positions[i].y = rand() % (state->window_h - sprite_h);
   255         positions[i].w = sprite_w;
   256         positions[i].h = sprite_h;
   257         velocities[i].x = 0;
   258         velocities[i].y = 0;
   259         while (!velocities[i].x && !velocities[i].y) {
   260             velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
   261             velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
   262         }
   263     }
   264 
   265     /* Main render loop */
   266     frames = 0;
   267     then = SDL_GetTicks();
   268     done = 0;
   269     while (!done) {
   270         /* Check for events */
   271         ++frames;
   272         while (SDL_PollEvent(&event)) {
   273             CommonEvent(state, &event, &done);
   274             switch (event.type) {
   275             case SDL_WINDOWEVENT:
   276                 switch (event.window.event) {
   277                 case SDL_WINDOWEVENT_EXPOSED:
   278                     SDL_SelectRenderer(event.window.windowID);
   279                     SDL_RenderFill(0xA0, 0xA0, 0xA0, 0xFF, NULL);
   280                     break;
   281                 }
   282                 break;
   283             default:
   284                 break;
   285             }
   286         }
   287         for (i = 0; i < state->num_windows; ++i) {
   288             MoveSprites(state->windows[i], sprites[i]);
   289         }
   290     }
   291 
   292     /* Print out some timing information */
   293     now = SDL_GetTicks();
   294     if (now > then) {
   295         printf("%2.2f frames per second\n",
   296                ((double) frames * 1000) / (now - then));
   297     }
   298     quit(0);
   299 }
   300 
   301 /* vi: set ts=4 sw=4 expandtab: */