课程设计—用C语言编码一个小游戏(flappy bird)
前言
这是我写的第一个程序,写一篇文章纪念一下,同时也给后续刚刚开始学习计算机的同学们一个参考。
注意:完成该程序需要用到easy-x库下<graphics.h>数据,建议用vc6或vs2013版本以上等支持安装easy-x库的软件
easy-x库安装挺简单的,见
Easy-X安装或
https://blog.csdn.net/_/article/details/
一、系统简介及最终效果

该游戏名为FLIP 滑稽,改自flappy bird。游戏实现了按空格键跳跃,越过障碍无得分,触碰障碍物边界或游戏窗口上下边界游戏结束的功能。其中图片、音效、文件写入/读取、键盘输入、鼠标输入的交互让游戏的体验更加良好。游戏主菜单下有多个模块供选择,可以开始/继续/退出游戏及获取有关帮助和游戏相关信息。游戏过程中可以随时暂停返回主菜单或选择继续游戏。游戏结束后也可选择返回主菜单或是重新开始或是退出游戏。








二、函数模块图及所需的一些材料

下图为我编程时所用到的图片和音频文件(积分下载材料点这里),百度云盘下载点这里,提取码2333 (可以的话积分下载支持一下呀)大家不一定要用我的材料,可以用自己喜欢的图片与音频文件,建议将这些材料放在一个文件夹里方便后面的引用。

