1、
1: C语言游戏设计
1.1:课程设计目标
C语言编写一款打飞机游戏,掌握函数的使用和编程的整体思路。
1.2:整体设计思路
总体设想:运行游戏时显示游戏的界面,允许用户选择个性化设置,A、D、W分别控制飞机的左右移动和发射子弹,不同的敌机飞行和攻击,并不时伴有奖励。游行运行时播放音效,同时记录飞机的生命和得分,达到一定的分数进入下一关。
需要构建的函数:位图调用模块、界面输出函数、主菜单函数、设置函数、速度选择函数、游戏控制函数、敌机移动函数、子弹移动函数、boss函数、计时函数。
1.3: 需调用的头文件:include
2、 //常规库头文件
include
3、clude
4、pal 敌机函数 Boss 函数 Bmp 位图调用 Set 设置函数 Update 计时函数 Delay 游控函数 Indelay 速控函数 Print 界面输出 Movebul 子弹速度 飞机的移动,子弹的发射,音乐的播放,信息的记录 1.5: 显示效果如下图所示: 初始设置界面: 游戏界面 2 算法实现 2.1 需要了解的知识点: Main函数和menu函数编写比较顺利,在bmp函数中遇到如何显示窗口和调用图片的问题,看了
5、一些例子和网上的资料,逐渐掌握了一下知识点: 设备上下文:设备,显示器,打印机,数码相机,扫描仪这些类似的设备 ,上下文,就是上面设备的相关信息,比如屏幕分辨率等 HANDLE 通用句柄,实际上是一个指向指针的指针,在Windows操作系统中,内存操作器经常移动对象,来满足各种程序的内存需要,为了解决寻找对象问题,内存管理器开辟出一块专门的内存储存空间,把移动后的地址存储在该空间,这样就可以通过该地址间接寻找到对象。 HDC设备描述句柄,实现对窗口操作区域的GDI(图形设备接口, 负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出)操作,如画线、写文本、
6、绘画制图等。 BITMAP 用于处理有像素数据定义的图像的对象。 GetDC(0) 检索特定的客户区域或整个屏幕的宣示设备上下文环境的句柄,以后可以使用该句柄在设备上下文环境中绘图。 LoadImage 装载图标、光标或位图。HANDLE LoadImage(HINSTANCE hinst,LPCTSTR lpszName,UINT uType,int cxDesired,int CyDesired,UINT fuLoad), hinst 处理包含被撞在图像模块的实例,装载oem图像时参数设为0;name指向装载图像资源的名称;type 指定被装备图像类型cxdesire
7、d 和cyDesired指定图标的宽度和高度,如果参数为0,则使用目前资源的高度。Fuload -LR_LOADFROMFILE:根据参数lpszName的值装载图像。若标记未被给定,lpszName的值为资源名称。 CreateCompatibleDC 该函数创建一个与指定设备兼容的内存设备上下文环境(DC)。通过GetDc()获取的HDC直接与相关设备沟通,而本函数创建的DC,则是与内存中的一个表面相关联。 SelectObject 计算机编程语言函数,该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象。 GetObject 函数功能:该函数得
8、到指定图形对象的信息,根据图形对象,函数把填满的或结构,或表项(用于逻辑调色板)数目放入一个指定的缓冲区。 BitBlt 该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境. ReleaseDC 函数释放设备上下文环境(DC)供其他应用程序使用。函数的效果与设备上下文环境类有关。它只释放公用的和设备上下文环境,对于类或私有的则无效。 DeleteDC :该函数删除指定的设备上下文环境. DeleteObject 该函数删除一个逻辑笔、画笔、字体、位图、区域或者调色板,释放所有与该对象有关的系统资源,在对象被删除之后,指定的句
9、柄也就失效了
system("mode con cols=48 lines=25") 表示窗口宽度和高度
system(“color OA”) color后面的0是背景色代号,A是前景色代号。各颜色代码如下:0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色 A=淡绿色 B=淡浅绿色 ,淡红色 D=淡紫色 E=淡黄色 F=亮白色
2.2 代码讲解:
#include
10、de
11、void InDelay(void); //速度选择函数 void print(int [][N]); //界面输出函数 void movebul(int [][N]); //子弹移动函数 void movebul1(int [][N]); //BOSS子弹移动函数 void movepla(int [][N]); //敌机移动函数 void movepla1(int [][N]); //敌机移动函数 void boss(int [][N]); //boss模块 void bmp(void); //位图调用模块
12、void set(void); //设置函数 void menu(void); //主菜单函数 int scr[23][N]={0},pl=20,bl=1,width=40,speed=4,density=30,score=0,death=7,k1=0,k2=7;//全局变量定义 int minute=0,second=0,p=0,k3=0; long int max=0; //时间结构体 struct clock { int minute; int second; }; typedef struct clock C
13、LOCK; //计时模块 void Update(void) { p++; if(p==7) { p=0; second++; } if(second==60) { second=0; minute++; } k3=minute; if(minute==15) { minute=0; } } //游戏控速模块 void Delay(void) { long t; for(t=0;t<=max;t++) { } } //速度选择函
14、数 void InDelay(void) { int sw=0; system("cls"); do { printf("请游戏的速度:0-10\n"); switch (getch()) { case'0':max=0;;break; case'1':max=1000;;break; case'2':max=10000;;break; case'3':max=100000;;break; case'4':max=1000000;;break; c
15、ase'5':max=10000000;;break; case'6':max=100000000;;break; case'7':max=1000000000;;break; case'8':max=10000000000;;break; case'9':max=100000000000;;break; case'10':max=500000000000;;break; default:printf("输入错误,请重新选择"); sw=1; } }while(sw); } //界面输出模块
16、
void print(int a[][N])
{
int i,j;
system("cls");
for(i=0;i<23;i++)
{
for(j=-1;j 17、 if(a[i][j]==2)printf("%c",43);//子弹
if(a[i][j]==3)printf("%c",3);//敌机1
if(a[i][j]==7)printf("%c",15);//敌机2
if(a[i][j]==8)printf("%c",14);//BOSS
if(a[i][j]==9)printf("%c",31);//BOSS攻击
//if(a[i][j]==4)printf("|");//垂直边界
//if(a[i][j]==5)printf("%c",20); 18、//上水平边界
//if(a[i][j]==6)printf("-");//下水平边界
if(i==1&&j==width-1)printf("得分:%d",score);
if(i==3&&j==width-1)printf("生命:%d",death);
if(i==5&&j==width-1)printf("设置:S键");
if(i==7&&j==width-1)printf("速度:V键");
if(i==9&&j==width-1)printf("时间:%2d:%2d",minute,second);
if(i= 19、12&&j==width-1)printf("控制:");
if(i==13&&j==width-1)printf(" W");
if(i==14&&j==width-1)printf(" A D");
if(i==15&&j==width-1)printf(" 5");
if(i==16&&j==width-1)printf(" 1 3");
}
printf("\n");
}
}
//BOSS攻击模块
//子弹攻击模块
void movebul(int a[][N])
20、{
int i,j;
for(i=0;i<21;i++)
for(j=0;j 21、 PlaySound("E:\\haha\\music\\enemy1_down.mp3", NULL, SND_FILENAME | SND_ASYNC);
}
if(a[i-1][j]==7)
{
score +=10;
k1=score;
//播放敌机2死亡音乐
PlaySound("E:\\haha\\music\\enemy3_down.mp3", NULL, SND_FILENAME | SND_ASYNC);
}
if(a[i-1][j] 22、8)
{
score +=40;
k1=score;
//播放过关音乐
PlaySound("E:\\haha\\music\\1761.mp3", NULL, SND_FILENAME | SND_ASYNC);
}
a[i][j]=0,a[i-1][j]=2;
}
}
}
//慢敌机移动模块
void movepla(int a[][N])
{
int i,j;
for(i=21;i>=0;i--)
for(j=0;j 23、 {
if(i==21&&a[i][j]==3)
a[i][j]=0;
if(a[i][j]==3)a[i][j]=0,a[i+1][j]=3;
}
if(a[21][pl]==1&&a[20][pl]==3)
{
death--;
k2=death;
}
}
//快敌机移动模块
void movepla1(int a[][N])
{
int i,j;
for(i=21;i>=0;i--)
for(j= 24、0;j 25、i++)
for(j=width;j>=0;j--)
{
if(i==21&&a[i][j]==8)
a[i][j]=0;
if(a[i][j]==8)a[i][j]=0,a[i][j+1]=8;
}
}
//位图调用模块
void bmp(void)//int argc, char* argv[]
{
HANDLE h;
HDC dc1,dc2;
BITMAP bmp;
dc1=GetDC(0);//得到屏幕DC
h=LoadImage(NULL,"E:\\haha\\music\\1.bmp",IMA 26、GE_BITMAP,0,0,LR_LOADFROMFILE);
dc2=CreateCompatibleDC(dc1);
SelectObject(dc2,h);
GetObject(h,sizeof(bmp),&bmp);
BitBlt(dc1,100,100, bmp.bmWidth=2080,bmp.bmHeight=1080,dc2,0,0,SRCCOPY);
Sleep(20);
ReleaseDC(0,dc1);
DeleteDC(dc2);
DeleteObject(h);
getch();
}
//游戏设置模块
void set(voi 27、d)
{
int sw=0,i,j;
system("cls");
do
{
sw=0;
printf("请游戏界面的大小:1.小 2.大 \n>>\n");
switch (getch())
{
case'1':width=200;pl=200;break;
case'2':width=20;pl=40;break;
default:printf("输入错误,请重新选择");
sw=1;
}
}while(sw);
28、 do
{
sw=0;
printf("请选择敌机密度:1.大 2.中 3.小 \n>>\n");
switch (getch())
{
case'1':density=10;break;
case'2':density=20;break;
case'3':density=30;break;
default:printf("错,请重新选择");
sw=1;
}
}while(sw);
29、 do
{
sw=0;
printf("敌机的飞行速度:1.快 2.中 3.慢 \n>>\n");
switch (getch())
{
case'1':speed=2;break;
case'2':speed=3;break;
case'3':speed=4;break;
default:printf("错误,请重新选择");
sw=1;
}
}while(sw);
for(i 30、0;i<22;i++)
for(j=0;j<40;j++)
scr[i][j]=0;
scr[21][pl]=1;
printf("按任意键保存");
getch();
}
//主菜单模块
void menu(void)
{
bmp();
system("mode con cols=46 lines=25");
system("color E0");
printf("%18c游戏说明:\n",32);
31、 printf("\n");
printf("%13c飞行控制:A向左 D向右\n",32);
printf("\n");
printf("%17cW:发射子弹\n",32);
printf("\n");
printf("%19cS:设置\n",32);
printf("\n");
printf("%16cEsc:开始游戏\n",32);
printf("\n");
pri 32、ntf("%14c游戏时间为15分钟",32);
printf("\n");
printf("\n");
printf("%13c本游戏由王均坐改编",32);
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("双击回车键直接进入游戏 >>>>:",15);
if(getch()=='s'||getch()=='S') set();
}
//主函数
void main() 33、
{
//全局变量初始化
long int i=0,j=0;
menu();
system("mode con cols=54 lines=25"); //屏幕大小控制
system("color 0A");//屏幕颜色更改
scr[21][pl]=1;
scr[0][0]=3;
//关卡一背景音乐
//PlaySound("E:\\haha\\music\\game_music.mp3", NULL, SND_ASYNC | SND_LOOP | SND_FILENAME); //方式一,不能同时播放两首歌曲
mciSend 34、String("open E:\\haha\\music\\game_music.mp3 alias MySong",NULL,0,NULL);
mciSendString("play MySong",NULL,0,NULL); //方式二,课同时播放两首歌
//关卡一/////////////////////////////////////////////////////////////////////////////////////////////////////////////// 35、/////////////////////
while(1)
{
int second=0,minute=0;
if(kbhit())//判断键盘当前是否有输入,有则返回该值,无则返回0
switch(getch())
{
case'a':
case'A':
case 49:if(pl>0)
scr[21][pl]=0,scr[21][--pl]=1;break;
case'd':
case'D':
case 51:if(pl 36、[pl]=0,scr[21][++pl]=1;break;
case'w':
case'W':
case 53:{scr[20][pl+1]=2;PlaySound("E:\\haha\\music\\enemy1_down.mp3", NULL, SND_FILENAME | SND_ASYNC);break;}
case's':
case'S':set();break;
case'v':
case'V':InDelay();break;
}
if(++j%density==0)//控制敌机密度
37、 {
j=0;
srand(time(NULL));//srang:调用系统时间作为种子
scr[0][rand()%width]=3;//rand:根据种子产生敌机随机数列1
scr[1][rand()%width]=7;//rand:根据种子产生敌机随机数列2
scr[rand()%20][1]=8;//rand:根据种子产生BOSS随机数列2
}
if(++i%speed==0)//控制敌机速度
movepla(scr);
movepla1(s 38、cr);
movebul(scr);
//movebul1(scr);
boss(scr);
print(scr);
Update();
Delay();
if(i==30000) i=0;
if(k1>=100) {mciSendString("close MySong",NULL,0,NULL);
PlaySound("E:\\haha\\music\\1761.mp3", NULL, SND_FILENAME | SND_ASYNC);
39、 printf("恭喜你闯过第1关:按任意键继续");getch();getch();break;}
if(k2==0) {printf("对不起,游戏结束:按任意键结束");getch();getch();break;}
if(k3==10) {printf("对不起,游戏结束:按任意键结束");getch();getch();break;}
}
//关卡二////////////////////////////////////////////////////////////////////////////////////////////////// 40、/////////////////////////////////
if(k1>=100)
{
//全局变量初始化
k1=0;
score=0;
death=7;
minute=0;
second=0;
width=40;
density=20;
speed=3;
//关卡二背景音乐
mciSendString("open E:\\haha\\music\\game_music.mp3 alias MySong",NULL,0,NULL);
mciSendString("play MySong",N 41、ULL,0,NULL);
while(1)
{
if(kbhit())//判断键盘当前是否有输入,有则返回该值,无则返回0
switch(getch())
{
case'a':
case 49:if(pl>0)
scr[21][pl]=0,scr[21][--pl]=1;break;
case'd':
case 51:if(pl 42、cr[20][pl+1]=2;PlaySound("C:\\gameresource\\sounds\\5.wav", NULL, SND_FILENAME | SND_ASYNC);break;}
case's':
case'S':set();break;
case'v':
case'V':InDelay();break;
}
if(++j%density==0)//控制敌机密度
{
j=0;
srand(time(NULL));//srang:调用系统时间作为种子
scr[0][ra 43、nd()%width]=3;//rand:根据种子产生随机数列1
scr[1][rand()%width]=7;//rand:根据种子产生随机数列2
scr[rand()%10][1]=8;//rand:根据种子产生BOSS随机数列2
}
if(++i%speed==0)//控制敌机速度
movepla(scr);
movepla1(scr);
movebul(scr);
//movebul1(scr);
boss(scr);
print(scr);
Up 44、date();
Delay();
if(i==30000) i=0;
if(k1>=500) {mciSendString("close MySong",NULL,0,NULL);
PlaySound("C:\\gameresource\\sounds\\9.wav", NULL, SND_FILENAME | SND_ASYNC);
printf("恭喜你闯过第2关:按任意键继续");getch();getch();break;}
if(k2==0) {printf( 45、"对不起,游戏结束:按任意键结束");getch();getch();break;}
if(k3==10) {printf("对不起,游戏结束:按任意键结束");getch();getch();break;}
}
}
//关卡三////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(k1>=500)
{
//全局变量初始化
k1=0;
46、
score=0;
death=7;
k1=0;
minute=0;
second=0;
width=20;
density=10;
speed=2;
//关卡三背景音乐
mciSendString("open C:\\gameresource\\sounds\\1.mp3 alias MySong",NULL,0,NULL);
mciSendString("play MySong",NULL,0,NULL);
while(1)
{
if(kbhit())//判断键盘当前是否有输入,有则 47、返回该值,无则返回0
switch(getch())
{
case'a':
case 49:if(pl>0)
scr[21][pl]=0,scr[21][--pl]=1;break;
case'd':
case 51:if(pl 48、D_FILENAME | SND_ASYNC);break;}
case's':
case'S':set();break;
case'v':
case'V':InDelay();break;
}
if(++j%density==0)//控制敌机密度
{
j=0;
srand(time(NULL));//srang:调用系统时间作为种子
scr[0][rand()%width]=3;//rand:根据种子产生随机数列1
scr[1][rand()%width]=7;//rand: 49、根据种子产生随机数列2
scr[rand()%10][1]=8;//rand:根据种子产生BOSS随机数列2
}
if(++i%speed==0)//控制敌机速度
movepla(scr);
movepla1(scr);
movebul(scr);
//movebul1(scr);
boss(scr);
print(scr);
Update();
Delay();
if(i==30000) i=0;
if(k1>=100 50、0) {mciSendString("close MySong",NULL,0,NULL);
PlaySound("E:\\haha\\music\\1761.wav", NULL, SND_FILENAME | SND_ASYNC);
printf("恭喜你闯过第3关:按任意键继续");getch();getch();break;}
if(k2==0) {printf("对不起,游戏结束:按任意键结束");getch();getch();break;}
if(k3==10) {printf("对不起,






