C语言高级demo Flappy Bird游戏

导语

这是C语言高级demo。用C语言实现Flappy Bird这款经典的游戏,最终的效果要达到与原著有一定的相似度。示意图如下:(完整的代码在结语部分)
示意图
本demo的要求有:

  1. 游戏画面精美,尽力达到原汁原味。
  2. 在游戏中没有图像的闪烁,画质良好且稳定。
  3. 对游戏的数据以文件形式储存。
  4. 实现积分。
  5. 游戏有玩法提示,良好的交互。
  6. 合适的音效。

序章

首先介绍我用到了那些技术。

  1. C语言
  2. EasyX图形库。EasyX 是针对 C++ 的图形库,可以帮助 C++语言初学者快速上手图形和游戏编程。它的内部调用Windows API 兼容性良好,对新手友好,使用简单,支持鼠标,批量绘图技术,支持真彩色。在项目开发中熟练使用图像库中对图片操作的函数,理解批量绘图函数并运用
  3. Window.h中的一些函数的使用:
    • 键盘处理函数GetAsyncKeyState(),它是一个用来判断函数调用时指定虚拟键的状态,确定用户当前是否按下了键盘上的一个键的函数。如果按下,则返回值最高位为1;
    • mciSendString(),它是用来播放多媒体文件的API指令,可以播放MPEG,AVI,WAV,MP3,等等。

总的来说,运用的技术没有太多,但是我在实际编码时发现了不少问题,比如图片的黑边如何处理,按键灵敏度等,在后面我会解释如何处理它们的。

游戏总体设计

游戏流程图

游戏流程图
(并不标准的流程图,但基本额能够表达清楚整个游戏的运行过程)

游戏中数据与函数介绍

以下内容全部定义在一个头文件中:FB_headfile.h

  1. 一, bird数据
struct Bird
{
	int birdhigh;
	int birdpicture;
	int number;
	float flow;
	float up;	
};
  1. 游戏中的图片数据
typedef struct Picture
{
	IMAGE birdpt[3][2];//bird图片
	IMAGE bandpt[5][2];//障碍物图片
	IMAGE backgroundpt;//背景图片
	IMAGE landpt;//下方可以移动土地
	IMAGE big_num[10][2];//大号的数字
	IMAGE mid_num[10][2];//中号数字
	IMAGE sm_num[10];//小号数字
	IMAGE gametitle[2];//游戏的标题
	IMAGE getready[2];//准备阶段标题
	/*所有的按钮和得分面板 
		0:button_play; 1:button_score; 
		2:tutorial.jpg; 3;score_panel*/
	IMAGE button[4][2];
	IMAGE copyright[2];//开始界面的版权文字
	IMAGE medals[4][2];//奖牌
	IMAGE gameover[2];//游戏结束
	IMAGE newscore;//最新的高分
};
  1. 游戏其他数据
typedef struct Data
{
	int landdata;//下方移动土地
	//障碍物 0是障碍物的x坐标,1是上障碍物的y坐标 2是下方障碍物y坐标
	int banddata[5][3];
	int nowscore;//本次得分
	int speed;//移动速度
	int oldscore[3];//0第一,1第二,2第三
	int scoreblock;//分数锁
	bool life;//bird是否存活
	Bird bird;//bird数据
};
  1. 用到的函数
void initdata(Data &data);//初始化游戏数据
void birdct(Data &data);// bird控制
bool play();//开始游戏
void databack(Data &data);//数据处理
void gamestartmenu(Picture picture, Data data);//绘制开始界面
void getread(Picture picture,Data data);//绘制getready界面
void picturedeal(Picture &picture,int n);//游戏图片处理(加载与旋转) n=1 是加载图片
void drowpicture(Picture picture, Data data);//绘制游戏内容
void collision(Data &data);//碰撞
void scorepanl(Picture picture,Data &data);//得分面板
void changeband(Data &data, int n);//改变障碍物的Y轴数据
using namespace std;

游戏实现

开始界面实现

