test/testalpha.c
author Patrice Mandin <patmandin@gmail.com>
Thu, 19 Jan 2006 21:28:52 +0000
changeset 1257 448a9a64537b
parent 1152 51a8702d8ecd
child 1293 23b1ef7d003b
permissions -rw-r--r--
[PATCH] SDL_GetVideoMode() does not find best mode, part 2

Following commit 1.51, I come accross a problem when SDL must choose between
several video modes that could suit the one asked.

If I ask 320x240 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200

The smallest selectables modes are 384x240 and 320x400. And SDL choose the later
in this list, but 384x240 is more suitable. So I added a check to compare
the pixel count (surface) of modes, and select the one which has the smallest
pixel count.

In my example, 384x240 has 92160 pixels, and 320x400 has 128000 pixels. So now
SDL will choose 384x240 for the asked 320x240 mode.
slouken@0
     1
slouken@0
     2
/* Simple program:  Fill a colormap with gray and stripe it down the screen,
slouken@0
     3
		    Then move an alpha valued sprite around the screen.
slouken@0
     4
 */
slouken@0
     5
slouken@0
     6
#include <stdio.h>
slouken@0
     7
#include <stdlib.h>
slouken@0
     8
#include <string.h>
slouken@0
     9
#include <math.h>
slouken@0
    10
slouken@0
    11
#include "SDL.h"
slouken@0
    12
slouken@0
    13
#define FRAME_TICKS	(1000/30)		/* 30 frames/second */
slouken@0
    14
icculus@1151
    15
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
icculus@1151
    16
static void quit(int rc)
icculus@1151
    17
{
icculus@1151
    18
	SDL_Quit();
icculus@1151
    19
	exit(rc);
icculus@1151
    20
}
icculus@1151
    21
icculus@1151
    22
slouken@0
    23
/* Create a "light" -- a yellowish surface with variable alpha */
slouken@0
    24
