Linux实现Flappy bird项目

目录

1、项目介绍

2、功能总结

3、前期准备

3.1 Ncurses库 

3.2 信号机制 

3.2.1 设置信号响应方式

3.2.2 设置定时器 

4、代码实现 

4.1 头文件引用及变量、函数定义

4.2 主函数

4.3 curses初始化 

4.4 设置定时器

4.5 定时器响应函数 

4.6 小鸟控制相关函数

4.7 管道控制相关函数 

5、效果测试


1、项目介绍

flappy bird是一款来自越南的独立游戏开发者Dong Nguyen所开发的作品游戏中玩家必须控制一只小鸟,跨越由各种不同长度水管所组成的障碍。

2、功能总结

  1. 按下空格键小鸟上升,不按小鸟下落
  2. 搭建小鸟需要穿过的管道
  3. 管道自动左移和创建
  4. 小鸟撞到管道游戏结束

3、前期准备

3.1 Ncurses库 

做这个项目之前,有两个值得思考:

  1. 如何显示游戏界面?
  2. 如何实现空格键控制小鸟上升?

我们可以通过Ncurses库来实现

Ncurses是最早的System V Release 4.0 (SVr4)中 curses的一个克隆和升级。

这是一个可自由配置的库,完全兼容旧版本curses。Ncurses构成了一个工作在底层终端代码之上的封装,并向用户提供了一个灵活高效的API(Application Programming Interface 应用程序接口)。它提供了创建窗口界面,移动光标,产生颜色,处理键盘按键等功能。使程序员编写应用程序不需要关心那些底层的终端操作。

简而言之,它是一个管理应用程序在字符终端显示的函数库。 

安装命令:

sudo apt-get install libncurses5-dev

注:为了能够使用Ncurses库,必须在源程序中将#include<curses.h>包括进来,而且在编译的需要与它链接起来. 在gcc中可以使用参数-lncurses进行编译.

initscr(void);是curses模式的入口。将终端屏幕初始化为curses模式,为当前屏幕和相关的数据结构分配内存。
int  endwin(void); 是curses模式的出口,退出curses模式,释放curses子系统和相关数据结构占用的内存。
int curs_set(int visibility); 设置光标是否可见,visibility:0(不可见),1(可见)
int move(int  new_y, int  new_x);将光标移动到new_y所指定的行和new_x所指定的列
int addch(const  chtype  char); 在当前光标位置添加字符
int  refresh(void); 刷新物理屏幕。将获取的内容显示到显示器上。    
int  keypad(WINDOW  *window_ptr,  bool  key_on); 允许使用功能键。exp:keypad(stdscr,1);//允许使用功能按键
 int getch(void);  读取键盘输入的一个字符
chtype inch(void); 获取当前光标位置的字符。
    注:curses有自己的字符类型chtype,使用时强制类型转换为char
int start_color(void); 启动color机制,初始化当前终端支持的所有颜色
int init_pair(short  pair_number,  short  foreground,  short  background);配置颜色对        
    COLOR_BLACK         黑色        COLOR_MAGENTA      品红色
    COLOR_RED           红色        COLOR_CYAN          青色
    COLOR_GREEN         绿色        COLOR_WHITE      白色
    COLOR_YELLOW     黄色       COLOR_BLUE       蓝色
int  COLOR_PAIR(int  pair_number); 
 
 设置颜色属性,设置完颜色对,可以通过COLOR_PAIR实现
int  attron(chtype  attribute); 启用属性设置
int  attroff(chtype  attribute); 关闭属性设置

示例:

#include <stdio.h>
#include <curses.h>int main(int argc,const char* argv[])
{char ch;initscr();//进入curses模式curs_set(0);keypad(stdscr,1);//允许使用功能按键noecho();//禁止输入字符显示start_color();//启动颜色机制init_pair(1,COLOR_RED,COLOR_BLUE);attron(COLOR_PAIR(1));move(10,10);addch('@');refresh();attroff(COLOR_PAIR(1));while(1);endwin();//退出curses模式return 0;
}

