加急见刊

多重透明无闪烁微机动画设计

徐超  2008-08-05

摘 要 该文阐述了一种利用EGA/VGA上的位页面结构及彩色调色板来开发一个可以处理数个快速图像重叠及优美画面质量的动画结构。利用这种技术不仅会产生多重透明图像效应,而且可用最快的速度画图。 动画设计一直是微型计算机编程人员的热门话题,有不少编程人员利用C语言系列中的gentimage()和putimage()函数,在屏幕上不断画、擦,产生动画效果。这样产生的动画有较强的闪烁感,而且动画只能在一致的背景颜色下产生。有些同志采用直接视屏缓冲区读、写,这对16色的640×480色图像,要同时处理分散在4个彩色页面中的图像,既复杂又费时,而且当图像相交时很难避免相互影响的问题,因为这些部分在缓冲区中占用了相同的位。 由于EGA/VGA的4个页面可单独被读出及写入,如果将图像存于单一页面,这样就可以免去EGA/VGA中处理分散于各页面中图像的烦人问题。可以很容易处理4组图像,而且在不同页面中的图像不会互相干扰,但这样也产生了另一个问题:由于不同页面中位的混合产生了新的色彩,相交部分看起来并不属于任何图像。我们所希望的是一个图在另一个图的前面,并且由前图可以看到后图的透明色。 通过修改彩色调色板的值,完全可以达到上述效果。 实际上,来自各页面4位混合的点的颜色是由这4位所指的调色板值决定的。假设该点是从4色中选一色,而不是从16色中选一色,如果由彩色页面0来的位为1,则选择色彩0。 如果由彩色页面1来的位为1,则选择色彩1。如果由彩色页面2来的位为1,则选择色彩2。如果由彩色页面3来的位为1,则选择色彩3。当不止一个位为1时,只来自最小号码页面的位决定颜色,其它页面的位则忽略不用。若每个位均为0,则选择背景颜色。我们所做的就是重新控制调色板寄存器使得来自最高次序页面且值为1的位有色彩决定权。附表列出了上述调色板值的设置。 这样我们将可以得到4个颜色及一个背景色,而且也会定出一个简单的图像次序,页面0中的图像在其它页面之前,页面1中的图像在页面2、3图像之前,依此类推,而且还有一种透明性,可以由前面图像的缺口或边缘看到背后图像。最重要的是这符合不同图像存于不同页面的标准,可以快速处理图像,从而消除动画闪烁的感觉。 下面的程序说明位页面的动画,它是利用WPS中SPT产生几幅.SPT图像,分别装入不同位面,修改调色板值产生的重叠透明的动画效果。读者可以看到在前景(中文字幕)不动的情形下,背景(一幅较大的太空夜图)缓缓移动,给人一种全新的动画感觉。 @@T5S12900.GIF;附表调色板值设置@@ 其实,只要对上面的想法稍作改进,便能产生更好效果的动画。我们可以只用一、二个页面来作动画,空出其它的页面处理色彩问题。例如:利用彩色页面3作动画,而用彩色页面0、1、2来提供8种色彩的图像。读者不妨亲自设计一下调色板的值。 #include #include #include #include #include #include #include typedef enum { RIGHT , LEFT , UP , DOWN } dir-move; int mov-spt ( unsigned char *filename , dir-move dir , int startx , int starty , int page , int forg ); void main() { FILE *fp ; struct palettetype pal,pall ; unsigned char name[30] ; int i,gdriver=DETECT, gmode, errorcode ; initgraph(&gdriver, &gmode, " "); errorcode=graphresult(); if (errorcode !=gr0k) /* an error occurred */ { printf(" Graphics error: %s\n",grapherrormsg(errorcode)); printf(" press any key to halt :"); getch(); exit(1); /* return with error code */ } getpalette(&pal); pall.size=16; for (i=0;i<16;i++) pall.colors[i]=LIGHTBLUE; setallpalette(&pall); move-spt("f2.spt",UP,0,0,1,RED); move-spt("f3.spt",DOWN,0,0,2,YELLOW); move-spt("f4.spt",LEFT,0,0,3,BLUE); move-spt("f5.spt",RIGHT,0,0,4,7); getch(); setallpalette(&pal); outpw(0x3c4,0x0f02); closegraph(); } int move-spt ( unsigned char *filename , dir-move dir , int startx , int starty , int page , int forg ) {

else pall.colors[i]=pal.colors[i]; } setallpalette(&pall); if((mirror=(unsigned char far *)farmalloc(sizeof(unsigned char) *384001))==NULL) { printf("Memory allocation error!\n"); exit(1); } memset(mirror,0,384001); fseek (fp,341,SEEK-SET); fread (&wid,sizeof(int),1,fp); fread (&hei,sizeof(int),1,fp); if(wid>640||(hei>480)) { printf("Sorry. Image too large.\n"); exit(1); } fseek(fp,641,SEEK-SET); if((startx+wid)>640)startx=640-wid; if((starty+hei)>480)starty=480-hei; for (i=0;i=0;col-=3) { for(i=0;i<480;i++) { offset1=(col+7)/8 +i*80; offset=i*80; video=(unsigned char far *)MK-FP(0xa000,offset1); movmem((void *)(mirror+offset),(void *)video,(640-col)/8); } } break; case UP; for (row=479;row>=0;row-=1) { for(i=0;i<480-row;i++) { offset1=row*80; offset=(479-row)*80; video=(unsigned char far *)MK-FP(0xa000,offset1); movmem((mirror+offset),video,80); } } break; case DOWN: for (row=0;row<480;row+=1) { for(i=0;i

下载