SDL_Surface *CreateLight(SDL_Surface *screen, int radius)
slouken@0
    25
{
slouken@0
    26
	Uint8  trans, alphamask;
slouken@0
    27
	int    range, addition;
slouken@0
    28
	int    xdist, ydist;
slouken@0
    29
	Uint16 x, y;
slouken@0
    30
	Uint16 skip;
slouken@0
    31
	Uint32 pixel;
slouken@0
    32
	SDL_Surface *light;
slouken@0
    33
slouken@0
    34
#ifdef LIGHT_16BIT
slouken@0
    35
	Uint16 *buf;
slouken@0
    36
slouken@0
    37
	/* Create a 16 (4/4/4/4) bpp square with a full 4-bit alpha channel */
slouken@0
    38
	/* Note: this isn't any faster than a 32 bit alpha surface */
slouken@0
    39
	alphamask = 0x0000000F;
slouken@0
    40
	light = SDL_CreateRGBSurface(SDL_SWSURFACE, 2*radius, 2*radius, 16,
slouken@0
    41
			0x0000F000, 0x00000F00, 0x000000F0, alphamask);
slouken@0
    42
#else
slouken@0
    43
	Uint32 *buf;
slouken@0
    44
slouken@0
    45
	/* Create a 32 (8/8/8/8) bpp square with a full 8-bit alpha channel */
slouken@0
    46
	alphamask = 0x000000FF;
slouken@0
    47
	light = SDL_CreateRGBSurface(SDL_SWSURFACE, 2*radius, 2*radius, 32,
slouken@0
    48
			0xFF000000, 0x00FF0000, 0x0000FF00, alphamask);
slouken@0
    49
	if ( light == NULL ) {
slouken@0
    50
		fprintf(stderr, "Couldn't create light: %s\n", SDL_GetError());
slouken@0
    51
		return(NULL);
slouken@0
    52
	}
slouken@0
    53
#endif
slouken@0
    54
slouken@0
    55
	/* Fill with a light yellow-orange color */
slouken@0
    56
	skip = light->pitch-(light->w*light->format->BytesPerPixel);
slouken@0
    57
#ifdef LIGHT_16BIT
slouken@0
    58
	buf = (Uint16 *)light->pixels;
slouken@0
    59
#else
slouken@0
    60
	buf = (Uint32 *)light->pixels;
slouken@0
    61
#endif
slouken@0
    62
        /* Get a tranparent pixel value - we'll add alpha later */
slouken@0
    63
	pixel = SDL_MapRGBA(light->format, 0xFF, 0xDD, 0x88, 0);
slouken@0
    64
	for ( y=0; y<light->h; ++y ) {
slouken@0
    65
		for ( x=0; x<light->w; ++x ) {
slouken@0
    66
			*buf++ = pixel;
slouken@0
    67
		}
slouken@0
    68
		buf += skip;	/* Almost always 0, but just in case... */
slouken@0
    69
	}
slouken@0
    70
slouken@0
    71
	/* Calculate alpha values for the surface. */
slouken@0
    72
#ifdef LIGHT_16BIT
slouken@0
    73
	buf = (Uint16 *)light->pixels;
slouken@0
    74
#else
slouken@0
    75
	buf = (Uint32 *)light->pixels;
slouken@0
    76
#endif
slouken@0
    77
	for ( y=0; y<light->h; ++y ) {
slouken@0
    78
		for ( x=0; x<light->w; ++x ) {
slouken@0
    79
			/* Slow distance formula (from center of light) */
slouken@0
    80
			xdist = x-(light->w/2);
slouken@0
    81
			ydist = y-(light->h/2);
slouken@0
    82
			range = (int)sqrt(xdist*xdist+ydist*ydist);
slouken@0
    83
slouken@0
    84
			/* Scale distance to range of transparency (0-255) */
slouken@0
    85
			if ( range > radius ) {
slouken@0
    86
				trans = alphamask;
slouken@0
    87
			} else {
slouken@0
    88
				/* Increasing transparency with distance */
slouken@0
    89
				trans = (Uint8)((range*alphamask)/radius);
slouken@0
    90
slouken@0
    91
				/* Lights are very transparent */
slouken@0
    92
				addition = (alphamask+1)/8;
slouken@0
    93
				if ( (int)trans+addition > alphamask ) {
slouken@0
    94
					trans = alphamask;
slouken@0
    95
				} else {
slouken@0
    96
					trans += addition;
slouken@0
    97
				}
slouken@0
    98
			}
slouken@0
    99
			/* We set the alpha component as the right N bits */
slouken@0
   100
			*buf++ |= (255-trans);
slouken@0
   101
		}
slouken@0
   102
		buf += skip;	/* Almost always 0, but just in case... */
slouken@0
   103
	}
slouken@0
   104
	/* Enable RLE acceleration of this alpha surface */
slouken@0
   105
	SDL_SetAlpha(light, SDL_SRCALPHA|SDL_RLEACCEL, 0);
slouken@0
   106
slouken@0
   107
	/* We're done! */
slouken@0
   108
	return(light);
slouken@0
   109
}
slouken@0
   110
slouken@0
   111
static Uint32 flashes = 0;
slouken@0
   112
static Uint32 flashtime = 0;
slouken@0
   113
slouken@0
   114
void FlashLight(SDL_Surface *screen, SDL_Surface *light, int x, int y)
slouken@0
   115
{
slouken@0
   116
	SDL_Rect position;
slouken@0
   117
	Uint32   ticks1;
slouken@0
   118
	Uint32   ticks2;
slouken@0
   119
slouken@0
   120
	/* Easy, center light */
slouken@0
   121
	position.x = x-(light->w/2);
slouken@0
   122
	position.y = y-(light->h/2);
slouken@0
   123
	position.w = light->w;
slouken@0
   124
	position.h = light->h;
slouken@0
   125
	ticks1 = SDL_GetTicks();
slouken@0
   126
	SDL_BlitSurface(light, NULL, screen, &position);
slouken@0
   127
	ticks2 = SDL_GetTicks();
slouken@0
   128
	SDL_UpdateRects(screen, 1, &position);
slouken@0
   129
	++flashes;
slouken@0
   130
slouken@0
   131
	/* Update time spend doing alpha blitting */
slouken@0
   132
	flashtime += (ticks2-ticks1);
slouken@0
   133
}
slouken@0
   134
