软件工程毕业设计_c语言游戏设计
1: C语言游戏设计
1.1:课程设计目标
C语言编写一款打飞机游戏,掌握函数的使用和编程的整体思路。
1.2:整体设计思路
总体设想:运行游戏时显示游戏的界面,允许用户选择个性化设置,A、
D、W分别控制飞机的左右移动和发射子弹,不同的敌机飞行和攻击,并不
时伴有奖励。游行运行时播放音效,同时记录飞机的生命和得分,达到一定的分数进入下一关。
需要构建的函数:位图调用模块、界面输出函数、主菜单函数、设置函数、速度选择函数、游戏控制函数、敌机移动函数、子弹移动函数、boss函数、计时函数。
1.3: 需调用的头文件:include
include
include
include
include
pragma comment(lib,"winmm.lib ")//导入声音头文件库
1.4: 游戏过程模拟:
1.5:显示效果如下图所示:
初始设置界面:游戏界面
2 算法实现
2.1需要了解的知识点:
Main函数和menu函数编写比较顺利,在bmp函数中遇到如何显示窗口和调用图片的问题,看了一些例子和网上的资料,逐渐掌握了一下知识点:
○1设备上下文:设备,显示器,打印机,数码相机,扫描仪这些类似的设备,
上下文,就是上面设备的相关信息,比如屏幕分辨率等
○2 HANDLE 通用句柄,实际上是一个指向指针的指针,在Windows操作系统中,
内存操作器经常移动对象,来满足各种程序的内存需要,为了解决寻找对象问题,内存管理器开辟出一块专门的内存储存空间,把移动后的地址存储在该空间,这样就可以通过该地址间接寻找到对象。
○3 HDC设备描述句柄,实现对窗口操作区域的GDI(图形设备接口, 负责系统
与绘图程序之间的信息交换,处理所有Windows程序的图形输出)操作,如画线、写文本、绘画制图等。
○4 BITMAP 用于处理有像素数据定义的图像的对象。
○5 GetDC(0) 检索特定的客户区域或整个屏幕的宣示设备上下文环境的句柄,以后可以使用该句柄在设备上下文环境中绘图。
○6LoadImage 装载图标、光标或位图。HANDLE LoadImage(HINSTANCE
hinst,LPCTSTR lpszName,UINT uType,int cxDesired,int CyDesired,UINT fuLoad), hinst 处理包含被撞在图像模块的实例,装载oem图像时参数设为0;name指向装载图像资源的名称;type 指定被装备图像类型cxdesired 和cyDesired指定图标的宽度和高度,如果参数为0,则使用目前资源的高度。Fuload -LR_LOADFROMFILE:根据参数lpszName的值装载图像。若标记未被给定,lpszName的值为资源名称。
○7 CreateCompatibleDC 该函数创建一个与指定设备兼容的内存设备上下文
环境(DC)。通过GetDc()获取的HDC直接与相关设备沟通,而本函数创建的DC,则是与内存中的一个表面相关联。
○8 SelectObject 计算机编程语言函数,该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象。
○9 GetObject 函数功能:该函数得到指定图形对象的信息,根据图形对象,函数把填满的或结构,或表项(用于逻辑调色板)数目放入一个指定的缓冲区。
10 BitBlt 该函数对指定的源设备环境区域中的像素进行位块(bit_block)○
转换,以传送到目标设备环境.
11
○
效果与设备上下文环境类有关。它只释放公用的和设备上下文环境,对于类或私有的则无效。
12 DeleteDC :该函数删除指定的设备上下文环境.
○
13 DeleteObject
○
板,释放所有与该对象有关的系统资源,在对象被删除之后,指定的句柄也就失效了
14 system("mode con cols=48 lines=25") 表示窗口宽度和高度
○
15system(“color OA”) color后面的0是背景色代号,A是前景色代号。○
各颜色代码如下:0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色 A=淡绿色 B=淡浅绿色,淡红色 D=淡紫色 E=淡黄色 F=亮白色
2.2 代码讲解:
#include
#include
#include
#include
#include
#include
#pragma comment(lib,"winmm.lib ")//导入声音头文件库
#define N 50 //宏
void Update(void); //计时函数
void Delay(void); //游戏控速函数
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); //位图调用模块
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 CLOCK;
//计时模块
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++)
{ }
}
//速度选择函数
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;
case'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);
}
//界面输出模块
void print(int a[][N])
{
int i,j;
system("cls");
for(i=0;i<23;i++)
{
for(j=-1;j { a[i+1][width-1]=4; //a[i][-1]=4; a[0][j-1]=5; a[22][j]=6; if(a[i][j]==0)printf(" ");//清空 if(a[i][j]==1)printf("%C%c%C",17,87,16);//角色 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);//上水平边界 //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==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]) { int i,j; for(i=0;i<21;i++) for(j=0;j { if(i==0&&a[i][j]==2)a[i][j]=0; if(a[i][j]==2) { if(a[i-1][j]==3) { score +=10; k1=score; //播放敌机1死亡音乐 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]==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 { 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=0;j { if(i==21&&a[i][j]==7) a[i][j]=0; if(a[i][j]==7)a[i][j]=0,a[i+1][j]=7; } if(a[21][pl]==1&&a[20][pl]==7) { death -=3; k=death; } } //横向奖励模块 void boss(int a[][N]) { int i,j; for(i=0;i<=21;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",IMAGE_BITMAP,0,0,LR_LOADFRO MFILE); 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(void) { 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); 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); 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=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); 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"); printf("%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() { //全局变量初始化 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); //方式一,不能同时播放两首歌曲 mciSendString("open E:\\haha\\music\\game_music.mp3 alias MySong",NULL,0,NULL); mciSendString("play MySong",NULL,0,NULL); //方式二,课同时播放两首歌 //关卡一 ///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// 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 scr[21][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)//控制敌机密度 { 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(scr); 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); printf("恭喜你闯过第1关:按任意键继续 ");getch();getch();break;} if(k2==0) {printf("对不起,游戏结束:按任意键结束 ");getch();getch();break;} if(k3==10) {printf("对不起,游戏结束:按任意键结束 ");getch();getch();break;} } //关卡二 ///////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// 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",NULL,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 scr[21][pl]=0,scr[21][++pl]=1;break; case'w':