三、具体代码(在代码中有具体的解释)
我是在安装了easy-x库的VC6.0下运行的
1、头文件
// #include<bits/stdc++.h> #include<stdio.h> #include <conio.h> #include <time.h> #include <graphics.h> #pragma comment(lib,"Winmm.lib")//导入音乐等多媒体 void main();//主函数 void startup();//初始化 void show();//画面显示 void updateWithInput();//与玩家输入有关的画面数据更新 void updateWithoutInput();//与玩家输入无关的画面数据更新 void gameOver();//结束处理 void startMenu();//开始菜单 oid pauseMenu();//暂停菜单 void overMenu();//结束菜单 void readHelpFile();//打开帮助页面 void readAboutFile();//打开关于页面 void readRecordFile();//读档 void writeRecordFile();//存档 #define High 600 //定义游戏界面的高度 #define Width 600 //定义游戏界面的宽度 #define Difficulty 10 //定义游戏难度(用Sleep函数控制快慢)
2、全局变量定义
//定义全局变量 IMAGE huaji1,huaji2,img_bk,tiao1,tiao2,pause,help,about,shang1,shang2,xia1,xia2,over1,over2,over3,over4;//各种图片 int huaji_x,huaji_y;//滑稽的坐标 int bar_x,shang_y,xia_y;//障碍的坐标 int score;//得分 //定义游戏状态:若为0初始化后显示主菜单,若为1直接进入游戏 int gameStatus=0;
3、存读档函数
//读取游戏存档,实现“继续游戏” void readRecordFile() { FILE *fp; fp=fopen("F:\\游戏记录.txt","r"); fscanf(fp,"%d %d %d %d %d %d",&huaji_x,&huaji_y,&bar_x,&shang_y,&xia_y,&score);//游戏核心数据读出 fclose(fp); } //游戏数据写入存档,保存游戏记录 void writeRecordFile() { FILE *fp; fp=fopen("F:\\游戏记录.txt","w+"); fprintf(fp,"%d %d %d %d %d %d",huaji_x,huaji_y,bar_x,shang_y,xia_y,score);//游戏核心数据写入 fclose(fp); }
4、关于/帮助菜单函数
//主菜单里的“帮助”界面 void readHelpFile() { loadimage(&help,"F:\\帮助.jpg");//打开帮助界面背景图片 putimage(0,0,&help); FlushBatchDraw(); mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐 mciSendString("open F:\\帮助.mp3 alias help",NULL,0,NULL);//打开帮助界面背景音乐 mciSendString("play help repeat",NULL,0,NULL);//播放 FILE *fp; char s[32]; fp=fopen("F:\\帮助.txt","r");//读取“帮助”文档 int length=25; //定义行间距 while(!feof(fp)) // 经过试验发现每行32个字符很适合 { fgets(s,32,fp); setbkmode(TRANSPARENT);//透明化文字背景 settextcolor(WHITE); settextstyle(20,0,_T("楷体")); outtextxy(25,length, s);//将字符串输出到界面对应坐标位置上 length+=25; } settextcolor(YELLOW); settextstyle(35,0,_T("华文新魏")); outtextxy(0,555,"温馨提示:点击屏幕任意位置回主菜单");//在底端输出温馨提示 Sleep(1000); FlushBatchDraw(); fclose(fp); MOUSEMSG m;//用鼠标控制退出帮助界面回到主菜单 while(1) { m=GetMouseMsg(); if(m.uMsg==WM_LBUTTONDOWN) { mciSendString("close help",NULL,0,NULL);//左击任意位置回主菜单 gameStatus=0; main(); } } } //主菜单里的“关于”界面 void readAboutFile() { loadimage(&about,"F:\\关于.jpg");//打开关于界面背景图片 putimage(0,0,&about); FlushBatchDraw(); mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐 mciSendString("open F:\\关于.mp3 alias about",NULL,0,NULL);//打开帮助界面背景音乐 mciSendString("play about repeat",NULL,0,NULL);//播放 FILE *fp; char s[80]; fp=fopen("F:\\关于.txt","r"); fgets(s,80,fp); setbkmode(TRANSPARENT);//背景透明 settextcolor(BLACK); settextstyle(50,0,_T("华文彩云")); outtextxy(250,0,"关于"); settextstyle(30,0,_T("华文行楷"));//输出关于界面的相关内容(内容较少就不用文本了直接写入) outtextxy(240,60,"关于的话"); outtextxy(250,95,"emmmmmm"); outtextxy(150,130,"这是个非常好玩的游戏"); outtextxy(250,165,"嗯 没错"); outtextxy(240,195,"就是这样"); settextcolor(RED); settextstyle(35,0,_T("华文新魏")); outtextxy(0,555,"温馨提示:点击屏幕任意位置回主菜单"); Sleep(1000); FlushBatchDraw(); fclose(fp); MOUSEMSG m;//用鼠标控制退出帮助界面回到主菜单 while(1) { m=GetMouseMsg(); if(m.uMsg==WM_LBUTTONDOWN) { mciSendString("close about",NULL,0,NULL);//左击任意位置回主菜单 gameStatus=0; main(); } } }
5、主菜单/暂停菜单/结束菜单函数
//主菜单界面 void startMenu() { mciSendString("close bkmusic_2",NULL,0,NULL);//关闭背景音乐 loadimage(&pause,"F:\\初始化界面.jpg");//打开初始化界面背景图片 putimage(0,0,&pause); FlushBatchDraw(); setbkmode(TRANSPARENT);//背景透明 settextcolor(YELLOW); settextstyle(50,0,_T("华文行楷"));//在对应位置输出菜单选项内容 outtextxy(175,150,"1 开始游戏"); outtextxy(175,250,"2 继续游戏"); outtextxy(50,350,"3 什么游戏,我要学习!"); settextcolor(WHITE);//这两个内容用不同字体 settextstyle(40,0,_T("华文彩云")); outtextxy(50,500,"4 帮助"); outtextxy(425,500,"5 关于"); char input;//判断是否有键盘输入 if(kbhit()) { input=getch(); if(input=='1') gameStatus=1;//进入新游戏 else if(input=='2') { readRecordFile();//读取存档,继续游戏 gameStatus=1; } else if(input=='3') { gameStatus=1;//去学习,退出游戏 exit(0); } else if(input=='4') { while(1)//让内容长久显示 readHelpFile();//读取帮助界面内容 } else if(input=='5') { while(1)//让内容长久显示 readAboutFile();//读取关于界面内容 } } } //暂停菜单界面 void pauseMenu() { while(1)//让内容长久显示 { loadimage(&pause,"F:\\暂停时的图片.jpg");//打开暂停菜单的背景图片 putimage(0,0,&pause); FlushBatchDraw(); char input; if(kbhit())//判断是否有鼠标输入 { input=getch(); if(input=='1')//开始新游戏 { gameStatus=1;//不进入主菜单,直接开始新游戏 main(); } else if(input=='2')//继续游戏 { startup();//从头开始初始化后读取存档,继续游戏 readRecordFile();//读取存档 show(); Sleep(1400);//预备开始阶段延时 while(1)//游戏循环执行 { show();//显示画面 updateWithoutInput();//与玩家输入无关的游戏界面更新 updateWithInput();//与玩家输入有光的游戏界面更新 } } else if(input=='3')//回主菜单 { gameStatus=0; startup(); putimage(0,0,&img_bk); //打开预备开始阶段背景画面 FlushBatchDraw(); show(); Sleep(1400);//预备开始阶段延时 break; } else if(input=='4')//退出游戏 { gameStatus=1; exit(0); } } } } void overMenu() { while(1) //让结束菜单长久显示 { loadimage(&over4,"F:\\结束时的背景图片.jpg"); putimage(0,0,&over4); setbkmode(TRANSPARENT);//透明化文字背景 settextcolor(WHITE); settextstyle(50,0,_T("华文行楷")); outtextxy(Width-500,High-500,"1 不够爽!再来一局!");//输出菜单内容 outtextxy(Width-500,High-400,"2 我想回主菜单了"); outtextxy(Width-500,High-300,"3 我要去学习了!!!"); settextcolor(YELLOW); settextstyle(50,0,_T("华文彩云")); outtextxy(Width-425,High-200,"得分: "); //显示得分 char s[10]; sprintf(s,"%d",score); outtextxy(Width-275,High-200,s); FlushBatchDraw(); char input; //判断是否有键盘输入 if(kbhit()) { input=getch(); if(input=='1')//开始新游戏 { gameStatus=1; main(); } else if(input=='2')//回主菜单 { gameStatus=0;//状态值为零,初始化后显示主菜单 startup(); putimage(0,0,&img_bk); //打开背景画面 FlushBatchDraw(); show(); Sleep(1400); break; } else if(input=='3')//去学习,退出游戏 exit(0); } } }
6、初始化函数
//初始化 void startup() { score=0; //初始化分数为0 initgraph(Width,High); //定义游戏界面大小 loadimage(&img_bk,"F:\\背景图片.jpg");//打开一系列游戏界面的图片 loadimage(&huaji1,"F:\\滑稽1.jpg"); loadimage(&huaji2,"F:\\滑稽2.jpg"); loadimage(&shang1,"F:\\上障碍1.jpg"); loadimage(&shang2,"F:\\上障碍2.jpg"); loadimage(&xia1,"F:\\下障碍1.jpg"); loadimage(&xia2,"F:\\下障碍2.jpg"); mciSendString("open F:\\背景音乐1.mp3 alias bkmusic_1",NULL,0,NULL);//打开背景音乐 mciSendString("play bkmusic_1 repeat",NULL,0,NULL);//播放 srand(time(NULL)); //利用系统时间产生伪随机种子,以为了得到随机位置的障碍 huaji_x = 24; //初始化滑稽坐标 huaji_y = rand() % 150 + 250; bar_x = 450; //初始化障碍的坐标 shang_y = rand() % 400 - 550; while(xia_y - shang_y>730 || xia_y - shang_y<670) //上下障碍随机出现的坐标范围 { shang_y = rand()%400 - 550; xia_y = rand()%300 + 150 ; } while(gameStatus==0) //状态为0则进入主菜单 { Sleep(200); startMenu();//主菜单界面 FlushBatchDraw(); } mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐 mciSendString("open F:\\背景音乐2.mp3 alias bkmusic_2",NULL,0,NULL);//打开游戏背景音乐 mciSendString("play bkmusic_2 repeat",NULL,0,NULL);//播放 mciSendString("close beginmusic",NULL,0,NULL); mciSendString("open F:\\开始.mp3 alias beginmusic ",NULL,0,NULL);//播放一次开始时的预备音效 mciSendString("play beginmusic",NULL,0,NULL); }
7、其他辅助函数
//显示画面 void show() { Sleep(Difficulty); //整体速度控制即难度 putimage(0,0,&img_bk); //打开背景画面 //采用精灵图与掩码图叠加偶读方法实现抠图,让部分区域透明 putimage(huaji_x,huaji_y,&huaji1,NOTSRCERASE); //透明化边界外的图片 putimage(huaji_x,huaji_y,&huaji2,SRCINVERT); putimage(bar_x,shang_y,&shang1,NOTSRCERASE);//上障碍 putimage(bar_x,shang_y,&shang2,SRCINVERT); putimage(bar_x,xia_y,&xia1,NOTSRCERASE);//下障碍 putimage(bar_x,xia_y,&xia2,SRCINVERT); setbkmode(TRANSPARENT);//文字背景透明 settextcolor(RED); settextstyle(50,0,_T("华文行楷")); outtextxy(0,0,"得分:"); settextcolor(RED); settextstyle(50,0,_T("Algerain"));//显示分数 char s[10]; sprintf(s,"%d",score); outtextxy(125,0,s); FlushBatchDraw(); } //与输入有关的更新 void updateWithInput() { char input; if (kbhit())//判断是否有键盘输入 { input = getch(); if (input==' ') { loadimage(&tiao1,"F:\\我跳1.jpg"); loadimage(&tiao2,"F:\\我跳2.jpg"); putimage(huaji_x,huaji_y,&tiao1,NOTSRCERASE);//每跳一下滑稽的表情就变一次 putimage(huaji_x,huaji_y,&tiao2,SRCINVERT); huaji_y-=30;//点一下空格滑稽就会上跳的高度 mciSendString("close jpmusic",NULL,0,NULL); mciSendString("open F:\\跳.mp3 alias jpmusic ",NULL,0,NULL);//按一下空格播放一次音效 mciSendString("play jpmusic",NULL,0,NULL); } else if(input==27)//27为esc 键的ascll码 { writeRecordFile();//存档 mciSendString("close bkmusic_2",NULL,0,NULL);//关闭游戏时的背景音乐 pauseMenu();//打开暂停界面 } } } //与玩家输入无关的游戏界面更新 void updateWithoutInput() { if (huaji_y<High) //自动下落 huaji_y++; if (bar_x>-140) //障碍左移,140为整个障碍的宽度 bar_x--; else //障碍重新从右边出现 { bar_x = Width; shang_y = rand()%300 - 450; while(xia_y - shang_y>730 || xia_y - shang_y<670) { shang_y =rand()%300 - 450; xia_y = rand()%300 + 150 ; } } if (((bar_x<50 && bar_x>-100) && (huaji_y+40>xia_y || huaji_y<shang_y+585)) || (huaji_y>550 || huaji_y<0 ))//判断失败 { mciSendString("close bkmusic_2",NULL,0,NULL);//关闭背景音乐 mciSendString("close overmusic_1",NULL,0,NULL); mciSendString("open F:\\尖叫.mp3 alias overmusic_1 ",NULL,0,NULL);//播放触碰危险边缘的尖叫音效 mciSendString("play overmusic_1",NULL,0,NULL); loadimage(&over1,"F:\\我输了1.jpg");//还是用两图叠加的方法实现 失败时表情边缘的透明 loadimage(&over2,"F:\\我输了2.jpg"); putimage(huaji_x,huaji_y,&over1,NOTSRCERASE);//输了后滑稽变为 失败时 的表情 putimage(huaji_x,huaji_y,&over2,SRCINVERT); FlushBatchDraw(); Sleep(2000);//表情出现后停留一段时间 mciSendString("close overmusic_2",NULL,0,NULL); mciSendString("open F:\\失败.mp3 alias overmusic_2 ",NULL,0,NULL);//播放 失败后 的背景音乐 mciSendString("play overmusic_2",NULL,0,NULL); loadimage(&over3,"F:\\不要打扰我学习.jpg");//打开 失败后 的背景图片 putimage(0,0,&over3); FlushBatchDraw(); Sleep(5000);//图片出现后停留一段时间 overMenu(); } if (bar_x==-90) //跳过障碍后加一分 { score++; mciSendString("close score",NULL,0,NULL); mciSendString("open F:\\加一.mp3 alias score",NULL,0,NULL);//打开加分时的音效 mciSendString("play score",NULL,0,NULL); } } //游戏结束处理 void gameOver() { EndBatchDraw();//结束绘图 closegraph();//关闭图片 }
8、主函数
void main() { startup(); //数据初始化 show(); //显示画面(这一画面为准备阶段的画面) Sleep(1400); //游戏准备阶段的延时 while(1)//游戏循环执行 { show(); //再次显示画面(游戏开始玩时的界面) updateWithoutInput();//与玩家输入无关的游戏界面更新 updateWithInput();//与玩家输入有光的游戏界面更新 } gameOver();//游戏结束处理 }
四、一些图片处理原理
loadimage(&tiao1,"F:\\我跳1.jpg"); //导入图片 loadimage(&tiao2,"F:\\我跳2.jpg"); putimage(huaji_x,huaji_y,&tiao1,NOTSRCERASE); //这里输入一张黑白图 putimage(huaji_x,huaji_y,&tiao2,SRCINVERT); // 这里输入原图
经过这几行代码的处理,在程序中就会把我们所需要的表情扣出来,不会有边缘的白边
五、完整源代码
#include<stdio.h> #include <conio.h> #include <time.h> #include <graphics.h> #pragma comment(lib,"Winmm.lib")//导入音乐等多媒体 void main();//主函数 void startup();//初始化 void show();//画面显示 void updateWithInput();//与玩家输入有关的画面数据更新 void updateWithoutInput();//与玩家输入无关的画面数据更新 void gameOver();//结束处理 void startMenu();//开始菜单 void pauseMenu();//暂停菜单 void overMenu();//结束菜单 void readHelpFile();//打开帮助页面 void readAboutFile();//打开关于页面 void readRecordFile();//读档 void writeRecordFile();//存档 #define High 600 //定义游戏界面的高度 #define Width 600 //定义游戏界面的宽度 #define Difficulty 10 //定义游戏难度(用Sleep函数控制快慢) //定义全局变量 IMAGE huaji1,huaji2,img_bk,tiao1,tiao2,pause,help,about,shang1,shang2,xia1,xia2,over1,over2,over3,over4;//各种图片 int huaji_x,huaji_y;//滑稽的坐标 int bar_x,shang_y,xia_y;//障碍的坐标 int score;//得分 //定义游戏状态:若为0初始化后显示主菜单,若为1直接进入游戏 int gameStatus=0; //读取游戏存档,实现“继续游戏” void readRecordFile() { FILE *fp; fp=fopen("F:\\游戏记录.txt","r"); fscanf(fp,"%d %d %d %d %d %d",&huaji_x,&huaji_y,&bar_x,&shang_y,&xia_y,&score);//游戏核心数据读出 fclose(fp); } //游戏数据写入存档,保存游戏记录 void writeRecordFile() { FILE *fp; fp=fopen("F:\\游戏记录.txt","w+"); fprintf(fp,"%d %d %d %d %d %d",huaji_x,huaji_y,bar_x,shang_y,xia_y,score);//游戏核心数据写入 fclose(fp); } //主菜单里的“帮助”界面 void readHelpFile() { loadimage(&help,"F:\\帮助.jpg");//打开帮助界面背景图片 putimage(0,0,&help); FlushBatchDraw(); mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐 mciSendString("open F:\\帮助.mp3 alias help",NULL,0,NULL);//打开帮助界面背景音乐 mciSendString("play help repeat",NULL,0,NULL);//播放 FILE *fp; char s[32]; fp=fopen("F:\\帮助.txt","r");//读取“帮助”文档 int length=25; //定义行间距 while(!feof(fp)) // 经过试验发现每行32个字符很适合 { fgets(s,32,fp); setbkmode(TRANSPARENT);//透明化文字背景 settextcolor(WHITE); settextstyle(20,0,_T("楷体")); outtextxy(25,length, s);//将字符串输出到界面对应坐标位置上 length+=25; } settextcolor(YELLOW); settextstyle(35,0,_T("华文新魏")); outtextxy(0,555,"温馨提示:点击屏幕任意位置回主菜单");//在底端输出温馨提示 Sleep(1000); FlushBatchDraw(); fclose(fp); MOUSEMSG m;//用鼠标控制退出帮助界面回到主菜单 while(1) { m=GetMouseMsg(); if(m.uMsg==WM_LBUTTONDOWN) { mciSendString("close help",NULL,0,NULL);//左击任意位置回主菜单 gameStatus=0; main(); } } } //主菜单里的“关于”界面 void readAboutFile() { loadimage(&about,"F:\\关于.jpg");//打开关于界面背景图片 putimage(0,0,&about); FlushBatchDraw(); mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐 mciSendString("open F:\\关于.mp3 alias about",NULL,0,NULL);//打开帮助界面背景音乐 mciSendString("play about repeat",NULL,0,NULL);//播放 FILE *fp; char s[80]; fp=fopen("F:\\关于.txt","r"); fgets(s,80,fp); setbkmode(TRANSPARENT);//背景透明 settextcolor(BLACK); settextstyle(50,0,_T("华文彩云")); outtextxy(250,0,"关于"); settextstyle(30,0,_T("华文行楷"));//输出关于界面的相关内容(内容较少就不用文本了直接写入) outtextxy(240,60,"关于的话"); outtextxy(250,95,"emmmmmm"); outtextxy(150,130,"这是个非常好玩的游戏"); outtextxy(250,165,"嗯 没错"); outtextxy(240,195,"就是这样"); settextcolor(RED); settextstyle(35,0,_T("华文新魏")); outtextxy(0,555,"温馨提示:点击屏幕任意位置回主菜单"); Sleep(1000); FlushBatchDraw(); fclose(fp); MOUSEMSG m;//用鼠标控制退出帮助界面回到主菜单 while(1) { m=GetMouseMsg(); if(m.uMsg==WM_LBUTTONDOWN) { mciSendString("close about",NULL,0,NULL);//左击任意位置回主菜单 gameStatus=0; main(); } } } //主菜单界面 void startMenu() { mciSendString("close bkmusic_2",NULL,0,NULL);//关闭背景音乐 loadimage(&pause,"F:\\初始化界面.jpg");//打开初始化界面背景图片 putimage(0,0,&pause); FlushBatchDraw(); setbkmode(TRANSPARENT);//背景透明 settextcolor(YELLOW); settextstyle(50,0,_T("华文行楷"));//在对应位置输出菜单选项内容 outtextxy(175,150,"1 开始游戏"); outtextxy(175,250,"2 继续游戏"); outtextxy(50,350,"3 什么游戏,我要学习!"); settextcolor(WHITE);//这两个内容用不同字体 settextstyle(40,0,_T("华文彩云")); outtextxy(50,500,"4 帮助"); outtextxy(425,500,"5 关于"); char input;//判断是否有键盘输入 if(kbhit()) { input=getch(); if(input=='1') gameStatus=1;//进入新游戏 else if(input=='2') { readRecordFile();//读取存档,继续游戏 gameStatus=1; } else if(input=='3') { gameStatus=1;//去学习,退出游戏 exit(0); } else if(input=='4') { while(1)//让内容长久显示 readHelpFile();//读取帮助界面内容 } else if(input=='5') { while(1)//让内容长久显示 readAboutFile();//读取关于界面内容 } } } //暂停菜单界面 void pauseMenu() { while(1)//让内容长久显示 { loadimage(&pause,"F:\\暂停时的图片.jpg");//打开暂停菜单的背景图片 putimage(0,0,&pause); FlushBatchDraw(); char input; if(kbhit())//判断是否有鼠标输入 { input=getch(); if(input=='1')//开始新游戏 { gameStatus=1;//不进入主菜单,直接开始新游戏 main(); } else if(input=='2')//继续游戏 { startup();//从头开始初始化后读取存档,继续游戏 readRecordFile();//读取存档 show(); Sleep(1400);//预备开始阶段延时 while(1)//游戏循环执行 { show();//显示画面 updateWithoutInput();//与玩家输入无关的游戏界面更新 updateWithInput();//与玩家输入有光的游戏界面更新 } } else if(input=='3')//回主菜单 { gameStatus=0; startup(); putimage(0,0,&img_bk); //打开预备开始阶段背景画面 FlushBatchDraw(); show(); Sleep(1400);//预备开始阶段延时 break; } else if(input=='4')//退出游戏 { gameStatus=1; exit(0); } } } } void overMenu() { while(1) //让结束菜单长久显示 { loadimage(&over4,"F:\\结束时的背景图片.jpg"); putimage(0,0,&over4); setbkmode(TRANSPARENT);//透明化文字背景 settextcolor(WHITE); settextstyle(50,0,_T("华文行楷")); outtextxy(Width-500,High-500,"1 不够爽!再来一局!");//输出菜单内容 outtextxy(Width-500,High-400,"2 我想回主菜单了"); outtextxy(Width-500,High-300,"3 我要去学习了!!!"); settextcolor(YELLOW); settextstyle(50,0,_T("华文彩云")); outtextxy(Width-425,High-200,"得分: "); //显示得分 char s[10]; sprintf(s,"%d",score); outtextxy(Width-275,High-200,s); FlushBatchDraw(); char input; //判断是否有键盘输入 if(kbhit()) { input=getch(); if(input=='1')//开始新游戏 { gameStatus=1; main(); } else if(input=='2')//回主菜单 { gameStatus=0;//状态值为零,初始化后显示主菜单 startup(); putimage(0,0,&img_bk); //打开背景画面 FlushBatchDraw(); show(); Sleep(1400); break; } else if(input=='3')//去学习,退出游戏 exit(0); } } } //初始化 void startup() { score=0; //初始化分数为0 initgraph(Width,High); //定义游戏界面大小 loadimage(&img_bk,"F:\\背景图片.jpg");//打开一系列游戏界面的图片 loadimage(&huaji1,"F:\\滑稽1.jpg"); loadimage(&huaji2,"F:\\滑稽2.jpg"); loadimage(&shang1,"F:\\上障碍1.jpg"); loadimage(&shang2,"F:\\上障碍2.jpg"); loadimage(&xia1,"F:\\下障碍1.jpg"); loadimage(&xia2,"F:\\下障碍2.jpg"); mciSendString("open F:\\背景音乐1.mp3 alias bkmusic_1",NULL,0,NULL);//打开背景音乐 mciSendString("play bkmusic_1 repeat",NULL,0,NULL);//播放 srand(time(NULL)); //利用系统时间产生伪随机种子,以为了得到随机位置的障碍 huaji_x = 24; //初始化滑稽坐标 huaji_y = rand() % 150 + 250; bar_x = 450; //初始化障碍的坐标 shang_y = rand() % 400 - 550; while(xia_y - shang_y>730 || xia_y - shang_y<670) //上下障碍随机出现的坐标范围 { shang_y = rand()%400 - 550; xia_y = rand()%300 + 150 ; } while(gameStatus==0) //状态为0则进入主菜单 { Sleep(200); startMenu();//主菜单界面 FlushBatchDraw(); } mciSendString("close bkmusic_1",NULL,0,NULL);//关闭主菜单背景音乐 mciSendString("open F:\\背景音乐2.mp3 alias bkmusic_2",NULL,0,NULL);//打开游戏背景音乐 mciSendString("play bkmusic_2 repeat",NULL,0,NULL);//播放 mciSendString("close beginmusic",NULL,0,NULL); mciSendString("open F:\\开始.mp3 alias beginmusic ",NULL,0,NULL);//播放一次开始时的预备音效 mciSendString("play beginmusic",NULL,0,NULL); } //显示画面 void show() { Sleep(Difficulty); //整体速度控制即难度 putimage(0,0,&img_bk); //打开背景画面 //采用精灵图与掩码图叠加偶读方法实现抠图,让部分区域透明 putimage(huaji_x,huaji_y,&huaji1,NOTSRCERASE); //透明化边界外的图片 putimage(huaji_x,huaji_y,&huaji2,SRCINVERT); putimage(bar_x,shang_y,&shang1,NOTSRCERASE);//上障碍 putimage(bar_x,shang_y,&shang2,SRCINVERT); putimage(bar_x,xia_y,&xia1,NOTSRCERASE);//下障碍 putimage(bar_x,xia_y,&xia2,SRCINVERT); setbkmode(TRANSPARENT);//文字背景透明 settextcolor(RED); settextstyle(50,0,_T("华文行楷")); outtextxy(0,0,"得分:"); settextcolor(RED); settextstyle(50,0,_T("Algerain"));//显示分数 char s[10]; sprintf(s,"%d",score); outtextxy(125,0,s); FlushBatchDraw(); } //与输入有关的更新 void updateWithInput() { char input; if (kbhit())//判断是否有键盘输入 { input = getch(); if (input==' ') { loadimage(&tiao1,"F:\\我跳1.jpg"); loadimage(&tiao2,"F:\\我跳2.jpg"); putimage(huaji_x,huaji_y,&tiao1,NOTSRCERASE);//每跳一下滑稽的表情就变一次 putimage(huaji_x,huaji_y,&tiao2,SRCINVERT); huaji_y-=30;//点一下空格滑稽就会上跳的高度 mciSendString("close jpmusic",NULL,0,NULL); mciSendString("open F:\\跳.mp3 alias jpmusic ",NULL,0,NULL);//按一下空格播放一次音效 mciSendString("play jpmusic",NULL,0,NULL); } else if(input==27)//27为esc 键的ascll码 { writeRecordFile();//存档 mciSendString("close bkmusic_2",NULL,0,NULL);//关闭游戏时的背景音乐 pauseMenu();//打开暂停界面 } } } //与玩家输入无关的游戏界面更新 void updateWithoutInput() { if (huaji_y<High) //自动下落 huaji_y++; if (bar_x>-140) //障碍左移,140为整个障碍的宽度 bar_x--; else //障碍重新从右边出现 { bar_x = Width; shang_y = rand()%300 - 450; while(xia_y - shang_y>730 || xia_y - shang_y<670) { shang_y =rand()%300 - 450; xia_y = rand()%300 + 150 ; } } if (((bar_x<50 && bar_x>-100) && (huaji_y+40>xia_y || huaji_y<shang_y+585)) || (huaji_y>550 || huaji_y<0 ))//判断失败 { mciSendString("close bkmusic_2",NULL,0,NULL);//关闭背景音乐 mciSendString("close overmusic_1",NULL,0,NULL); mciSendString("open F:\\尖叫.mp3 alias overmusic_1 ",NULL,0,NULL);//播放触碰危险边缘的尖叫音效 mciSendString("play overmusic_1",NULL,0,NULL); loadimage(&over1,"F:\\我输了1.jpg");//还是用两图叠加的方法实现 失败时表情边缘的透明 loadimage(&over2,"F:\\我输了2.jpg"); putimage(huaji_x,huaji_y,&over1,NOTSRCERASE);//输了后滑稽变为 失败时 的表情 putimage(huaji_x,huaji_y,&over2,SRCINVERT); FlushBatchDraw(); Sleep(2000);//表情出现后停留一段时间 mciSendString("close overmusic_2",NULL,0,NULL); mciSendString("open F:\\失败.mp3 alias overmusic_2 ",NULL,0,NULL);//播放 失败后 的背景音乐 mciSendString("play overmusic_2",NULL,0,NULL); loadimage(&over3,"F:\\不要打扰我学习.jpg");//打开 失败后 的背景图片 putimage(0,0,&over3); FlushBatchDraw(); Sleep(5000);//图片出现后停留一段时间 overMenu(); } if (bar_x==-90) //跳过障碍后加一分 { score++; mciSendString("close score",NULL,0,NULL); mciSendString("open F:\\加一.mp3 alias score",NULL,0,NULL);//打开加分时的音效 mciSendString("play score",NULL,0,NULL); } } //游戏结束处理 void gameOver() { EndBatchDraw();//结束绘图 closegraph();//关闭图片 } void main() { startup(); //数据初始化 show(); //显示画面(这一画面为准备阶段的画面) Sleep(1400); //游戏准备阶段的延时 while(1)//游戏循环执行 { show(); //再次显示画面(游戏开始玩时的界面) updateWithoutInput();//与玩家输入无关的游戏界面更新 updateWithInput();//与玩家输入有光的游戏界面更新 } gameOver();//游戏结束处理 }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232702.html原文链接:https://javaforall.net