slouken@0
   135
static int sprite_visible = 0;
slouken@0
   136
static SDL_Surface *sprite;
slouken@0
   137
static SDL_Surface *backing;
slouken@0
   138
static SDL_Rect    position;
slouken@0
   139
static int         x_vel, y_vel;
slouken@0
   140
static int	   alpha_vel;
slouken@0
   141
slouken@0
   142
int LoadSprite(SDL_Surface *screen, char *file)
slouken@0
   143
{
slouken@0
   144
	SDL_Surface *converted;
slouken@0
   145
slouken@0
   146
	/* Load the sprite image */
slouken@0
   147
	sprite = SDL_LoadBMP(file);
slouken@0
   148
	if ( sprite == NULL ) {
slouken@0
   149
		fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
slouken@0
   150
		return(-1);
slouken@0
   151
	}
slouken@0
   152
slouken@0
   153
	/* Set transparent pixel as the pixel at (0,0) */
slouken@0
   154
	if ( sprite->format->palette ) {
slouken@0
   155
		SDL_SetColorKey(sprite, SDL_SRCCOLORKEY,
slouken@0
   156
						*(Uint8 *)sprite->pixels);
slouken@0
   157
	}
slouken@0
   158
slouken@0
   159
	/* Convert sprite to video format */
slouken@0
   160
	converted = SDL_DisplayFormat(sprite);
slouken@0
   161
	SDL_FreeSurface(sprite);
slouken@0
   162
	if ( converted == NULL ) {
slouken@0
   163
		fprintf(stderr, "Couldn't convert background: %s\n",
slouken@0
   164
							SDL_GetError());
slouken@0
   165
		return(-1);
slouken@0
   166
	}
slouken@0
   167
	sprite = converted;
slouken@0
   168
slouken@0
   169
	/* Create the background */
slouken@0
   170
	backing = SDL_CreateRGBSurface(SDL_SWSURFACE, sprite->w, sprite->h, 8,
slouken@0
   171
								0, 0, 0, 0);
slouken@0
   172
	if ( backing == NULL ) {
slouken@0
   173
		fprintf(stderr, "Couldn't create background: %s\n",
slouken@0
   174
							SDL_GetError());
slouken@0
   175
		SDL_FreeSurface(sprite);
slouken@0
   176
		return(-1);
slouken@0
   177
	}
slouken@0
   178
slouken@0
   179
	/* Convert background to video format */
slouken@0
   180
	converted = SDL_DisplayFormat(backing);
slouken@0
   181
	SDL_FreeSurface(backing);
slouken@0
   182
	if ( converted == NULL ) {
slouken@0
   183
		fprintf(stderr, "Couldn't convert background: %s\n",
slouken@0
   184
							SDL_GetError());
slouken@0
   185
		SDL_FreeSurface(sprite);
slouken@0
   186
		return(-1);
slouken@0
   187
	}
slouken@0
   188
	backing = converted;
slouken@0
   189
slouken@0
   190
	/* Set the initial position of the sprite */
slouken@0
   191
	position.x = (screen->w-sprite->w)/2;
slouken@0
   192
	position.y = (screen->h-sprite->h)/2;
slouken@0
   193
	position.w = sprite->w;
slouken@0
   194
	position.h = sprite->h;
slouken@0
   195
	x_vel = 0; y_vel = 0;
slouken@0
   196
	alpha_vel = 1;
slouken@0
   197
slouken@0
   198
	/* We're ready to roll. :) */
slouken@0
   199
	return(0);
slouken@0
   200
}
slouken@0
   201
slouken@0
   202
void AttractSprite(Uint16 x, Uint16 y)
slouken@0
   203
{
slouken@0
   204
	x_vel = ((int)x-position.x)/10;
slouken@0
   205
	y_vel = ((int)y-position.y)/10;
slouken@0
   206
}
slouken@0
   207
slouken@0
   208
