diff options
Diffstat (limited to 'distrib/sdl-1.2.15/test/testalpha.c')
-rw-r--r-- | distrib/sdl-1.2.15/test/testalpha.c | 547 |
1 files changed, 547 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/test/testalpha.c b/distrib/sdl-1.2.15/test/testalpha.c new file mode 100644 index 0000000..7e04fbe --- /dev/null +++ b/distrib/sdl-1.2.15/test/testalpha.c @@ -0,0 +1,547 @@ + +/* Simple program: Fill a colormap with gray and stripe it down the screen, + Then move an alpha valued sprite around the screen. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "SDL.h" + +#define FRAME_TICKS (1000/30) /* 30 frames/second */ + +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ +static void quit(int rc) +{ + SDL_Quit(); + exit(rc); +} + +/* Fill the screen with a gradient */ +static void FillBackground(SDL_Surface *screen) +{ + Uint8 *buffer; + Uint16 *buffer16; + Uint16 color; + Uint8 gradient; + int i, k; + + /* Set the surface pixels and refresh! */ + if ( SDL_LockSurface(screen) < 0 ) { + fprintf(stderr, "Couldn't lock the display surface: %s\n", + SDL_GetError()); + quit(2); + } + buffer=(Uint8 *)screen->pixels; + if (screen->format->BytesPerPixel!=2) { + for ( i=0; i<screen->h; ++i ) { + memset(buffer,(i*255)/screen->h, screen->w*screen->format->BytesPerPixel); + buffer += screen->pitch; + } + } + else + { + for ( i=0; i<screen->h; ++i ) { + gradient=((i*255)/screen->h); + color = (Uint16)SDL_MapRGB(screen->format, gradient, gradient, gradient); + buffer16=(Uint16*)buffer; + for (k=0; k<screen->w; k++) + { + *(buffer16+k)=color; + } + buffer += screen->pitch; + } + } + + SDL_UnlockSurface(screen); + SDL_UpdateRect(screen, 0, 0, 0, 0); +} + +/* Create a "light" -- a yellowish surface with variable alpha */ +SDL_Surface *CreateLight(int radius) +{ + Uint8 trans, alphamask; + int range, addition; + int xdist, ydist; + Uint16 x, y; + Uint16 skip; + Uint32 pixel; + SDL_Surface *light; + +#ifdef LIGHT_16BIT + Uint16 *buf; + + /* Create a 16 (4/4/4/4) bpp square with a full 4-bit alpha channel */ + /* Note: this isn't any faster than a 32 bit alpha surface */ + alphamask = 0x0000000F; + light = SDL_CreateRGBSurface(SDL_SWSURFACE, 2*radius, 2*radius, 16, + 0x0000F000, 0x00000F00, 0x000000F0, alphamask); +#else + Uint32 *buf; + + /* Create a 32 (8/8/8/8) bpp square with a full 8-bit alpha channel */ + alphamask = 0x000000FF; + light = SDL_CreateRGBSurface(SDL_SWSURFACE, 2*radius, 2*radius, 32, + 0xFF000000, 0x00FF0000, 0x0000FF00, alphamask); + if ( light == NULL ) { + fprintf(stderr, "Couldn't create light: %s\n", SDL_GetError()); + return(NULL); + } +#endif + + /* Fill with a light yellow-orange color */ + skip = light->pitch-(light->w*light->format->BytesPerPixel); +#ifdef LIGHT_16BIT + buf = (Uint16 *)light->pixels; +#else + buf = (Uint32 *)light->pixels; +#endif + /* Get a tranparent pixel value - we'll add alpha later */ + pixel = SDL_MapRGBA(light->format, 0xFF, 0xDD, 0x88, 0); + for ( y=0; y<light->h; ++y ) { + for ( x=0; x<light->w; ++x ) { + *buf++ = pixel; + } + buf += skip; /* Almost always 0, but just in case... */ + } + + /* Calculate alpha values for the surface. */ +#ifdef LIGHT_16BIT + buf = (Uint16 *)light->pixels; +#else + buf = (Uint32 *)light->pixels; +#endif + for ( y=0; y<light->h; ++y ) { + for ( x=0; x<light->w; ++x ) { + /* Slow distance formula (from center of light) */ + xdist = x-(light->w/2); + ydist = y-(light->h/2); + range = (int)sqrt(xdist*xdist+ydist*ydist); + + /* Scale distance to range of transparency (0-255) */ + if ( range > radius ) { + trans = alphamask; + } else { + /* Increasing transparency with distance */ + trans = (Uint8)((range*alphamask)/radius); + + /* Lights are very transparent */ + addition = (alphamask+1)/8; + if ( (int)trans+addition > alphamask ) { + trans = alphamask; + } else { + trans += addition; + } + } + /* We set the alpha component as the right N bits */ + *buf++ |= (255-trans); + } + buf += skip; /* Almost always 0, but just in case... */ + } + /* Enable RLE acceleration of this alpha surface */ + SDL_SetAlpha(light, SDL_SRCALPHA|SDL_RLEACCEL, 0); + + /* We're done! */ + return(light); +} + +static Uint32 flashes = 0; +static Uint32 flashtime = 0; + +void FlashLight(SDL_Surface *screen, SDL_Surface *light, int x, int y) +{ + SDL_Rect position; + Uint32 ticks1; + Uint32 ticks2; + + /* Easy, center light */ + position.x = x-(light->w/2); + position.y = y-(light->h/2); + position.w = light->w; + position.h = light->h; + ticks1 = SDL_GetTicks(); + SDL_BlitSurface(light, NULL, screen, &position); + ticks2 = SDL_GetTicks(); + SDL_UpdateRects(screen, 1, &position); + ++flashes; + + /* Update time spend doing alpha blitting */ + flashtime += (ticks2-ticks1); +} + +static int sprite_visible = 0; +static SDL_Surface *sprite; +static SDL_Surface *backing; +static SDL_Rect position; +static int x_vel, y_vel; +static int alpha_vel; + +int LoadSprite(SDL_Surface *screen, char *file) +{ + SDL_Surface *converted; + + /* Load the sprite image */ + sprite = SDL_LoadBMP(file); + if ( sprite == NULL ) { + fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError()); + return(-1); + } + + /* Set transparent pixel as the pixel at (0,0) */ + if ( sprite->format->palette ) { + SDL_SetColorKey(sprite, SDL_SRCCOLORKEY, + *(Uint8 *)sprite->pixels); + } + + /* Convert sprite to video format */ + converted = SDL_DisplayFormat(sprite); + SDL_FreeSurface(sprite); + if ( converted == NULL ) { + fprintf(stderr, "Couldn't convert background: %s\n", + SDL_GetError()); + return(-1); + } + sprite = converted; + + /* Create the background */ + backing = SDL_CreateRGBSurface(SDL_SWSURFACE, sprite->w, sprite->h, 8, + 0, 0, 0, 0); + if ( backing == NULL ) { + fprintf(stderr, "Couldn't create background: %s\n", + SDL_GetError()); + SDL_FreeSurface(sprite); + return(-1); + } + + /* Convert background to video format */ + converted = SDL_DisplayFormat(backing); + SDL_FreeSurface(backing); + if ( converted == NULL ) { + fprintf(stderr, "Couldn't convert background: %s\n", + SDL_GetError()); + SDL_FreeSurface(sprite); + return(-1); + } + backing = converted; + + /* Set the initial position of the sprite */ + position.x = (screen->w-sprite->w)/2; + position.y = (screen->h-sprite->h)/2; + position.w = sprite->w; + position.h = sprite->h; + x_vel = 0; y_vel = 0; + alpha_vel = 1; + + /* We're ready to roll. :) */ + return(0); +} + +void AttractSprite(Uint16 x, Uint16 y) +{ + x_vel = ((int)x-position.x)/10; + y_vel = ((int)y-position.y)/10; +} + +void MoveSprite(SDL_Surface *screen, SDL_Surface *light) +{ + SDL_Rect updates[2]; + int alpha; + + /* Erase the sprite if it was visible */ + if ( sprite_visible ) { + updates[0] = position; + SDL_BlitSurface(backing, NULL, screen, &updates[0]); + } else { + updates[0].x = 0; updates[0].y = 0; + updates[0].w = 0; updates[0].h = 0; + sprite_visible = 1; + } + + /* Since the sprite is off the screen, we can do other drawing + without being overwritten by the saved area behind the sprite. + */ + if ( light != NULL ) { + int x, y; + + SDL_GetMouseState(&x, &y); + FlashLight(screen, light, x, y); + } + + /* Move the sprite, bounce at the wall */ + position.x += x_vel; + if ( (position.x < 0) || (position.x >= screen->w) ) { + x_vel = -x_vel; + position.x += x_vel; + } + position.y += y_vel; + if ( (position.y < 0) || (position.y >= screen->h) ) { + y_vel = -y_vel; + position.y += y_vel; + } + + /* Update transparency (fade in and out) */ + alpha = sprite->format->alpha; + if ( (alpha+alpha_vel) < 0 ) { + alpha_vel = -alpha_vel; + } else + if ( (alpha+alpha_vel) > 255 ) { + alpha_vel = -alpha_vel; + } + SDL_SetAlpha(sprite, SDL_SRCALPHA, (Uint8)(alpha+alpha_vel)); + + /* Save the area behind the sprite */ + updates[1] = position; + SDL_BlitSurface(screen, &updates[1], backing, NULL); + + /* Blit the sprite onto the screen */ + updates[1] = position; + SDL_BlitSurface(sprite, NULL, screen, &updates[1]); + + /* Make it so! */ + SDL_UpdateRects(screen, 2, updates); +} + +void WarpSprite(SDL_Surface *screen, int x, int y) +{ + SDL_Rect updates[2]; + + /* Erase, move, Draw, update */ + updates[0] = position; + SDL_BlitSurface(backing, NULL, screen, &updates[0]); + position.x = x-sprite->w/2; /* Center about X */ + position.y = y-sprite->h/2; /* Center about Y */ + updates[1] = position; + SDL_BlitSurface(screen, &updates[1], backing, NULL); + updates[1] = position; + SDL_BlitSurface(sprite, NULL, screen, &updates[1]); + SDL_UpdateRects(screen, 2, updates); +} + +int main(int argc, char *argv[]) +{ + const SDL_VideoInfo *info; + SDL_Surface *screen; + int w, h; + Uint8 video_bpp; + Uint32 videoflags; + int i, done; + SDL_Event event; + SDL_Surface *light; + int mouse_pressed; + Uint32 ticks, lastticks; + + + /* Initialize SDL */ + if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { + fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); + return(1); + } + + /* Alpha blending doesn't work well at 8-bit color */ +#ifdef _WIN32_WCE + /* Pocket PC */ + w = 240; + h = 320; +#else + w = 640; + h = 480; +#endif + info = SDL_GetVideoInfo(); + if ( info->vfmt->BitsPerPixel > 8 ) { + video_bpp = info->vfmt->BitsPerPixel; + } else { + video_bpp = 16; + fprintf(stderr, "forced 16 bpp mode\n"); + } + videoflags = SDL_SWSURFACE; + for ( i = 1; argv[i]; ++i ) { + if ( strcmp(argv[i], "-bpp") == 0 ) { + video_bpp = atoi(argv[++i]); + if (video_bpp<=8) { + video_bpp=16; + fprintf(stderr, "forced 16 bpp mode\n"); + } + } else + if ( strcmp(argv[i], "-hw") == 0 ) { + videoflags |= SDL_HWSURFACE; + } else + if ( strcmp(argv[i], "-warp") == 0 ) { + videoflags |= SDL_HWPALETTE; + } else + if ( strcmp(argv[i], "-width") == 0 && argv[i+1] ) { + w = atoi(argv[++i]); + } else + if ( strcmp(argv[i], "-height") == 0 && argv[i+1] ) { + h = atoi(argv[++i]); + } else + if ( strcmp(argv[i], "-resize") == 0 ) { + videoflags |= SDL_RESIZABLE; + } else + if ( strcmp(argv[i], "-noframe") == 0 ) { + videoflags |= SDL_NOFRAME; + } else + if ( strcmp(argv[i], "-fullscreen") == 0 ) { + videoflags |= SDL_FULLSCREEN; + } else { + fprintf(stderr, + "Usage: %s [-width N] [-height N] [-bpp N] [-warp] [-hw] [-fullscreen]\n", + argv[0]); + quit(1); + } + } + + /* Set video mode */ + if ( (screen=SDL_SetVideoMode(w,h,video_bpp,videoflags)) == NULL ) { + fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n", + w, h, video_bpp, SDL_GetError()); + quit(2); + } + FillBackground(screen); + + /* Create the light */ + light = CreateLight(82); + if ( light == NULL ) { + quit(1); + } + + /* Load the sprite */ + if ( LoadSprite(screen, "icon.bmp") < 0 ) { + SDL_FreeSurface(light); + quit(1); + } + + /* Print out information about our surfaces */ + printf("Screen is at %d bits per pixel\n",screen->format->BitsPerPixel); + if ( (screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + printf("Screen is in video memory\n"); + } else { + printf("Screen is in system memory\n"); + } + if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + printf("Screen has double-buffering enabled\n"); + } + if ( (sprite->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + printf("Sprite is in video memory\n"); + } else { + printf("Sprite is in system memory\n"); + } + + /* Run a sample blit to trigger blit acceleration */ + MoveSprite(screen, NULL); + if ( (sprite->flags & SDL_HWACCEL) == SDL_HWACCEL ) { + printf("Sprite blit uses hardware alpha acceleration\n"); + } else { + printf("Sprite blit dosn't uses hardware alpha acceleration\n"); + } + + /* Set a clipping rectangle to clip the outside edge of the screen */ + { SDL_Rect clip; + clip.x = 32; + clip.y = 32; + clip.w = screen->w-(2*32); + clip.h = screen->h-(2*32); + SDL_SetClipRect(screen, &clip); + } + + /* Wait for a keystroke */ + lastticks = SDL_GetTicks(); + done = 0; + mouse_pressed = 0; + while ( !done ) { + /* Update the frame -- move the sprite */ + if ( mouse_pressed ) { + MoveSprite(screen, light); + mouse_pressed = 0; + } else { + MoveSprite(screen, NULL); + } + + /* Slow down the loop to 30 frames/second */ + ticks = SDL_GetTicks(); + if ( (ticks-lastticks) < FRAME_TICKS ) { +#ifdef CHECK_SLEEP_GRANULARITY +fprintf(stderr, "Sleeping %d ticks\n", FRAME_TICKS-(ticks-lastticks)); +#endif + SDL_Delay(FRAME_TICKS-(ticks-lastticks)); +#ifdef CHECK_SLEEP_GRANULARITY +fprintf(stderr, "Slept %d ticks\n", (SDL_GetTicks()-ticks)); +#endif + } + lastticks = ticks; + + /* Check for events */ + while ( SDL_PollEvent(&event) ) { + switch (event.type) { + case SDL_VIDEORESIZE: + screen = SDL_SetVideoMode(event.resize.w, event.resize.h, video_bpp, videoflags); + if ( screen ) { + FillBackground(screen); + } + break; + /* Attract sprite while mouse is held down */ + case SDL_MOUSEMOTION: + if (event.motion.state != 0) { + AttractSprite(event.motion.x, + event.motion.y); + mouse_pressed = 1; + } + break; + case SDL_MOUSEBUTTONDOWN: + if ( event.button.button == 1 ) { + AttractSprite(event.button.x, + event.button.y); + mouse_pressed = 1; + } else { + SDL_Rect area; + + area.x = event.button.x-16; + area.y = event.button.y-16; + area.w = 32; + area.h = 32; + SDL_FillRect(screen, &area, 0); + SDL_UpdateRects(screen,1,&area); + } + break; + case SDL_KEYDOWN: +#ifdef _WIN32_WCE + // there is no ESC key at all + done = 1; +#else + if ( event.key.keysym.sym == SDLK_ESCAPE ) { + done = 1; + } else if (event.key.keysym.sym == SDLK_t) { + videoflags ^= SDL_FULLSCREEN; + screen = SDL_SetVideoMode(w, h, video_bpp, videoflags); + if ( screen == NULL ) { + fprintf(stderr, "Couldn't toggle video mode: %s\n", + SDL_GetError()); + quit(2); + } + FillBackground(screen); + } +#endif + + break; + case SDL_QUIT: + done = 1; + break; + default: + break; + } + } + } + SDL_FreeSurface(light); + SDL_FreeSurface(sprite); + SDL_FreeSurface(backing); + + /* Print out some timing information */ + if ( flashes > 0 ) { + printf("%d alpha blits, ~%4.4f ms per blit\n", + flashes, (float)flashtime/flashes); + } + + SDL_Quit(); + return(0); +} |