3.2 信号机制 

获取空格按键是可以通过getchar阻塞获取字符按键输入,但是这样做就会影响小鸟的下落和管道的创建。在Linux中,软中断信号(signal,简称为信号)是在软件层次上对中断的一种模拟,用来通知进程发生了异步事件。内核可以因为内部事件而给进程发送信号,通知进程发生了某个事件。

信号响应的方式:

  • 忽略信号,即对信号不做任何处理;
  • 捕捉信号,即信号发生时执行用户自定义的信号处理函数。
  • 执行缺省操作,Linux对每种信号都规定了默认操作。

3.2.1 设置信号响应方式

#include  <unistd.h>
#include <signal.h>typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler); 

 成功时返回原先的信号处理函数,失败时返回SIG_ERR

  • signum:指明了所要处理的信号类型
  • handler:描述了与信号关联的动作,SIG_DFL代表缺省方式; SIG_IGN 代表忽略信号;指定的信号处理函数代表捕捉方式

示例 

// 头文件省略
void handler (int signo) {printf(“HELLO!\n”); 
}int  main() {signal(SIGINT, handler);while ( 1 ) ;return 0;
}

3.2.2 设置定时器 

struct itimerval {struct timeval it_interval; /* 计时器重新启动的间歇值 */struct timeval it_value;    /* 计时器安装后首次启动的初 };                               始值,之后就没有用 */
struct timeval {long tv_sec;       /* 秒 */long tv_usec;      /* 微妙*/
};
int setitimer(int which, const struct itimerval *value,struct itimerval *ovalue)

参数:

  • which:间歇计时器类型,ITIMER_REAL      //数值为0,发送的信号是SIGALRM。
  • struct itimerval *value:将value指向的结构体设为计时器的当前值;
  • struct itimerval *ovalue:保存计时器原有值。一般设置为NULL。

返回值: 成功返回0。失败返回-1。 

4、代码实现 

4.1 头文件引用及变量、函数定义

#include <stdio.h>
#include <curses.h>
#include <signal.h>
#include <sys/time.h>
#include <stdlib.h>#define BIRD '@'
#define BLANK ' '
#define PIPE '+'
/*定义关于管道的结构体*/
typedef struct Pipe{int x;//列坐标int y;//横坐标struct Pipe *next;
}Pipe_node, *Pipe_list;Pipe_list head,tail;void creat_list();//创建链表
void show_pipe();//显示管道
void clear_pipe();//清楚管道
void move_pipe();//移动管道int bird_y,bird_x;//小鸟坐标void show_bird();//显示小鸟
void clear_bird();//清除小鸟
void move_bird();//移动小鸟void init_curses();//curses库初始化
int set_timer(int ms_t);//设置定时器--ms
void handler(int sig);//信号处理函数

4.2 主函数

int main()
{bird_y = 15;//行bird_x = 10;//列init_curses();signal(SIGALRM,handler);set_timer(500);//500mssrand(time(0));//随机种子creat_list();show_pipe();show_bird();move_bird();return 0;
}

4.3 curses初始化 

void init_curses()
{initscr();//进入curses模式curs_set(0);//禁止光标显示noecho();//禁止输入字符显示keypad(stdscr,1);//启动功能按键start_color();//启动颜色机制init_pair(1,COLOR_WHITE,COLOR_RED);//小鸟颜色设置init_pair(2,COLOR_WHITE,COLOR_GREEN);//管道颜色设置
}

4.4 设置定时器


int set_timer(int ms_t)
{struct itimerval timer;long t_sec,t_usec;int ret;t_sec = ms_t / 1000;//st_usec = (ms_t % 1000)*1000;//ustimer.it_value.tv_sec = t_sec;timer.it_value.tv_usec = t_usec;//首次启动定时值timer.it_interval.tv_sec = t_sec;timer.it_interval.tv_usec = t_usec;//定时时间间隔ret = setitimer(ITIMER_REAL,&timer,NULL);//return ret;}

4.5 定时器响应函数 

void handler(int sig)
{Pipe_list p,new;//小鸟下落clear_bird();bird_y++;show_bird();/*游戏结束判断*/if((char)inch() == PIPE){set_timer(0);endwin();exit(1);}p = head->next;int i,j;if(p->x == 0){head->next = p->next;for(i=p->x;i<p->x+10;i++){//创建上半部分管道for(j=0;j<p->y;j++){move(j,i);addch(BLANK);}//创建下半部分管道for(j=p->y+5;j<25;j++){move(j,i);addch(BLANK);}refresh();}free(p);new = (Pipe_list)malloc(sizeof(Pipe_node));new->x = tail->x +20;new->y = rand() % 11 +5;new->next = NULL;tail->next = new;tail = new;}//管道移动clear_pipe();move_pipe();show_pipe();
}

4.6 小鸟控制相关函数

void show_bird()//显示小鸟
{attron(COLOR_PAIR(1));move(bird_y,bird_x);addch(BIRD);refresh();attroff(COLOR_PAIR(1));
}
void clear_bird()//清除小鸟
{move(bird_y,bird_x);addch(BLANK);refresh();}
void move_bird()//移动小鸟
{char key;while(1){key = getch();if(key == ' '){clear_bird();bird_y--;show_bird();/*游戏结束判断*/if((char)inch() == PIPE){set_timer(0);endwin();exit(1);}}}
}

4.7 管道控制相关函数 

void creat_list()//创建链表
{int i;Pipe_list p,new;head = (Pipe_list)malloc(sizeof(Pipe_node));head->next = NULL;p = head;for(i = 0;i<5;i++){new = (Pipe_list)malloc(sizeof(Pipe_node));new->x = (i+1)*20;new->y = rand()%11+5;//(5-15行)new->next = NULL;p->next = new;p = new;}tail = p;
}
void show_pipe()//显示管道
{Pipe_list p;int i,j;p = head->next;attron(COLOR_PAIR(2));while(p){for(i=p->x;i<p->x+10;i++){//创建上半部分管道for(j=0;j<p->y;j++){move(j,i);addch(PIPE);}//创建下半部分管道for(j=p->y+5;j<25;j++){move(j,i);addch(PIPE);}}refresh();p = p->next;}attroff(COLOR_PAIR(2));
}
void clear_pipe()//清除管道
{Pipe_list p;int i,j;p = head->next;while(p){for(i=p->x;i<p->x+10;i++){//创建上半部分管道for(j=0;j<p->y;j++){move(j,i);addch(BLANK);}//创建下半部分管道for(j=p->y+5;j<25;j++){move(j,i);addch(BLANK);}}refresh();p = p->next;}
}
void move_pipe()//移动管道
{Pipe_list p;p = head->next;while(p){p->x--;p = p->next;}
}

5、效果测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/674605.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何复制本地docker镜像到其他主机

&#xff08;1&#xff09;打包镜像 比如我要复制的镜像是grafana的镜像 docker images 这里我把打包的镜像放在了根~目录下&#xff0c;如截图所示&#xff1a; docker save grafana/grafana:latest -o ~/grafana.jar &#xff08;2&#xff09;移动镜像 scp命令拷贝镜像到目标…

【机器学习系统的构建】从模型开发的过程讲清楚K-Fold 交叉验证 (Cross-Validation)的原理和应用

0、前言 最近在学习集成学习的时候了解到了k折交叉验证&#xff0c;其实在之前学习吴恩达老师的课程中也学过交叉验证&#xff0c;但是当时也不是很明白。这次借着自己的疑问以及网上搜找资料&#xff0c;终于把交叉验证给弄明白了。 在弄清楚前&#xff0c;我有这样几个疑问…

【数据分享】2022年中国1km分辨率的河网密度数据(免费获取)

水系数据是我们在各项研究中经常使用的数据&#xff01;之前我们分享过一份来源于Open Street Map的2024年全国水系数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff01; 本次我们分享一份来源于Science Data Bank平台上的2022年中国1km分辨率的河网密度数据&am…

Amazon Q Business现已正式上市!利用生成式人工智能协助提高员工生产力

在 2023 年度 AWS re:Invent 大会上&#xff0c;我们预览了 Amazon Q Business&#xff0c;这是一款基于生成式人工智能的助手&#xff0c;可以根据企业系统中的数据和信息回答问题、提供摘要、生成内容额安全地完成任务。 借助 Amazon Q Business&#xff0c;您可以部署安全、…

Skywalking数据持久化与自定义链路追踪

学习本篇文章之前首先要了解一下Sky walking的基础知识 分布式链路追踪工具Skywalking详解 一&#xff0c;Sky walking数据持久化 Sky walking提供了es&#xff0c;MySQL等数据持久化方案&#xff0c;默认使用h2基于内存的数据库&#xff0c;重启之后数据即会丢失。 在实际工…

纹理映射技术在AI去衣应用中的关键作用

引言&#xff1a; 随着人工智能技术的飞速发展&#xff0c;其在图像处理领域中的应用也日益广泛。AI去衣&#xff0c;作为一种颇具争议的技术应用&#xff0c;指的是利用深度学习算法自动移除或替换图片中的衣物。在这一过程中&#xff0c;纹理映射技术扮演了不可或缺的角色。本…

python环境下labelImg图片标注工具的使用

labelimg GitHub地址 python环境下labelImg图片标注工具的使用 1. 写在开头2. 如何使用2.1安装2.2 启动2.2.1 先启动后设置标注的目录2.2.2 指定标注的目录和预设置的标签 2.3 设置自动保存和显示类别。2.4 保存文件类型2.5 [快捷键](https://github.com/HumanSignal/labelImg…

我独自升级崛起下载方法分享 下载教程

《我独自升级&#xff1a;崛起》这款精彩绝伦的动作角色扮演游戏&#xff0c;灵感来源于大热网络漫画&#xff0c;让玩家亲自踏上主角程肖宇的征途&#xff0c;从觉醒初阶到实力飞跃&#xff0c;每一步成长都扣人心弦。值得注意的是&#xff0c;尽管全球正式发布日期定在了五月…

每天五分钟计算机视觉:通过交并比判断对象检测算法的性能

本文重点 在对象检测领域,交并比(Intersection over Union,简称IoU)是衡量算法性能的重要指标之一。它不仅直观地反映了预测框与真实框之间的重叠程度,还是判断算法是否“运行良好”的关键依据。 那个定位是好的? 对象检测任务中,我们希望不仅检测到对象,同时我们还希…

重学SpringBoot3-SPI机制

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-SPI机制 什么是 SPI&#xff1f;Spring Boot 中的 SPI 机制spring.factories 文件自动配置的实现启动流程中的作用 SPI实际应用步骤 1: 新建模块步骤 2:…

瑞友天翼应用虚拟化系统SQL注入致远程代码执行漏洞复现

0x01 产品简介 瑞友天翼应用虚拟化系统是西安瑞友信息技术资讯有限公司研发的具有自主知识产权,基于服务器计算架构的应用虚拟化平台。它将用户各种应用软件集中部署在瑞友天翼服务器(群)上,客户端通过WEB即可快速安全的访问经服务器上授权的应用软件,实现集中应用、远程接…

AIGC技术带给我们什么?基于AIGC原理及其技术更迭的思考

AIGC技术带给我们什么&#xff1f;基于AIGC原理以及技术更迭的思考 前言 AI&#xff0c;这个词在如今人们的视野中出现频率几乎超过了所有一切其他的事物&#xff0c;更有意思的是&#xff0c;出现频率仅次于这个词的&#xff0c;几乎都会加上一个修饰亦或是前缀——AI&#…