void MoveSprite(SDL_Surface *screen, SDL_Surface *light)
slouken@0
   209
{
slouken@0
   210
	SDL_Rect updates[2];
slouken@0
   211
	int alpha;
slouken@0
   212
slouken@0
   213
	/* Erase the sprite if it was visible */
slouken@0
   214
	if ( sprite_visible ) {
slouken@0
   215
		updates[0] = position;
slouken@0
   216
		SDL_BlitSurface(backing, NULL, screen, &updates[0]);
slouken@0
   217
	} else {
slouken@0
   218
		updates[0].x = 0; updates[0].y = 0;
slouken@0
   219
		updates[0].w = 0; updates[0].h = 0;
slouken@0
   220
		sprite_visible = 1;
slouken@0
   221
	}
slouken@0
   222
slouken@0
   223
	/* Since the sprite is off the screen, we can do other drawing
slouken@0
   224
	   without being overwritten by the saved area behind the sprite.
slouken@0
   225
	 */
slouken@0
   226
	if ( light != NULL ) {
slouken@0
   227
		int x, y;
slouken@0
   228
slouken@0
   229
		SDL_GetMouseState(&x, &y);
slouken@0
   230
		FlashLight(screen, light, x, y);
slouken@0
   231
	}
slouken@0
   232
	   
slouken@0
   233
	/* Move the sprite, bounce at the wall */
slouken@0
   234
	position.x += x_vel;
slouken@0
   235
	if ( (position.x < 0) || (position.x >= screen->w) ) {
slouken@0
   236
		x_vel = -x_vel;
slouken@0
   237
		position.x += x_vel;
slouken@0
   238
	}
slouken@0
   239
	position.y += y_vel;
slouken@0
   240
	if ( (position.y < 0) || (position.y >= screen->h) ) {
slouken@0
   241
		y_vel = -y_vel;
slouken@0
   242
		position.y += y_vel;
slouken@0
   243
	}
slouken@0
   244
slouken@0
   245
	/* Update transparency (fade in and out) */
slouken@0
   246
	alpha = sprite->format->alpha;
slouken@0
   247
	if ( (alpha+alpha_vel) < 0 ) {
slouken@0
   248
		alpha_vel = -alpha_vel;
slouken@0
   249
	} else
slouken@0
   250
	if ( (alpha+alpha_vel) > 255 ) {
slouken@0
   251
		alpha_vel = -alpha_vel;
slouken@0
   252
	}
slouken@0
   253
	SDL_SetAlpha(sprite, SDL_SRCALPHA, (Uint8)(alpha+alpha_vel));
slouken@0
   254
slouken@0
   255
	/* Save the area behind the sprite */
slouken@0
   256
	updates[1] = position;
slouken@0
   257
	SDL_BlitSurface(screen, &updates[1], backing, NULL);
slouken@0
   258
	
slouken@0
   259
	/* Blit the sprite onto the screen */
slouken@0
   260
	updates[1] = position;
slouken@0
   261
	SDL_BlitSurface(sprite, NULL, screen, &updates[1]);
slouken@0
   262
slouken@0
   263
	/* Make it so! */
slouken@0
   264
	SDL_UpdateRects(screen, 2, updates);
slouken@0
   265
}
slouken@0
   266
slouken@0
   267
void WarpSprite(SDL_Surface *screen, int x, int y)
slouken@0
   268
{
slouken@0
   269
	SDL_Rect updates[2];
slouken@0
   270
slouken@0
   271
	/* Erase, move, Draw, update */
slouken@0
   272
	updates[0] = position;
slouken@0
   273
	SDL_BlitSurface(backing, NULL, screen, &updates[0]);
slouken@0
   274
	position.x = x-sprite->w/2;	/* Center about X */
slouken@0
   275
	position.y = y-sprite->h/2;	/* Center about Y */
slouken@0
   276
	updates[1] = position;
slouken@0
   277
	SDL_BlitSurface(screen, &updates[1], backing, NULL);
slouken@0
   278
	updates[1] = position;
slouken@0
   279
	SDL_BlitSurface(sprite, NULL, screen, &updates[1]);
slouken@0
   280
	SDL_UpdateRects(screen, 2, updates);
slouken@0
   281
}
slouken@0
   282
slouken@0
   283
