Flappy Bird游戏 C语言实现
Posted 丶chuchu丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flappy Bird游戏 C语言实现相关的知识,希望对你有一定的参考价值。
目录
大家是否玩过上面这款游戏呢?想要自己做出来并不难,跟着我来用手吧。
(参考童晶老师的《C和C++游戏趣味编程》)
一、准备工作
编译器使用VS2019,但需要下载一个图形库Easy—X。
由于此图形库是C++的,所以我们要以C++文件来进行编写,C++文件内也可以使用C语言。
EasyX 下载地址https://easyx.cn/
怎样安装 EasyX? - EasyXhttps://easyx.cn/setup#:~:text=1.%20%E5%8F%8C%E5%87%BB%E4%B8%8B%E8%BD%BD%E7%9A%84%20EasyX%20%E5%AE%89%E8%A3%85%E5%8C%85%EF%BC%8C%E5%9C%A8%E2%80%9CWindows%20%E5%B7%B2%E4%BF%9D%E6%8A%A4%E4%BD%A0%E7%9A%84%E7%94%B5%E8%84%91%E2%80%9D%E6%8F%90%E7%A4%BA%E7%AA%97%E4%B8%AD%EF%BC%8C%E7%82%B9%E2%80%9C%E6%9B%B4%E5%A4%9A%E4%BF%A1%E6%81%AF%E2%80%9D%EF%BC%8C%E5%86%8D%E7%82%B9%E2%80%9C%E4%BB%8D%E8%A6%81%E8%BF%90%E8%A1%8C%E2%80%9D%EF%BC%8C%E8%BF%99%E6%97%B6%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%20EasyX%20%E7%9A%84%E5%AE%89%E8%A3%85%E7%A8%8B%E5%BA%8F%E3%80%82%202.,EasyX%20%E5%AE%89%E8%A3%85%E7%A8%8B%E5%BA%8F%E4%BC%9A%E6%A3%80%E6%B5%8B%E5%88%B0%E5%BD%93%E5%89%8D%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E5%AE%89%E8%A3%85%E7%9A%84%20Visual%20Studio%20%E7%89%88%E6%9C%AC%E3%80%82%20%E5%9C%A8%E5%AF%B9%E5%BA%94%E7%9A%84%20VS%20%E7%89%88%E6%9C%AC%E5%8F%B3%E4%BE%A7%E7%82%B9%E5%87%BB%E2%80%9C%E5%AE%89%E8%A3%85%E2%80%9D%E5%8D%B3%E5%8F%AF%E3%80%82
二、初识图形化界面
先来做一个窗口
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
int main()
{
initgraph(600, 600);
_getch();
closegraph();
return 0;
}
可能很多函数、头文件不认识。记住这样用就行,不理解没关系。
这样我们就创建了一个600×600的图形界面。
接下来创建一个小球
#define _CRT_SECURE_NO_WARNINGS 1
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
int main()
{
initgraph(600, 600);
fillcircle(300,300,100);
_getch();
closegraph();
return 0;
}
我们运用fillcircle( )函数,第一个值参数是X坐标,第二个参数是Y坐标,第三个参数是半径。
这里讲解一下横纵坐标的定义:
接下来创建一个矩形
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
int main()
{
initgraph(600, 600);
fillrectangle(200,0,400,400);
_getch();
closegraph();
return 0;
}
我们使用fillrectangle( )函数,前两个参数是矩形左上角坐标,后两个参数是矩形右下角坐标。
三、设置参数
有了上面基础,下面我们一步一步来做。
首先我们要选定好我们窗口大小、小球大小以及方块障碍物大小。
我们想要小球动起来,需要给他初速度与重力加速度,方块同理。
在平面上就可以理解为它们的横纵坐标移动。
我们先设置基本参数,详情见注释
float w, h, g;//游戏画面宽高与重力加速度
float ball_x, ball_y, ball_vy, r;//小球圆心坐标,y方向速度和半径
float rect1_x1, rect1_y1, rect1_x2, rect1_y2, rect1_vx;//上方块的横纵坐标
//因为画面向左移动,我们只要让方块向左移就可以实现,所以需要x方向速度
float rect2_x1, rect2_y1, rect2_x2, rect2_y2, rect2_vx;//下方块的横纵坐标
float rect_h = 130;//因为随机方块高度的需要,单独设置一个高度
int score;//得分
再给参数赋值
//下面给具体参数
w = 600;
h = 400;
g = 0.6;
initgraph(w, h);//创建一个窗口
//小球参数
r = 20;
ball_x = w / 4;//让小球在画面左边1/4处
ball_y = h - r;//让小球贴地,离地面一个半径距离
ball_vy = 0;
//上方块参数
rect1_x1 = w * 3 / 4;//方块在画面3/4处
rect1_y1 = 0;//上方块左上角y坐标为0
rect1_x2 = rect1_x1 + 30;//+30就是指宽度为30
rect1_y2 = rect1_y1 + rect_h;//高度为130
//下方块参数
rect2_x1 = w * 3 / 4;
rect2_y1 = h - rect_h;//下方块的左上角y坐标离右下角差一个高度
rect2_x2 = rect2_x1 + 30;
rect2_y2 = h;//下方块贴地
//速度
rect1_vx = rect2_vx = -3;
最后我们来看一下效果
fillcircle(ball_x, ball_y, r);
fillrectangle(rect1_x1, rect1_y1, rect1_x2, rect1_y2);
fillrectangle(rect2_x1, rect2_y1, rect2_x2, rect2_y2);
_getch();
closegraph();
四、设置速度
小球的运动
画面一直在动,就需要循环。接下来的我们就放在一个死循环里进行。
首先我们先让小球动起来,用_kbhit() 来收集按键,_getch()接收,如代码:
while (1)
{
if(_kbhit())//当按键时
{
char input = _getch();//获得输入字符
if (input == ' ')//按下空格时
{
ball_vy = -15;//给小球一个向上的初速度
}
}
}
有了速度不够,速度要换成路程才行,平面上体现为小球的坐标更新。
当小球落到地面时,我们把速度变为0,并且纵坐标变为h - r就能实现小球在地面上。
现在我们来看下效果。
while (1)
{
//当摁下空格,小球向上跳跃,给一个反向速度
if(_kbhit())
{
char input = _getch();
if (input == ' ')
{
ball_vy = -17;
}
}
if (ball_y >= h - r)//当小球落到地面时
{
ball_vy = 0;//速度变为0
ball_y = h - r;//规范其y坐标,防止落到地面下。
}
ball_vy = ball_vy + g;//y方向初速度为0,再加上一个重力加速度
ball_y = ball_y + ball_vy;//根据小球y方向速度更新y坐标
cleardevice();//在每次循环清一次屏,不然会出现小球的轨迹
fillcircle(ball_x, ball_y, r);
fillrectangle(rect1_x1, rect1_y1, rect1_x2, rect1_y2);
fillrectangle(rect2_x1, rect2_y1, rect2_x2, rect2_y2);
Sleep(10);//让小球暂停10ms,不然小球一眨眼就没了
}
closegraph();
画面的运动
画面的运动可以看作方块向左移,那么我们就要给方块的x坐标更新。
rect1_x1 = rect1_x1 + rect_vx;
rect2_x1 = rect2_x1 + rect_vx;
但是方块到了最左边,我们还需要让它出现在右边,并且此时得分+1。
重新出现的方块我们需要一个新的随机高度,增加趣味性。
别忘了把方块左移速度提升上去,增加游戏难度。
//更新两个方块的位置坐标
rect1_x1 += rect_vx;
rect1_x2 += rect_vx;
rect2_x1 += rect_vx;
rect2_x2 += rect_vx;
if (rect1_x1 <= 0 && rect2_x1 <= 0)//方块来到最左边
{
//让他们出现在最右侧
rect1_x1 = rect2_x1 = w - 30;
rect1_x2 = rect2_x2 = w;
score += 1;//得分+1
rect_h = rand() % int(h / 4) + h / 4;//设置随即高度,高度不超过画面的1/4
//设置随即高度
rect2_y1 = h - rect_h;
rect1_y2 = rect_h;
if (score > 0)
rect_vx -= 0.1;//如果速度一直大于0,左移速度加大。当得分为0速度还原。
}
看一下效果:
这里我的参数有些不合理,大家可以自行更改,原理就是这样。
判断输赢
如果碰到方块的边缘,那么得分变为0,速度还原。否则继续。
这里是六种死法,所以我们需要六个条件判断。
if (((ball_x + r >= rect2_x1)
&&(ball_y + r >= h - rect_h)
&&(ball_x - r <= rect2_x2))//碰到下方块
||((ball_x + r >= rect1_x1)
&&(ball_y - r <= rect_h)
&&(ball_x - r <= rect1_x2))//碰到上方块
)
{
Sleep(100);//给个慢速回放,看看怎么死的
score = 0;//得分归0
}
结尾咱给来一份打印成绩,代码如下,暂且了解就行:
TCHAR s[20];
_stprintf(s, _T("%d"), score);
settextstyle(40, 0, _T("宋体"));
outtextxy(50, 30, s);
五、完整代码
以下是自己选了合适的参数,并添加了一些元素。
大家也可以参照自行修改。
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
float w, h, g;//游戏画面宽高与重力加速度
float ball_x, ball_y, ball_vy, r;//小球圆心坐标,y方向速度和半径
float rect1_x1, rect1_y1, rect1_x2, rect1_y2, rect_vx;//上方块的横纵坐标
//因为画面向左移动,我们只要让方块向左移就可以实现,所以需要x方向速度
float rect2_x1, rect2_y1, rect2_x2, rect2_y2;//下方块的横纵坐标
float rect_h = 125;//因为随机方块高度的需要,单独设置一个高度
int score = 0;//得分
//下面给具体参数
w = 600;
h = 400;
g = 0.4;
initgraph(w, h);//创建一个窗口
//小球参数
r = 18;
ball_x = w / 4;//让小球在画面左边1/4处
ball_y = h - r;//让小球贴地,离地面一个半径距离
ball_vy = 0;
//上方块参数
rect1_x1 = w * 3 / 4;//方块在画面3/4处
rect1_y1 = 0;//上方块左上角y坐标为0
rect1_x2 = rect1_x1 + 30;//+30就是指宽度为30
rect1_y2 = rect1_y1 + rect_h;//高度为130
//下方块参数
rect2_x1 = w * 3 / 4;
rect2_y1 = h - rect_h;//下方块的左上角y坐标离右下角差一个高度
rect2_x2 = rect2_x1 + 30;
rect2_y2 = h;//下方块贴地
//速度
rect_vx = -2.5;
while (1)
{
//当摁下空格,小球向上跳跃,给一个反向速度
if(_kbhit())
{
char input = _getch();
if (input == ' ')
{
ball_vy = -8;
}
}
ball_vy = ball_vy + g;//y方向初速度为0,再加上一个重力加速度
ball_y = ball_y + ball_vy;//根据小球y方向速度更新y坐标
if (ball_y >= h - r)
{
ball_vy = 0;
ball_y = h - r;
}
//更新两个方块的位置坐标
rect1_x1 += rect_vx;
rect1_x2 += rect_vx;
rect2_x1 += rect_vx;
rect2_x2 += rect_vx;
if (rect1_x1 <= 0 && rect2_x1 <= 0)//方块来到最左边
{
//让他们出现在最右侧
rect1_x1 = rect2_x1 = w - 30;
rect1_x2 = rect2_x2 = w;
score += 1;//得分+1
rect_h = rand() % int(h / 5.5) + h / 5.5;//设置随即高度
rect1_y2 = rect_h;
rect2_y1 = h - rect_h;
if (score > 0)
rect_vx -= 0.1;//如果速度一直大于0,左移速度加大。
}
if (((ball_x + r >= rect2_x1)
&&(ball_y + r >= h - rect_h)
&&(ball_x - r <= rect2_x2))//碰到下方块
||((ball_x + r >= rect1_x1)
&&(ball_y - r <= rect_h)
&&(ball_x - r <= rect1_x2))//碰到上方块
||(ball_y + r >= h - 10)//碰到底部
)
{
Sleep(100);//给个慢速回放,看看怎么死的
score = 0;//得分归0
rect_vx = -3;//碰到就速度还原
}
if (ball_y - r <= 10)//如果碰到顶部,直接回到底部,分数为0
{
ball_vy += 100 * g;
ball_y += ball_vy;
score = 0;
}
cleardevice();
//绘制小球
setfillcolor(GREEN);//填上绿色
fillcircle(ball_x, ball_y - 10, r);
//绘制方块
setfillcolor(BROWN);//填上棕色
fillrectangle(rect1_x1, rect1_y1, rect1_x2, rect1_y2);
fillrectangle(rect2_x1, rect2_y1, rect2_x2, rect2_y2);
setfillcolor(RED);
fillrectangle(0, 0, w, 10);
fillrectangle(0, h - 10, w, h);
//打印分数
TCHAR s[20];
_stprintf(s, _T("%d"), score);
settextstyle(40, 0, _T("宋体"));
outtextxy(50, 30, s);
Sleep(10);
}
closegraph();
return 0;
}
如果你能看到这,希望对您有所帮助,我会继续写一些有趣的游戏,欢迎关注。
以上是关于Flappy Bird游戏 C语言实现的主要内容,如果未能解决你的问题,请参考以下文章