testalpha.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:11k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

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