int main(int argc, char *argv[])
slouken@0
   284
{
slouken@0
   285
	const SDL_VideoInfo *info;
slouken@0
   286
	SDL_Surface *screen;
slouken@0
   287
	Uint8  video_bpp;
slouken@0
   288
	Uint32 videoflags;
slouken@0
   289
	Uint8 *buffer;
slouken@691
   290
	int    i, k, done;
slouken@0
   291
	SDL_Event event;
slouken@0
   292
	SDL_Surface *light;
slouken@0
   293
	int mouse_pressed;
slouken@0
   294
	Uint32 ticks, lastticks;
slouken@691
   295
	Uint16 *buffer16;
slouken@691
   296
        Uint16 color;
slouken@691
   297
        Uint8  gradient;
slouken@691
   298
slouken@0
   299
slouken@0
   300
	/* Initialize SDL */
slouken@0
   301
	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
slouken@0
   302
		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
icculus@1151
   303
		return(1);
slouken@0
   304
	}
slouken@0
   305
slouken@0
   306
	/* Alpha blending doesn't work well at 8-bit color */
slouken@0
   307
	info = SDL_GetVideoInfo();
slouken@0
   308
	if ( info->vfmt->BitsPerPixel > 8 ) {
slouken@0
   309
		video_bpp = info->vfmt->BitsPerPixel;
slouken@0
   310
	} else {
slouken@0
   311
		video_bpp = 16;
slouken@691
   312
                fprintf(stderr, "forced 16 bpp mode\n");
slouken@0
   313
	}
slouken@0
   314
	videoflags = SDL_SWSURFACE;
slouken@0
   315
	while ( argc > 1 ) {
slouken@0
   316
		--argc;
slouken@0
   317
		if ( strcmp(argv[argc-1], "-bpp") == 0 ) {
slouken@0
   318
			video_bpp = atoi(argv[argc]);
slouken@691
   319
                        if (video_bpp<=8) {
slouken@691
   320
                            video_bpp=16;
slouken@691
   321
                            fprintf(stderr, "forced 16 bpp mode\n");
slouken@691
   322
                        }
slouken@0
   323
			--argc;
slouken@0
   324
		} else
slouken@0
   325
		if ( strcmp(argv[argc], "-hw") == 0 ) {
slouken@0
   326
			videoflags |= SDL_HWSURFACE;
slouken@0
   327
		} else
slouken@0
   328
		if ( strcmp(argv[argc], "-warp") == 0 ) {
slouken@0
   329
			videoflags |= SDL_HWPALETTE;
slouken@0
   330
		} else
slouken@0
   331
		if ( strcmp(argv[argc], "-fullscreen") == 0 ) {
slouken@0
   332
			videoflags |= SDL_FULLSCREEN;
slouken@0
   333
		} else {
slouken@0
   334
			fprintf(stderr, 
slouken@0
   335
			"Usage: %s [-bpp N] [-warp] [-hw] [-fullscreen]\n",
slouken@0
   336
								argv[0]);
icculus@1151
   337
			quit(1);
slouken@0
   338
		}
slouken@0
   339
	}
slouken@0
   340
slouken@0
   341
	/* Set 640x480 video mode */
icculus@1152
   342
#ifndef _WIN32_WCE
slouken@0
   343
	if ( (screen=SDL_SetVideoMode(640,480,video_bpp,videoflags)) == NULL ) {
slouken@0
   344
		fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
slouken@0
   345
						video_bpp, SDL_GetError());
icculus@1151
   346
		quit(2);
slouken@0
   347
	}
icculus@1152
   348
#else
icculus@1152
   349
	/* Pocket PC */
icculus@1152
   350
	if ( (screen=SDL_SetVideoMode(240,320,video_bpp,SDL_FULLSCREEN)) == NULL ) {
icculus@1152
   351
		fprintf(stderr, "Couldn't set 240x320x%d video mode: %s\n",
icculus@1152
   352
						video_bpp, SDL_GetError());
icculus@1152
   353
		quit(2);
icculus@1152
   354
	}
icculus@1152
   355
#endif
slouken@0
   356
	/* Set the surface pixels and refresh! */
