flappy+bird+c语言程序,C语言版flappy_bird实现
一、实验说明
1. 环境介绍
本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序:
LX终端(LXTerminal):Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令。
GVim
2.环境使用
使用GVim编辑器输入实验所需的代码及文件,使用LX终端(LXTerminal)运行所需命令进行操作。 完成实验后可以点击桌面上方的“实验截图”保存并分享实验结果到微博,向好友展示自己的学习进度。实验楼提供后台系统截图,可以真实有效证明您已经完成了实验。 实验记录页面可以在“我的主页”中查看,其中含有每次实验的截图及笔记,以及每次实验的有效学习时间(指的是在实验桌面内操作的时间,如果没有操作,系统会记录为发呆时间)。这些都是您学习的真实性证明。 本课程中的所有源码可以通过以下方式下载:
二、项目介绍
这次我们的项目是flappy bird游戏,这次,准备好砸你的键盘吧。最终效果图是这样的
三、项目实战
1. 基础知识
我们的项目用到了一点数据结构的知识,还涉及到了linux的一些系统调用,有助于我们加深对linux下的程序设计的深入理解。此外,我们还用了一个文本界面的屏幕绘图库ncurses,编译时需要加上-lcurses选项。
1.1.安装ncurses库
在终端输入sudo apt-get install libncurses5-dev
2. 设计思路
我们的flappy bird游戏里最关键的两点就是响应键盘输入和定时绘图。这就需要结合linux提供的系统函数和我们使用的ncurses库来完成了。另一个问题是如何使bird能看起来像是在向前飞一样,如果一直移动bird势必会超出屏幕范围。我们不妨反过来想,让bird一直保持在原地,而让背景一直向bird的方向移动。这样,就造成了好像bird一直向前移动的效果。
3. 开始动手
让我们先来完成一些基础工作,因为我们是终端字符界面,所以一切离不开ASCII字符,我们需要定义一些常量。我们用'*'来表示背景里的柱子,用'O'来表示bird。好了,代码如下:
include
include
include
include
define CHAR_BIRD 'O'
define CHAR_STONE '*'
define CHAR_BLANK ' '
背景上的柱子用链表结构表示,定义为结构体如下:
typedef struct node {
int x, y;
struct node *next;
}node, *Node;
还需要几个全局变量:
Node head, tail;
int bird_x, bird_y;
int ticker;
为了调用起来方便,我们先声明一下我们定义的函数:
void init();
void init_bird();
void init_draw();
void init_head();
void init_wall();
void drop(int sig);
int set_ticker(int n);
4. 定时问题
现在我们来解决如何让背景定时移动的问题。linux系统为我们提供了信号这一概念,可以解决我们的问题。不知道什么是信号?没关系,说白了就是linux内核有个定时器,它每隔一段时间就会向我们的程序发送一个信号,我们的信号接收函数就会被自动执行,我们只要在接受信号的函数里移动背景就行了。因为是内核发送的信号,所以不会因为我们的键盘接受阻塞而阻塞。怎么样,是不是很简单?下面就来写我们的代码:
int set_ticker(int n_msec)
{
struct itimerval timeset;
long n_sec, n_usec;
n_sec = n_msec / 1000;
n_usec = (n_msec % 1000) * 1000L;
timeset.it_interval.tv_sec = n_sec;
timeset.it_interval.tv_usec = n_usec;
timeset.it_value.tv_sec = n_sec;
timeset.it_value.tv_usec = n_usec;
return setitimer(ITIMER_REAL, ×et, NULL);
}
以上代码用来设定内核的定时周期,下面是我们的信号接受函数:
void drop(int sig)
{
int j;
Node tmp, p;
//draw bird
move(bird_y, bird_x);
addch(CHAR_BLANK);
refresh();
bird_y++;
move(bird_y, bird_x);
addch(CHAR_BIRD);
refresh();
if((char)inch() == CHAR_STONE) {
set_ticker(0);
sleep(1);
endwin();
exit(0);
}
//first wall out of screen?
p = head->next;
if(p->x < 0) {
head->next = p->next;
free(p);
tmp = malloc(sizeof(node));
tmp->x = 99;
do {
tmp->y = rand() % 16;
} while(tmp->y < 5);
tail->next = tmp;
tmp->next = NULL;
tail = tmp;
ticker -= 10; //speed up!
set_ticker(ticker);
}
//draw new walls
for(p = head->next; p->next != NULL; p->x--, p = p->next) {
for(j = 0; j < p->y; j++) {
move(j, p->x);
addch(CHAR_BLANK);
refresh();
}
for(j = p->y+5; j <= 23; j++) {
move(j, p->x);
addch(CHAR_BLANK);
refresh();
}
if(p->x-10 >= 0 && p->x < 80) {
for(j = 0; j < p->y; j++) {
move(j, p->x-10);
addch(CHAR_STONE);
refresh();
}
for(j = p->y + 5; j <= 23; j++) {
move(j, p->x-10);
addch(CHAR_STONE);
refresh();
}
}
}
tail->x--;
}
我们在信号接受函数里将背景向前移动一列,并且让bird向下掉落一行,而且要检测bird是否撞到柱子,是的话game就over了。
5. main函数
先看看代码:
int main()
{
char ch;
init();
while(1) {
ch = getch();
if(ch == ' ' || ch == 'w' || ch == 'W') {
move(bird_y, bird_x);
addch(CHAR_BLANK);
refresh();
bird_y--;
bird_y--;
move(bird_y, bird_x);
addch(CHAR_BIRD);
refresh();
if((char)inch() == CHAR_STONE) {
set_ticker(0);
sleep(1);
endwin();
exit(0);
}
}
else if(ch == 'z' || ch == 'Z') {
set_ticker(0);
do {
ch = getch();
} while(ch != 'z' && ch != 'Z');
set_ticker(ticker);
}
else if(ch == 'q' || ch == 'Q') {
sleep(1);
endwin();
exit(0);
}
}
return 0;
}
我们在main里先做好初始化,然后在循环中接受键盘输入。如果是w或空格键被按下,我们的bird就向上飞两行,如果是q被按下就退出游戏,z被按下游戏则会暂停。 下面看一下init函数:
void init()
{
initscr();
cbreak();
noecho();
curs_set(0);
srand(time(0));
signal(SIGALRM, drop);
init_bird();
init_head();
init_wall();
init_draw();
sleep(1);
ticker = 500;
set_ticker(ticker);
}
init函数首先初始化屏幕,调用了ncurses提供的函数,然后调用各个子函数进行初始化。注意,我们安装了信号接收函数drop,并且设定了定时时间。各个初始化子函数如下。 初始化bird位置:
void init_bird(){
bird_x = 5;
bird_y = 15;
move(bird_y, bird_x);
addch(CHAR_BIRD);
refresh();
sleep(1);
}
初始化背景里的柱子链表结构:
void init_head() //with header{
Node tmp;
tmp = malloc(sizeof(node));
tmp->next = NULL;
head = tmp;
tail = head;
}
void init_wall(){
int i;
Node tmp, p;
p = head;
for(i = 19; i <= 99; i += 20) {
tmp = malloc(sizeof(node));
tmp->x = i;
do {
tmp->y = rand() % 16;
}while(tmp->y < 5);
p->next = tmp;
tmp->next = NULL;
p = tmp;
}
tail = p;
}
初始化屏幕:
void init_draw()
{
Node p;
int i, j;
for(p = head->next; p->next != NULL; p = p->next) {
for(i = p->x; i > p->x-10; i--) {
for(j = 0; j < p->y; j++) {
move(j, i);
addch(CHAR_STONE);
refresh();
}
for(j = p->y+5; j <= 23; j++) {
move(j, i);
addch(CHAR_STONE);
refresh();
}
}
sleep(1);
}
}
6. 编译
gcc flappy_bird.c -o flappy_bird -lcurses
到此,我们的flappy_bird游戏就完成了
flappy+bird+c语言程序,C语言版flappy_bird实现相关推荐
- 打豆豆游戏c语言编程,C语言程序打豆豆(函数版)分享!
[项目] 设计一个程序,能重复地在显示下面的信息: 根据用户输入的选项,输出一句提示性的话语(将来会对应实现某个功能).输入0,则退出. 要求将各功能定义专门的函数. 参考解答: #include # ...
- flappy+bird+c语言程序,C语言实现flappy bird游戏
本文实例为大家分享了C语言实现flappy bird的具体代码,供大家参考,具体内容如下 #include #include #include //定义全局变量 int high,width; //边 ...
- 棱形旋转c语言程序_C 语言时隔 5 年重回巅峰,这 20 个热门项目拿去练手!
在上个月的 TIOBE 编程语言排名中,C 语言和 Java 的差距只有 0.01%.在近日 TIOBE 公布的 2020 年 5 月编程语言排行榜中,C 语言成功超越了 Java,重返第一的王者宝座 ...
- 蜂鸣器发出7种音阶c语言程序_C语言编程新思路
第一章 单元测试 1.单选题: 关于一个C语言程序执行的起点和终点,以下选项正确的是 ( ). 选项: A: main 任意 B: main 最后一个 C: main main D: 第一个 最后一个 ...
- 文件的记录c语言程序,c语言程序学生籍贯信息记录簿设计.docx
c 语言程序学生籍贯信息记录簿设计 学生籍贯信息记录簿 课程设计报告书 班 级: 方 0909-1 学 号:姓 名: 苑 小 叶 指导教师 : 康 亚 男 石家庄铁道大学四方学院 2010年 07月 ...
- 学生实验平台搭建c语言程序,c语言程序设计实验学生用.doc
c语言程序设计实验学生用 C语言程序设计 实验指导 (学生用) 计算机基础教研室 <C语言程序设计>课程组 2012年9月 前 言 <C语言程序设计>是计算机科学技术系面向全校 ...
- 插入法排序c语言程序,C语言之插入排序算法
一.什么是直接插入算法? 直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的纪录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的纪录插入完为止,得到一个新的有序序列. 选择 ...
- 青花瓷音乐的单片机c语言程序,c语言曲谱_单片机c语言音乐简谱代码
51单片机曲谱编写音乐程序,我看不懂曲谱,谁能教下我! //<世上只有妈妈好>51单片机C语言程序和音乐采灯程序 //此程序在硬件上调试通过 //本程序的单片机晶振采用11.0592MHZ ...
- 框图c语言程序,C语言程序设计框图
<C语言程序设计框图>由会员分享,可在线阅读,更多相关<C语言程序设计框图(86页珍藏版)>请在人人文库网上搜索. 1.第三章控制结构,返回总目录,目录,3.1节目结构框,3. ...
- 简单谱子C语言程序,c语言曲谱_单片机c语言音乐简谱代码
51单片机曲谱编写音乐程序,我看不懂曲谱,谁能教下我! //<世上只有妈妈好>51单片机C语言程序和音乐采灯程序 //此程序在硬件上调试通过 //本程序的单片机晶振采用11.0592MHZ ...
最新文章
- PMAC上位机编程基础1---编程环境配置
- oracle db file sequential read,db file sequential read等待事件
- java 二进制文件拷贝_Java复制二进制文件
- 半导体重磅!英飞凌宣布100亿美元收购赛普拉斯
- jquery监听html状态,jquery监听页面刷新
- 单片机c语言串转并的IO实验,74LS164 串入并出实验
- json文件简介及借助于python解析json文件
- mysql 百万级数据库优化方案
- USBkey结合win7实现登陆验证
- cleaned_data debug django
- 小程序服务器获取appid,微信小程序小程序appid如何获取
- 如何建立一个小型的局域网,来实现电脑与电脑之间的通信
- WAP1.0 前端开发经验(转)
- 基于关联规则与可平面图的商品摆放规划-----实验报告
- [NLP论文阅读] Discourse-Based Objectives for Fast Unsupervised Sentence Representation Learning
- 一个屌丝程序猿的人生(九十九)
- 《码农翻身》读后感---程序员的潜规则
- 使用python实现正态分布检验
- 堆内存、栈内存、方法区
- 【ABAP】MFBF过账到质量检验库存类型Demo
热门文章
- 关于Python中rank()函数的理解
- c语言极限,C语言问题合集
- MPSK 通信系统的 Monte Carlo 仿真
- 微信自动回复的智能聊天机器人怎么做?
- HLS、Smooth Streaming、HDS和Dash
- mysql win10 优化设置_Win10电脑优化必做的几个优化技巧提升速度!
- [Inception V1]赫布学习理论(Hebbian theory)
- Adidas商品上货监控,有货时提醒商品尺码
- 2017年总结,2018新开始
- 苹果手机白屏_为什么安卓用久了会卡顿,苹果用久了会闪退?看完长知识了