?? 函數實現動畫的技巧.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 + -