slouken@0
   357
	if ( SDL_LockSurface(screen) < 0 ) {
slouken@0
   358
		fprintf(stderr, "Couldn't lock the display surface: %s\n",
slouken@0
   359
							SDL_GetError());
icculus@1151
   360
		quit(2);
slouken@0
   361
	}
slouken@0
   362
	buffer=(Uint8 *)screen->pixels;
slouken@691
   363
	if (screen->format->BytesPerPixel!=2) {
slouken@691
   364
		for ( i=0; i<screen->h; ++i ) {
slouken@691
   365
			memset(buffer,(i*255)/screen->h, screen->pitch);
slouken@691
   366
			buffer += screen->pitch;
slouken@691
   367
		}
slouken@0
   368
	}
slouken@691
   369
        else
slouken@691
   370
        {
slouken@691
   371
		for ( i=0; i<screen->h; ++i ) {
slouken@691
   372
			gradient=((i*255)/screen->h);
slouken@691
   373
                        color = SDL_MapRGB(screen->format, gradient, gradient, gradient);
slouken@691
   374
                        buffer16=(Uint16*)buffer;
slouken@691
   375
                        for (k=0; k<screen->w; k++)
slouken@691
   376
                        {
slouken@691
   377
                            *(buffer16+k)=color;
slouken@691
   378
                        }
slouken@691
   379
			buffer += screen->pitch;
slouken@691
   380
		}
slouken@691
   381
        }
slouken@691
   382
slouken@0
   383
	SDL_UnlockSurface(screen);
slouken@0
   384
	SDL_UpdateRect(screen, 0, 0, 0, 0);
slouken@0
   385
slouken@0
   386
	/* Create the light */
slouken@0
   387
	light = CreateLight(screen, 82);
slouken@0
   388
	if ( light == NULL ) {
icculus@1151
   389
		quit(1);
slouken@0
   390
	}
slouken@0
   391
slouken@0
   392
	/* Load the sprite */
slouken@0
   393
	if ( LoadSprite(screen, "icon.bmp") < 0 ) {
slouken@0
   394
		SDL_FreeSurface(light);
icculus@1151
   395
		quit(1);
slouken@0
   396
	}
slouken@0
   397
slouken@886
   398
	/* Print out information about our surfaces */
slouken@886
   399
	printf("Screen is at %d bits per pixel\n",screen->format->BitsPerPixel);
slouken@886
   400
	if ( (screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
slouken@886
   401
		printf("Screen is in video memory\n");
slouken@886
   402
	} else {
slouken@886
   403
		printf("Screen is in system memory\n");
slouken@886
   404
	}
slouken@886
   405
	if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
slouken@886
   406
		printf("Screen has double-buffering enabled\n");
slouken@886
   407
	}
