test/testsprite.c
author Holmes Futrell <hfutrell@umail.ucsb.edu>
Fri, 18 Jul 2008 19:23:13 +0000
branchgsoc2008_iphone
changeset 2377 e9a0bad0ea07
parent 1931 103c6fec2a60
child 2784 9bbe3bd94be8
permissions -rw-r--r--
Just renamed it...
     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 #include <math.h>
     7 
     8 #include "SDL.h"
     9 
    10 #define NUM_SPRITES	100
    11 #define MAX_SPEED 	1
    12 
    13 SDL_Surface *sprite;
    14 int numsprites;
    15 SDL_Rect *sprite_rects;
    16 SDL_Rect *positions;
    17 SDL_Rect *velocities;
    18 int sprites_visible;
    19 int debug_flip;
    20 Uint16 sprite_w, sprite_h;
    21 
    22 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    23 static void
    24 quit(int rc)
    25 {
    26     SDL_Quit();
    27     exit(rc);
    28 }
    29 
    30 int
    31 LoadSprite(char *file)
    32 {
    33     SDL_Surface *temp;
    34 
    35     /* Load the sprite image */
    36     sprite = SDL_LoadBMP(file);
    37     if (sprite == NULL) {
    38         fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
    39         return (-1);
    40     }
    41 
    42     /* Set transparent pixel as the pixel at (0,0) */
    43     if (sprite->format->palette) {
    44         SDL_SetColorKey(sprite, (SDL_SRCCOLORKEY | SDL_RLEACCEL),
    45                         *(Uint8 *) sprite->pixels);
    46     }
    47 
    48     /* Convert sprite to video format */
    49     temp = SDL_DisplayFormat(sprite);
    50     SDL_FreeSurface(sprite);
    51     if (temp == NULL) {
    52         fprintf(stderr, "Couldn't convert background: %s\n", SDL_GetError());
    53         return (-1);
    54     }
    55     sprite = temp;
    56 
    57     /* We're ready to roll. :) */
    58     return (0);
    59 }
    60 
    61 void
    62 MoveSprites(SDL_Surface * screen, Uint32 background)
    63 {
    64     int i, nupdates;
    65     SDL_Rect area, *position, *velocity;
    66 
    67     nupdates = 0;
    68     /* Erase all the sprites if necessary */
    69     if (sprites_visible) {
    70         SDL_FillRect(screen, NULL, background);
    71     }
    72 
    73     /* Move the sprite, bounce at the wall, and draw */
    74     for (i = 0; i < numsprites; ++i) {
    75         position = &positions[i];
    76         velocity = &velocities[i];
    77         position->x += velocity->x;
    78         if ((position->x < 0) || (position->x >= (screen->w - sprite_w))) {
    79             velocity->x = -velocity->x;
    80             position->x += velocity->x;
    81         }
    82         position->y += velocity->y;
    83         if ((position->y < 0) || (position->y >= (screen->h - sprite_w))) {
    84             velocity->y = -velocity->y;
    85             position->y += velocity->y;
    86         }
    87 
    88         /* Blit the sprite onto the screen */
    89         area = *position;
    90         SDL_BlitSurface(sprite, NULL, screen, &area);
    91         sprite_rects[nupdates++] = area;
    92     }
    93 
    94     if (debug_flip) {
    95         if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
    96             static int t = 0;
    97 
    98             Uint32 color = SDL_MapRGB(screen->format, 255, 0, 0);
    99             SDL_Rect r;
   100             r.x =
   101                 (sin((float) t * 2 * 3.1459) + 1.0) / 2.0 * (screen->w - 20);
   102             r.y = 0;
   103             r.w = 20;
   104             r.h = screen->h;
   105 
   106             SDL_FillRect(screen, &r, color);
   107             t += 2;
   108         }
   109     }
   110 
   111     /* Update the screen! */
   112     if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
   113         SDL_Flip(screen);
   114     } else {
   115         SDL_UpdateRects(screen, nupdates, sprite_rects);
   116     }
   117     sprites_visible = 1;
   118 }
   119 
   120 /* This is a way of telling whether or not to use hardware surfaces */
   121 Uint32
   122 FastestFlags(Uint32 flags, int width, int height, int bpp)
   123 {
   124     const SDL_VideoInfo *info;
   125 
   126     /* Hardware acceleration is only used in fullscreen mode */
   127     flags |= SDL_FULLSCREEN;
   128 
   129     /* Check for various video capabilities */
   130     info = SDL_GetVideoInfo();
   131     if (info->blit_hw_CC && info->blit_fill) {
   132         /* We use accelerated colorkeying and color filling */
   133         flags |= SDL_HWSURFACE;
   134     }
   135     /* If we have enough video memory, and will use accelerated
   136        blits directly to it, then use page flipping.
   137      */
   138     if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
   139         /* Direct hardware blitting without double-buffering
   140            causes really bad flickering.
   141          */
   142         if (info->video_mem * 1024 > (height * width * bpp / 8)) {
   143             flags |= SDL_DOUBLEBUF;
   144         } else {
   145             flags &= ~SDL_HWSURFACE;
   146         }
   147     }
   148 
   149     /* Return the flags */
   150     return (flags);
   151 }
   152 
   153 int
   154 main(int argc, char *argv[])
   155 {
   156     SDL_Surface *screen;
   157     Uint8 *mem;
   158     int width, height;
   159     Uint8 video_bpp;
   160     Uint32 videoflags;
   161     Uint32 background;
   162     int i, done;
   163     SDL_Event event;
   164     Uint32 then, now, frames;
   165 
   166     /* Initialize SDL */
   167     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
   168         fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
   169         return (1);
   170     }
   171 
   172     numsprites = NUM_SPRITES;
   173     videoflags = SDL_SWSURFACE | SDL_ANYFORMAT;
   174     width = 640;
   175     height = 480;
   176     video_bpp = 8;
   177     debug_flip = 0;
   178     while (argc > 1) {
   179         --argc;
   180         if (strcmp(argv[argc - 1], "-width") == 0) {
   181             width = atoi(argv[argc]);
   182             --argc;
   183         } else if (strcmp(argv[argc - 1], "-height") == 0) {
   184             height = atoi(argv[argc]);
   185             --argc;
   186         } else if (strcmp(argv[argc - 1], "-bpp") == 0) {
   187             video_bpp = atoi(argv[argc]);
   188             videoflags &= ~SDL_ANYFORMAT;
   189             --argc;
   190         } else if (strcmp(argv[argc], "-fast") == 0) {
   191             videoflags = FastestFlags(videoflags, width, height, video_bpp);
   192         } else if (strcmp(argv[argc], "-hw") == 0) {
   193             videoflags ^= SDL_HWSURFACE;
   194         } else if (strcmp(argv[argc], "-flip") == 0) {
   195             videoflags ^= SDL_DOUBLEBUF;
   196         } else if (strcmp(argv[argc], "-debugflip") == 0) {
   197             debug_flip ^= 1;
   198         } else if (strcmp(argv[argc], "-fullscreen") == 0) {
   199             videoflags ^= SDL_FULLSCREEN;
   200         } else if (isdigit(argv[argc][0])) {
   201             numsprites = atoi(argv[argc]);
   202         } else {
   203             fprintf(stderr,
   204                     "Usage: %s [-bpp N] [-hw] [-flip] [-fast] [-fullscreen] [numsprites]\n",
   205                     argv[0]);
   206             quit(1);
   207         }
   208     }
   209 
   210     /* Set video mode */
   211     screen = SDL_SetVideoMode(width, height, video_bpp, videoflags);
   212     if (!screen) {
   213         fprintf(stderr, "Couldn't set %dx%d video mode: %s\n",
   214                 width, height, SDL_GetError());
   215         quit(2);
   216     }
   217 
   218     /* Load the sprite */
   219     if (LoadSprite("icon.bmp") < 0) {
   220         quit(1);
   221     }
   222 
   223     /* Allocate memory for the sprite info */
   224     mem = (Uint8 *) malloc(4 * sizeof(SDL_Rect) * numsprites);
   225     if (mem == NULL) {
   226         SDL_FreeSurface(sprite);
   227         fprintf(stderr, "Out of memory!\n");
   228         quit(2);
   229     }
   230     sprite_rects = (SDL_Rect *) mem;
   231     positions = sprite_rects;
   232     sprite_rects += numsprites;
   233     velocities = sprite_rects;
   234     sprite_rects += numsprites;
   235     sprite_w = sprite->w;
   236     sprite_h = sprite->h;
   237     srand(time(NULL));
   238     for (i = 0; i < numsprites; ++i) {
   239         positions[i].x = rand() % (screen->w - sprite_w);
   240         positions[i].y = rand() % (screen->h - sprite_h);
   241         positions[i].w = sprite->w;
   242         positions[i].h = sprite->h;
   243         velocities[i].x = 0;
   244         velocities[i].y = 0;
   245         while (!velocities[i].x && !velocities[i].y) {
   246             velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
   247             velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
   248         }
   249     }
   250     background = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
   251 
   252     /* Print out information about our surfaces */
   253     printf("Screen is at %d bits per pixel\n", screen->format->BitsPerPixel);
   254     if ((screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
   255         printf("Screen is in video memory\n");
   256     } else {
   257         printf("Screen is in system memory\n");
   258     }
   259     if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
   260         printf("Screen has double-buffering enabled\n");
   261     }
   262     if ((sprite->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
   263         printf("Sprite is in video memory\n");
   264     } else {
   265         printf("Sprite is in system memory\n");
   266     }
   267     /* Run a sample blit to trigger blit acceleration */
   268     {
   269         SDL_Rect dst;
   270         dst.x = 0;
   271         dst.y = 0;
   272         dst.w = sprite->w;
   273         dst.h = sprite->h;
   274         SDL_BlitSurface(sprite, NULL, screen, &dst);
   275         SDL_FillRect(screen, &dst, background);
   276     }
   277     if ((sprite->flags & SDL_HWACCEL) == SDL_HWACCEL) {
   278         printf("Sprite blit uses hardware acceleration\n");
   279     }
   280     if ((sprite->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
   281         printf("Sprite blit uses RLE acceleration\n");
   282     }
   283 
   284     /* Loop, blitting sprites and waiting for a keystroke */
   285     frames = 0;
   286     then = SDL_GetTicks();
   287     done = 0;
   288     sprites_visible = 0;
   289     while (!done) {
   290         /* Check for events */
   291         ++frames;
   292         while (SDL_PollEvent(&event)) {
   293             switch (event.type) {
   294             case SDL_MOUSEBUTTONDOWN:
   295                 SDL_WarpMouse(screen->w / 2, screen->h / 2);
   296                 break;
   297             case SDL_KEYDOWN:
   298                 /* Any keypress quits the app... */
   299             case SDL_QUIT:
   300                 done = 1;
   301                 break;
   302             default:
   303                 break;
   304             }
   305         }
   306         MoveSprites(screen, background);
   307     }
   308     SDL_FreeSurface(sprite);
   309     free(mem);
   310 
   311     /* Print out some timing information */
   312     now = SDL_GetTicks();
   313     if (now > then) {
   314         printf("%2.2f frames per second\n",
   315                ((double) frames * 1000) / (now - then));
   316     }
   317     SDL_Quit();
   318     return (0);
   319 }