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