slouken@886
   408
	if ( (sprite->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
slouken@886
   409
		printf("Sprite is in video memory\n");
slouken@886
   410
	} else {
slouken@886
   411
		printf("Sprite is in system memory\n");
slouken@886
   412
	}
slouken@886
   413
slouken@886
   414
	/* Run a sample blit to trigger blit acceleration */
slouken@886
   415
	{ SDL_Rect dst;
slouken@886
   416
		dst.x = 0;
slouken@886
   417
		dst.y = 0;
slouken@886
   418
		dst.w = sprite->w;
slouken@886
   419
		dst.h = sprite->h;
slouken@886
   420
		SDL_BlitSurface(sprite, NULL, screen, &dst);
slouken@886
   421
		SDL_FillRect(screen, &dst, 0);
slouken@886
   422
	}
slouken@886
   423
	if ( (sprite->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
slouken@886
   424
		printf("Sprite blit uses hardware alpha acceleration\n");
slouken@886
   425
	} else {
slouken@886
   426
		printf("Sprite blit dosn't uses hardware alpha acceleration\n");
slouken@886
   427
	}
slouken@886
   428
slouken@0
   429
	/* Set a clipping rectangle to clip the outside edge of the screen */
slouken@0
   430
	{ SDL_Rect clip;
slouken@0
   431
		clip.x = 32;
slouken@0
   432
		clip.y = 32;
slouken@0
   433
		clip.w = screen->w-(2*32);
slouken@0
   434
		clip.h = screen->h-(2*32);
slouken@0
   435
		SDL_SetClipRect(screen, &clip);
slouken@0
   436
	}
slouken@0
   437
slouken@0
   438
	/* Wait for a keystroke */
slouken@0
   439
	lastticks = SDL_GetTicks();
slouken@0
   440
	done = 0;
slouken@0
   441
	mouse_pressed = 0;
slouken@0
   442
	while ( !done ) {
slouken@0
   443
		/* Update the frame -- move the sprite */
slouken@0
   444
		if ( mouse_pressed ) {
slouken@0
   445
			MoveSprite(screen, light);
slouken@0
   446
			mouse_pressed = 0;
slouken@0
   447
		} else {
slouken@0
   448
			MoveSprite(screen, NULL);
slouken@0
   449
		}
slouken@0
   450
slouken@0
   451
		/* Slow down the loop to 30 frames/second */
slouken@0
   452
		ticks = SDL_GetTicks();
slouken@0
   453
		if ( (ticks-lastticks) < FRAME_TICKS ) {
slouken@0
   454
#ifdef CHECK_SLEEP_GRANULARITY
slouken@0
   455
fprintf(stderr, "Sleeping %d ticks\n", FRAME_TICKS-(ticks-lastticks));
slouken@0
   456
#endif
slouken@0
   457
			SDL_Delay(FRAME_TICKS-(ticks-lastticks));
slouken@0
   458
#ifdef CHECK_SLEEP_GRANULARITY
slouken@0
   459
fprintf(stderr, "Slept %d ticks\n", (SDL_GetTicks()-ticks));
slouken@0
   460
#endif
slouken@0
   461
		}
slouken@0
   462
		lastticks = ticks;
slouken@0
   463
slouken@0
   464
		/* Check for events */
slouken@0
   465
		while ( SDL_PollEvent(&event) ) {
slouken@0
   466
			switch (event.type) {
slouken@0
   467
				/* Attract sprite while mouse is held down */
slouken@0
   468
				case SDL_MOUSEMOTION:
slouken@0
   469
					if (event.motion.state != 0) {
slouken@0
   470
						AttractSprite(event.motion.x,
slouken@0
   471
								event.motion.y);
slouken@0
   472
						mouse_pressed = 1;
slouken@0
   473
					}
slouken@0
   474
					break;
slouken@0
   475
				case SDL_MOUSEBUTTONDOWN:
slouken@0
   476
					if ( event.button.button == 1 ) {
slouken@0
   477
						AttractSprite(event.button.x,
slouken@0
   478
						              event.button.y);
slouken@0
   479
						mouse_pressed = 1;
slouken@0
   480
					} else {
slouken@0
   481
						SDL_Rect area;
slouken@0
   482
slouken@0
   483
						area.x = event.button.x-16;
slouken@0
   484
						area.y = event.button.y-16;
slouken@0
   485
						area.w = 32;
slouken@0
   486
						area.h = 32;
slouken@0
   487
						SDL_FillRect(screen, &area, 0);
slouken@0
   488
						SDL_UpdateRects(screen,1,&area);
slouken@0
   489
					}
slouken@0
   490
					break;
slouken@0
   491
				case SDL_KEYDOWN:
slouken@0
   492
					/* Any keypress quits the app... */
slouken@0
   493
				case SDL_QUIT:
slouken@0
   494
					done = 1;
slouken@0
   495
					break;
slouken@0
   496
				default:
slouken@0
   497
					break;
slouken@0
   498
			}
slouken@0
   499
		}
slouken@0
   500
	}
slouken@0
   501
	SDL_FreeSurface(light);
slouken@0
   502
	SDL_FreeSurface(sprite);
slouken@0
   503
	SDL_FreeSurface(backing);
slouken@0
   504
slouken@0
   505
	/* Print out some timing information */
slouken@0
   506
	if ( flashes > 0 ) {
slouken@0
   507
		printf("%d alpha blits, ~%4.4f ms per blit\n", 
slouken@0
   508
			flashes, (float)flashtime/flashes);
slouken@0
   509
	}
icculus@1151
   510
icculus@1151
   511
	SDL_Quit();
slouken@0
   512
	return(0);
slouken@0
   513
}