资源描述
1: C语言游戏设计
1.1:课程设计目标
C语言编写一款打飞机游戏,掌握函数的使用和编程的整体思路。
1.2:整体设计思路
总体设想:运行游戏时显示游戏的界面,允许用户选择个性化设置,A、D、W分别控制飞机的左右移动和发射子弹,不同的敌机飞行和攻击,并不时伴有奖励。游行运行时播放音效,同时记录飞机的生命和得分,达到一定的分数进入下一关。
需要构建的函数:位图调用模块、界面输出函数、主菜单函数、设置函数、速度选择函数、游戏控制函数、敌机移动函数、子弹移动函数、boss函数、计时函数。
1.3: 需调用的头文件:include<stdio.h> //常规库头文件
include<conio.h> //控制台输入输出流头文件
include<stdlib.h> //系统函数头文件
include<time.h> //时间函数头文件
include<windows.h> //windows函数库
include<mmsystem.h> //导入声音头文件
pragma comment(lib,"winmm.lib ")//导入声音头文件库
1.4: 游戏过程模拟:
启动游戏
用户个性化设置
恭喜进入下一关
Game over
判断飞机生命
记录飞机飞行时间和生命
判断输入指令
Menu
菜单函数
Mpovepal1
敌弹
Movepal
敌机函数
Boss
函数
Bmp
位图调用
Set
设置函数
Update
计时函数
Delay
游控函数
Indelay
速控函数
Print
界面输出
Movebul
子弹速度
飞机的移动,子弹的发射,音乐的播放,信息的记录
1.5: 显示效果如下图所示:
初始设置界面: 游戏界面
2 算法实现
2.1 需要了解的知识点:
Main函数和menu函数编写比较顺利,在bmp函数中遇到如何显示窗口和调用图片的问题,看了一些例子和网上的资料,逐渐掌握了一下知识点:
设备上下文:设备,显示器,打印机,数码相机,扫描仪这些类似的设备 ,上下文,就是上面设备的相关信息,比如屏幕分辨率等
HANDLE 通用句柄,实际上是一个指向指针的指针,在Windows操作系统中,内存操作器经常移动对象,来满足各种程序的内存需要,为了解决寻找对象问题,内存管理器开辟出一块专门的内存储存空间,把移动后的地址存储在该空间,这样就可以通过该地址间接寻找到对象。
HDC设备描述句柄,实现对窗口操作区域的GDI(图形设备接口, 负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出)操作,如画线、写文本、绘画制图等。
BITMAP 用于处理有像素数据定义的图像的对象。
GetDC(0) 检索特定的客户区域或整个屏幕的宣示设备上下文环境的句柄,以后可以使用该句柄在设备上下文环境中绘图。
LoadImage 装载图标、光标或位图。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的值为资源名称。
CreateCompatibleDC 该函数创建一个与指定设备兼容的内存设备上下文环境(DC)。通过GetDc()获取的HDC直接与相关设备沟通,而本函数创建的DC,则是与内存中的一个表面相关联。
SelectObject 计算机编程语言函数,该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象。
GetObject 函数功能:该函数得到指定图形对象的信息,根据图形对象,函数把填满的或结构,或表项(用于逻辑调色板)数目放入一个指定的缓冲区。
BitBlt 该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境.
ReleaseDC 函数释放设备上下文环境(DC)供其他应用程序使用。函数的效果与设备上下文环境类有关。它只释放公用的和设备上下文环境,对于类或私有的则无效。
DeleteDC :该函数删除指定的设备上下文环境.
DeleteObject 该函数删除一个逻辑笔、画笔、字体、位图、区域或者调色板,释放所有与该对象有关的系统资源,在对象被删除之后,指定的句柄也就失效了
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<stdio.h> //常规库头文件
#include<conio.h> //控制台输入输出流头文件
#include<stdlib.h> //系统函数头文件
#include<time.h> //时间函数头文件
#include<windows.h> //windows函数库
#include<mmsystem.h> //导入声音头文件
#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<width;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<width;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<width;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<width;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_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(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<width-2)
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<width-2)
scr[21][pl]=0,scr[21][++pl]=1;break;
case'w':
case 53:{scr[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][rand()%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);
Update();
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("对不起,游戏结束:按任意键结束");getch();getch();break;}
if(k3==10) {printf("对不起,游戏结束:按任意键结束");getch();getch();break;}
}
}
//关卡三////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(k1>=500)
{
//全局变量初始化
k1=0;
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())//判断键盘当前是否有输入,有则返回该值,无则返回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<width-2)
scr[21][pl]=0,scr[21][++pl]=1;break;
case'w':
case 53:{scr[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][rand()%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);
Update();
Delay();
if(i==30000) i=0;
if(k1>=1000) {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("对不起,
展开阅读全文