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