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