在这里插入图片描述
实现前的讲解:(之后会默认你已经明白这些知识了)

  1. 黑边处理:仔细的你可能已经发现了,几乎所有的图片数据都是二维,并且第二维的元素为2。我简单解释一下:因为素材图片都是网上找到,如果直接画上去会有很难看的黑边,我用的图形库又不能使用透明背景的图片,但它支持绘图时,将要绘制的图像像素与他要覆盖范围内的原像素进行位运算并显示运算后的结果图像,基于这个功能,我们可以自己实现去黑边,首先每张图片需要制作它的掩码图,比如:
    在这里插入图片描述
    有了它的掩码图,就可以去掉黑边了。具体的原理可以自行百度,我提供一份参考资料:点这里
  2. 闪烁处理: 大多数情况下,我们直接绘制在屏幕上的图片会有严重的闪烁!这十分影响游戏的效果,发生闪烁的原因可以自行百度,这里不再赘述。好在图形库位我们实现了批量绘图的技术,简单提及一下它是如何实现的:在开始批量绘图时(调用:BeginBatchDraw()),他就另外创建了一个画板,你的只有所有绘制的图像都会这这个画板上,而不是直接显示在你的显示器上,当你本次绘画完成时(调用FlushBatchDraw();),它会一次性把你之前画的内容显示出来。最后记得关闭批量绘图
    tips:不同的图形库对于批量绘图有不同实现。
  3. 这一部分编码难度在分数排名的绘制,它涉及到文件操作、界面的跳转等。

代码示例

  1. 掩码图的运用与批量绘图技术:
BeginBatchDraw();//开始批量绘图
putimage(0, 0, &picture.backgroundpt);
putimage(50, 100, &picture.gametitle[0], SRCAND);
putimage(50, 100, &picture.gametitle[1], SRCPAINT);

putimage(115, 180, &picture.birdpt[number][0], SRCAND);
putimage(115, 180, &picture.birdpt[number][1], SRCPAINT);

putimage(20, 345, &picture.button[0][0], SRCAND);
putimage(20, 345, &picture.button[0][1], SRCPAINT);

putimage(150, 340, &picture.button[1][0], SRCAND);
putimage(150, 340, &picture.button[1][1], SRCPAINT);

putimage(n, 400, &picture.landpt);

putimage(70, 425, &picture.copyright[0], SRCAND);
putimage(70, 425, &picture.copyright[1], SRCPAINT);

FlushBatchDraw();//将已经绘制的图像一次性显示出来
						
Sleep(50);
putimage(0, 0, &picture.backgroundpt);

putimage(50, 100, &picture.gametitle[0], SRCAND);
putimage(50, 100, &picture.gametitle[1], SRCPAINT);

putimage(115, 180, &picture.birdpt[number][0], SRCAND);
putimage(115, 180, &picture.birdpt[number][1], SRCPAINT);

putimage(20, 340, &picture.button[0][0], SRCAND);
putimage(20, 340, &picture.button[0][1], SRCPAINT);

putimage(150, 340, &picture.button[1][0], SRCAND);
putimage(150, 340, &picture.button[1][1], SRCPAINT);

putimage(n, 400, &picture.landpt);

putimage(70, 425, &picture.copyright[0], SRCAND);
putimage(70, 425, &picture.copyright[1], SRCPAINT);

FlushBatchDraw();//将已经绘制的图像一次性显示出来
EndBatchDraw();//结束批量绘图

bird控制

实现前的讲解:

  1. 这个部分实现的难点在于捕获键盘信息。我使用了window的api(GetAsyncKeyState)来获取按键信息。
  2. 设置bird的下降速度。

流程图:
在这里插入图片描述
实现函数:birdct()

游戏绘图

流程图:
在这里插入图片描述
实现函数:drowpicture()

碰撞与得分实现

这是游戏中最复杂的部分。

  1. 碰撞的设计思路:
    在这里插入图片描述
    实现函数:collision()

结语

感谢你的参阅,游戏还有很多不完善的地方,有兴趣的话你可以添加自己的玩法。最后附上项目的地址:点这里

  • 7
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值