📄 函数实现动画的技巧.txt
字号:
9.1.8 用putimage 函数实现动画的技巧
9.2 菜单设计技术
9.2.1 下拉式菜单的设计
9.2.2 选择式菜单的设计
9.2.3 实现阴影窗口的技巧
9.3 音响技巧
9.3.1 音乐程序设计
9.3.2 自动识谱音乐程序
9.3.3 实现后台演奏音乐的技巧
9.1.7 用随机函数实现动画的技巧
在一些特殊的C语言动画技术中,可以利用随机函数int random(int num ) 取一个0~num范围内的随机数,经过某种运算后,再利用C 语言的作图语句产生各种大小不同的图形,也能产生很强的移动感。
程序dh1.c就是利用随机函数来产生动画应用。该程序运行后,屏幕中间绘出一台微型计算机,微机下方同时显示“computer”的放大字形,在画出微机的小屏幕内,产生各种大小不同、颜色各异的矩形,这些矩形互相覆盖,给人以极强的动画感。
程序中改变x1、x2、y1、y2的值,能将图形移动屏幕的任何位置,改变x、y的值,能将图形放大或缩小。
[例9-7] 动画显示程序DH1.C
#include<conio.h>
#inclu]de<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<time.h>
#define X1 260
#define X2 320
#define y1 140
#define y2 180
#define Xy 16
int gdrive,gmode,mcolor,ecode;
struct palettetype palette;
void initialize(void);
void rbars(void);
int main( )
{
initialize( ); /*初始化图形系统*/
/* 显示放大字体*/
setcolor(YELLOW);
settextstyle(TRIPLEX_FONT,HORIZ_DIR,4);
settextjustify(CENTER_TEXT,CENTER_TEXT);
outtextxy((getmaXX( )/2-17),360,"COMPUTER");
rbars( ); /* 主程序*/
closegraph( )/*关闭图形系统*/
return 1;
}
void initialize(void)
{
gdrive=DETECT;
initgraph (&gdrive,&gmode," ");
ecode=graphresult( );
if(ecode!=0)
{
printf("Graphice Error: %d\n",grapherrormsg(ecode));
eXit(1);
}
getpalette(&palette);
mcolor=getmaXcolor( )+1;
}
void rbars(void)
{
int color; /* 画计算机图形*/
setcolor(DARKGRAY);
bar3d(X1-20,y1-20,X2+56,y2+70,0,3);
setfillstyle(CLOSE_DOT_FILL,BLUE);
setfillstyle(SOLID_FILL,RED);
circle(X2+28,y2+60,4);
bar(X1+4,y1+78,X1+20,y1+83);
setcolor(MAGENTA);
circle(X2+28,y2+60,4);
circle(X2+16,y2+60,4);
circle(X2+4,y2+60,4);
setcolor(WHITE);
setfillstyle(SOLID_FILL,DARKGRAY);
bar3d(X1-60,y1+120,X1+154,y1+170,0,2);
bar3d(X1+120,y1+126,X1+100,y1+164,0,2);
line (X1+20,y1+145,X1+100,y1+145);
setfillstyle(SOLID_FILL,GREEN);
bar(X1+26,y1+130,X1+34,y1+132);
bar(X1+26,y1+150,X1+34,y1+152);
setfillstyle(WIDE_DOT_FILL,RED);
bar(X1-24,y1+128,X1-44,y1+142);
/*利用随机函数实现矩形画面互相覆盖,产生动感*/
while(!kbhit( ))
{
color=random(mcolor-1)+1;
setcolor(color);
setfillstyle(random(11)+1,color);
bar3d(X1+random(getmaXX( )/Xy),y1+random(getmaXy( )/Xy),X2+getmaXX( )/Xy,y2+getmaXy( )/Xy,0,5 );
}
}
9.1.8 用putimage 函数实现动画的技巧
计算机图形动画显示的是由一系列静止图像在不同位置上的重现。计算机图形动画技术一般分为画擦法和覆盖刷新法两大类。画擦法是先画T时刻的图形,然后在T +△T时刻把它擦掉,改画新时刻的图形是由点、线、圆等基本图元组成。这种一画一擦的方法对于实现简单图形的动态显示是比较有效的。而当需要显示比较复杂的图形时,由于画擦图形时间相对较长,致使画面在移动时出现局部闪烁现象,使得动画视觉效果变差。所以,为提高图形的动态显示效果,在显示比较复杂的图形时多采用覆盖刷新的方法。
在Turbo C 的图形函数中,有几个函数可完成动画的显示:
getimage(int left,int top,int right,int bottom,void far*buf) 函数把屏幕图形部分拷贝到由buf所指向的内存区域。
imagesize() 函数用来确定存储图形所需的字节数,所定义的字节数根据实际需要可以定义得多一些。
putimage( )函数可以把getimage( )存储的图形重写在屏幕上。利用putimage( )函数中的COPY_PUT项,在下一个要显示的位置上于屏幕中重写图像,如此重复、交替地显示下去,即可达到覆盖刷新的目的,从而实现动画显示。由于图形是一次性覆盖到显示区的,并在瞬间完成,其动态特性十分平滑,动画效果较好。
程序dh2.c就是根据上述思路而实现的。程序运行时,将在屏幕上出现一个跳动的红色小球。
[例9-8] 动画显示程序dh2.c
#include <stdio.h>
#include<graphics.h>
#include<alloc.h>
#include<conio.h>
void main(void)
{
int driver=DETECT,mode;
int k=0,i,m,m1;
int maXX,mayy,size;
char *buf;
initgraph(&driver,&mode," ");
maXX=getmaXX( );
mayy=getmaXy( );
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(1,1,maXX,mayy);
setcolor(RED);
for(i=0;i<=10;i++)
circle(150,150,i);
size=imagesize(100,100,250,200);
if(size != -1)
buf=malloc(size);
if(buf)
{
getimage(100,100,250,200,buf);
m=120;m1=m;
do{
k=k+1;
if((m1+100)>mayy)
{
for(m=m+30;m<maXX;m=m+30)
{
m1=m1-20;
putimage(m,m1,buf,COPY_PUT);
}
}
if((m+100)>maXX)
{
m=m-100;
for(m1=m1+100;m1>=1;m1=m1-10)
{
m1=m1-19;
putimage(m,m1,buf,COPY_PUT);
}
for(m=m;m>1;m=m-30)
{
m1=m1-17;
putimage(m,m1,buf,COPY_PUT);
}
}
m1=m1+20;
m=m+20;
putimage(m,m1,buf,COPY_PUT);
}while(k!=1000);
getch( );
}
restorecrtmode( );
}
9.2 菜单设计技术
菜单在用户编写的程序中占据相当一部分内容。设计一个高质量的菜单,不仅能使系统美观,更主要的是能够使操作者使用方便,避免一些误操作带来的严重后果。
9.2.1 下拉式菜单的设计
下拉式菜单是一个窗口菜单,它具有一个主菜单,其中包括几个选择项,主菜单的每一项又可以分为下一级菜单,这样逐级下分,用一个个窗口的形式弹出在屏幕上,一旦操作完毕又可以从屏幕上消失,并恢复原来的屏幕状态。
设计下拉式菜单的关键就是在下级菜单窗口弹出之前,要将被该窗口占用的屏幕区域保存起来,然后产生这一级菜单窗口,并可用光标键选择菜单中各项,用回车键来确认。如果某选择项还有下级菜单,则按同样的方法再产生下一级菜单窗口。
用Turbo C 在文本方式时提供的函数gettext( ) 来放屏幕规定区域的内容,当需要时用puttext( )函数释放出来,再加上键盘管理函数bioskey( ),就可以完成下拉式菜单的设计。
程序menu1.c是一个简单拉式菜单。运行时在屏幕上一行显示主菜单的内容,当按ALT+F则进入File子菜单,然后可用光标键移动色棒选择操作,用回车确认。用Esc键退出主菜单,并可用ALT+X退出菜单系统。
[例9-9] 下拉式菜单menu1.c
/*下拉式菜单menu1.c*/
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<bios.h>
void main(void)
{
int i,key,key0,key1,y,test;
char *m[ ]={"File","Edit","Run","Compile","Projsct","Options","Debug","Break/watch "}; /*定义主菜单的内容*/
char *f[ ]={"Load F3", /* 定义FILE 子菜单的内容*/
"Pick ALT+F3",
"New",
"Save F2",
"Write to",
"Directory",
"Change dir",
"Os shell",
"Quit ALT+X"};
char buf[16*10*2],buf1[16*2]; /* 定义保存屏幕区域的数组变量*/
textbackground(BLUE); /* 设置文本屏幕背景色*/
clrscr( ); /* 屏幕背径着色*/
window(1,1,80,1); /* 定义一个文本窗口*/
textbackground(WHITE); /*设置窗口背景色*/
textcolor(BLACK);
clrscr( );
window(1,1,80,2);
for(i=0;i<8;i++)
cprintf("%s",m[i]); /*显示主菜单的内容*/
while(1)
{
key=0;
while(bioskey(1) == 0); /*等待键盘输入*/
key = bioskey(0); /*取键盘输入码*/
key = key&0Xff? 0:key>>8; /*只取扩充键码*/
if(key == 45) eXit(0); /*如果按ALT+X 键则退出*/
if(key == 33) /* 如果按ALT+F 则显示子菜单*/
{
textbackground(BLACK);
textcolor (WHITE);
gotoxy(4,1);
cprintf("%s",m[0]);
gettext(4,2,19,11,buf);/*保存窗口区域的在原有内容*/
window(4,2,19,11);
textbackground(WHITE);
textcolor(BLACK);
clrscr( );
window(4,2,19,12);
gotoxy(1,1); /*作一个单线形边框*/
putch(0xff);
for(i=2;i<10;i++)
{
gotoxy(1,i); putch(0×b3);
gotoxy(16,i); putch(0×b3);
}
gotoxy(1,10);
putch(0Xc0);
for(i=2;i<16;i++)
putch(0Xc4);
putch(0Xd9);
for(i=2;i<10;i++)
{
gotoxy(2,i);
cprintf("%s",f[i-1]);
}
gettext(2,2,18,3,buf1);
textbackground(BLACK);
textcolor(WHITE);
gotoxy(2,2);
cprintf("%s",f[0]);
y=2;
key1=0;
while((key0!=27)&&(key1!=45)&&(key0!=13))
{/*输入为ALT+X,回车或ESC 键退出循环*/
while(bioskey(1)==0); /*等待键盘输入*/
key0=key1=bioskey(0); / *取键盘输入码* /
key0=key0&0Xff; / *只取扩充码* /
key1=key1&0Xff? 0:key1>>8;
if(key1==72||key1==80) /*如果为上下箭头键*/
{
puttext(2,y,18,y+1,buf1); /*恢复原来的信息*/
if(key1==72) y=y==2? 9:y-1; /*上箭头处理*/
if(key1==80) y=y==9? 2:y+1; /*下箭头处理*/
getteXt(2,y,18,y+1,buf1); /*保存新色棒前产生这一位置屏幕内容*/
textbackground(BLACK); /*产生新色棒*/
textcolor(WHITE);
gotoxy(2,y);
cprintf("%s",f[y-1]);
}
}
if(key1 == 45) eXit(0); /*按ALT+X 退出*/
if(key0 == 13) /*回车按所选菜单项进行处理*/
{
switch(y)
{
case 1:
break;
case 2:
break;
case 9:
eXit(0);
default:
break;
}
}
else /*按E S C 键返回主菜单*/
{
window(1,1,80,2);
puttext(4,2,19,11,buf); /*释放子菜单窗口占据的屏幕原来内容*/
textbackground(WHITE);
textcolor(BLACK);
gotoxy(4,1);
cprintf("%s",m[0]);
}
}
}
}
9.2.2 选择式菜单的设计
所谓选择式菜单,就是在屏幕上出现一个菜单,操作者可根据菜单上所提供的数字或字母按相应的键去执行特定的程序,当程序执行完后又回到主菜单上。
这种菜单编制简单,操作方便,使用灵活,尤其适用于大型管理程序。如果在自动批处理文件上加入这种菜单后,操作者可根据菜单上的提示,进行相应的操作,这样可以简化许多步骤,对一般微机用户来说是比较适合的。
[例9-10] 选择式菜单程序menu2.c
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
main( )
{
char ch;
int i;
do {
system("cls");
printf("\n\t1. into Turbo C ");
printf("\n\t2. into Windows" );
printf("\n\t3. into Wps");
printf("\n\t4. into Dbase") ;
printf("\n\t0. Quit \n\n");
printf("\t Please select:");
ch=getch( );
switch(ch)
{
case '1': system("tc");break;
case '2': system("win");break;
case '3': system("wps");break;
case '4': system("dbase");break;
case '0': system("cls");eXit(1);
default:
printf("\n\t*** wrong !!! ***\n");
for (i=0;i<600;i++);
{ ; }
}
}
while(1);
}
9.2.3 实现阴影窗口的技巧
目前,许多应用软件都采用了输出窗口技术,有的甚至使用了带有阴影的输出窗口。这种技术给人们以新鲜醒目的感觉,可达到事半功倍的作用。
程序menu3.c是一个阴影窗口的例子。其中用到两个自编函数,一个是建立窗口函数set_win( ),另一个是建立带有阴影部分的窗口函数set_bkwin( )。这两个函数需要传递以下几个参数:
int X1,y1,X2,y2,b,bc,tc
char *head
其中:x1、y1、x2、y2决定了窗口边框大小, b用来选择窗口的类型;当b = 0时,无边框,当b =1时,单线边框,当b = 2时,上下边框为双线,左右边框为单线,当b = 3时,双线边框,当b = 4时,上下边框为单线,左右边框为双线;参数b c用来决定窗口的背景颜色,其范围为0 ~ 7;参数t c决定窗口内字符的颜色,其范围为0 ~ 15; 参数head为窗口名称。
在文本状态下,一个字符在屏幕缓冲区内要占用2个字节来存储。且字符内容在前属性在后,顺序存储。所谓属性,就是字符的背景颜色和字符颜色,我们可以通过改变其属性字节,来实现窗口的阴影。
[例9 - 11] 阴影窗口程序menu3.c
#include<stdio.h>
#include<string.h>
#include<conio.h>
#define screen (*screen_ptr)
typedef struct texel_struct
{
unsigned char attr;
}teXel;
typedef texel screen_array[25][80];
screen_array far *screen_ptr = (screen_array far *) 0Xb800;
void set_win( int X1,int y1, int X2,int y2,int b,int bc, int tc,char *head);
void set_bkwin(int X1,int y1,int X2,int y2,int b,int bc,int tc,char *head);
void main(void )
{
set_bkwin(1,2,25,18,2,2,1,"window");
getch();
}
void set_bkwin(X1,y1,X2,y2,b,bc,tc,head)
int X1, y1, X2, y2, b, bc, tc;
char *head;
{
int i, j;
for(i=X1+1;i<X2+2;i++)
{
for(j=y2;j<y2+1;j++)
screen[j][i].attr=8;
}
for(i=X2+1;i<X2+2;i++)
{
for(j=y1;j<y2+1;j++)
screen[j][i].attr=8;
}
set_win(X1,y1,X2,y2,b,bc,tc,head);
}
void set_win(X1,y1,X2,y2,b,bc,tc,head)
int X1,y1,X2,y2,b,bc,tc;
char *head;
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -