flappy+bird+c语言程序,课内资源 - 基于EasyX实现的Flappy Bird小游戏

一、设计目的掌握定义函数,并熟练使用各函数

实现各函数模块的调用

学会将静态库导入工程,熟练使用库函数

掌握使用graphics.h的IMAG的数据类型

学会调用API

学会编写合适的算法来解决问题

二、设计内容

为了更好地掌握各数据类型、数据结构的使用以及C语言程序设计的思想,以C语言平日课堂知识为主,复刻了前几年在移动端很火的一款游戏Flappy bird。

成品Flappy bird截图如下:

游戏开始

a63a9114a17baec446a6f5a94d4ba882.png

游戏画面

796a12700af1568b26f1b6e4abce8ff5.png

游戏结束

ba04560fc8134f95f84114d7a39d2241.png

三、概要设计

3.1 功能模块图

7ee04955ed5c082829898806f08b7506.png

3.2 各个模块详细的功能描述

Custom Function list 自定义函数

voidprint();

voidbegin();//载入music、背景、First stone

voidprintstone();

voidbird();//控制鸟的下降和上升

voidjudgement();

voidscoleprint();

voidendorretry();

使用到的头文件和lib

#include

#include

#include

#include

#include

#include

#include"mmsystem.h"

#includeWINMM.lib(VC6.0自带的静态库)

四、详细设计

首先,需要安装EasyX图形库,将.exe呈现出更好的图形界面,然后,利用graphics.h绘制图像。

熟悉graphics头文件中的各种库函数,比如

initgraph();// 界面初始化

circle();// 画圆

RGB();// 颜色设置

IMAGE// 定义IMAGE对象

closegraphics();// 关闭绘图界面等等

还需要寻找一些库函数,识别键盘的敲击,比如while(!kbhit())等等。熟悉相关库函数后,开始本次flappy bird程序编写。

实现思路如下所示:

背景图片的显示

加入小鸟图片

小鸟自由下落,按键后上升

加入静态的障碍物

障碍物向左移动

判断小鸟和障碍物的碰撞

障碍物移动出左边界后,在右边重新出现

加入记分模块

加入开始界面、结束界面

加入背景音乐

分阶段编写实现上述10个模块。

首先,由于我需要设置图形界面,所以调用了VC6.0里头对窗口句柄属性操作的函数,实现对窗口句柄属性的修改,这里由于游戏简单,仅修改了窗口名字,下面贴代码:

// 获取窗口句柄

HWND hwnd=GetHWnd();

// 设置窗口标题文字

SetWindowText(hwnd,"大峰子的Flappy bird!");

而后便是游戏窗口的设置,这里为了尽最大限度地复刻移动端,给玩家带来熟悉的感觉,我初始化成了350X600,大概是6寸的手机屏幕大小。这一步的实现是:

initgraph(350,600);

之后,需明确游戏的两个对象,鸟,管道;

由于小鸟的属性本质是取其需打印位置的左上角坐标(X’, Y’),然后通过库函数

loadimage();

putimage();

将准备好的图片素材输出到该位置上,这样小鸟就呈现在了屏幕上,所以我们需要定义两个全局变量bird_x、bird_y去实现存储小鸟坐标的功能。

之前提到,本游戏主要是基于C语言graphics.h中各类绘图库函数实现的,所以要定义IMAGE对象,代码说话:

IMAGE background,bird1[4],bird2[4],scole1[10],scole2[10],stone_up1,stone_up2,stone_down1,stone_down2,stone_up3,stone_up4,stone_down3,stone_down4;

以便于后面的loadimage和putimage这一系列操作。

随后,便是各个功能模块的技术实现了,我简述一下我的技术实现:

背景图片的显示。这个比较简单,定左上角为(0,0)点,只要使用函数putimage()就能实现该模块

加入小鸟图片。首先我们观察游戏会发现,该游戏中小鸟只会上下移动,并不会左右移动,造成小鸟向前飞的错觉是管道相对于小鸟的相对位移造成的,因此,我们只需要putimage到(150,300)即屏幕中央偏左的位置即可。另外,这里有一个小技术实现,就是三光栅操作,使得位图能透明显示。其原理是XOR,即异步运算,掩码图XOR精灵图=能透明显示到背景图上的位图。

举个例子:

a459a114ff5f320a4ef62a9b2ef9e208.png

2b303466b4e8daf0910582e23964d2be.png

黑XOR黑=原颜色。通过XOR运算将两张图像先后重叠打印,就能够实现图像的显示而不造成图像闪烁现象。

加入静态的障碍物管道。这个原理与2是一致的。不再过度阐述。

开始时播放背景音乐。这里需要调用媒体播放API,双线程进行,不然就会造成“播放.wav时控制台黑屏”的现象。这里用到的是头文件windows.h下的库函数Playsound,下面贴代码:

PlaySound("000.wav",NULL,SND_FILENAME|SND_ASYNC|SND_LOOP);

通过这段代码,实现多线程、循环播放。此外实现该功能需要添加WINMM.lib到project当中。

加入封面、结束界面。封面的加入较为简单,制作一个350X600的图片,在开始时putimage,并利用getch函数实现停顿直至键盘输入。结束界面的“GAME OVER”图像,显示方法如上述描述的一样,不再过多阐述。

小鸟的自动下落,键盘输入空格or鼠标左键时上升。首先,自动下落可以通过循环解决,每一次循环都进行一次按键检测 if(kbhit()),若按下空格键or鼠标左键,bird_y减小,小鸟图像打印时将上移,造成一种小鸟向上飞跃的感觉,若没有按按键,则bird_y+=3,缓慢下降。

障碍物向左移动。这个操作是在自定义函数printstone中实现的。关键点在于游戏一开始时柱子的初始化、柱子的随机长度、及柱子移动到屏幕左边框后右侧柱子重新出现…这三种情况的技术实现。

柱子的随机长度怎么设置呢?需要用rand函数,其位于stdlib.h中,用rand()%310-550,将得到的数值赋给上方的柱子坐标stone_y,保持x不变,y-750,就得到了下柱子的位置坐标,再putimage()即可。

为了让每一次游戏时管道间的间距位置都不一致,我使用了srand随机种子,由于随机种子函数值决定了rand()得到的数字序列,所以可以利用时间的多样性实现随机种子的多样性,下面贴代码:

srand((unsigned)time(NULL));

这样每次rand();得到的数字都是不定的,达到伪随机的效果。

如何实现柱子的左移呢?在printstone中添加stone_x— 这一行,这样每次while循环就能实现柱子的左移。

如何才能在一开始游戏时只出现一个柱子呢?需把stone_x2赋一个极小值,让putimage();到350*600的屏幕之外即可。

同理,每次循环检测柱子坐标变量stone_x的值是否等于0,等于0的话,将stone_x重新赋值为350即可。

碰撞判断模块。我自定义了一个judgement();进行判断,如果鸟和管道的素材重叠,就判断游戏失败了,执行endorretry();。由于我的bird图像素材是34X24,所以区间就是stone_y+-24,同时要考虑管道的素材是140*600,首先考虑碰撞上界,上界即是与上管道重叠,因此有以下代码实现:

if((stone_x1>10&&stone_x1<20)||(stone_x1>174&&stone_x1<184))

if((bird_y>(stone_y1+576)&&bird_y(stone_y1+726))&&bird_y

同时,掉出下界也需要判断,下界分为与下管道重叠,与窗口下边缘重叠,所以有了以下的代码实现:

elseif(stone_x1>=20&&stone_x1<=174)

if(!(bird_y>(stone_y1+600)&&bird_y

if(bird_y>576)

// 判断结果为ture后,即进入endorretry();或者main while(1)主循环

计分模块。当stone_x==150时,scole++,即柱子过屏幕一半的位置时,默认小鸟通过了柱子。当碰撞后,初始化,即执行endorretry();,scole=0,计分归零。

暂停模块。比较简单,键盘检测鼠标右键、Esc键,即在bird函数中检测键盘输入是否等于27(ASCII码对应Esc键),或者是否等于’ ’(对应空格),然后再使用getch();函数停顿即可。

游戏失败后的初始化模块。当 judgement();中判断成功并进入endorretry();,将打印Game Over图像并初始化。技术实现上,需要消除图像闪烁问题,这里需要用到BeginBatchDraw();和EndBatchDraw();批量绘图函数来消除Sleep();函数造成的闪烁问题。

功能函数的调用关系图

84138a6aacb335d985cdaa85783ec0c7.png

各功能函数的数据流程图

f2ffbe14a23365c6d36581067e6051b0.png

五、测试数据及运行结果

1e863706b0f9e2e5889f370d84cdabbf.png

bd5f389d62ffc4bd9f5c073d8bdc4638.png

674efc58ad43bf028bf9b8f319c6ff57.png

六、调试情况,设计技巧及体会

6.1 调试改进

像素小鸟翅膀的扇动

cc56aa876e26f5c4b7a7d7dbc64953a3.png

改进办法:当bird_y上升/下降时,利用IMAGE数组控制输出不同类型的图案。

像素小鸟位移感严重,跳跃不顺畅

改进办法:按键检测到空格键or鼠标左键时,将bird_y-=80调整至bird_y-=40,减小相对位移的长度。

柱子移动偏慢

改进办法:多设置一个难度模块,通过改变柱子移动速度达到难度的改变,例如定义全局变量n,将stone_x—修改为stone_x=stone_x-n,然后通过scanf(“%d”,&n);去控制每次循环时柱子向左移动的位移即可。

缺乏最高分模块,记录玩家最高分

改进办法:后续加入该模块。

6.2 体会

通过这次C语言课程设计,让我很好地掌握了C语言数据类型的使用,学会了用结构化、模块化的思想去编写程序,增强程序的健壮性,可读性,同时增强了对于添加并引用lib的熟练度,让程序功能更好地达到目的。同时增强了个人对计算机、程序编写的自信心,有利于未来的职业发展,衷心地感谢任课老师的指导与栽培。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值