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://xiahunao.cn/news/3017053.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Go语言fmt包深度探索:格式化输入输出的利器

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f3ad; 引言一、基础输出函数fmt.Print与fmt.Println&#x1f4cc; fmt.Print&#xff1a;纯粹输出&#xff0c;不带换行&#x1f4cc; fmt.Println&#xff1a;输出后自动添加换行符 二、格式化输出fmt.Printf&…

【C语言】用数组和函数实现扫雷游戏

用数组和函数实现扫雷游戏 游戏界面&#xff1a; 代码如下&#xff1a; game.h #pragma once #include <stdio.h> #include <stdlib.h> #include <time.h> #define EASY_COUNT 10 #define ROW 9 #define COL 9 #define ROWS ROW2 #define COLS COL2 //初始…

Error Code: 1449. The user specified as a definer (‘admin‘@‘%‘) does not exist

前言 在进行MySQL数据库迁移或存储过程部署时&#xff0c;您可能会遇到错误 [Err] 1449 - The user specified as a definer (admin%) does not exist。这篇文章将为您提供一个详细的解决方案&#xff0c;帮助您顺利解决这一问题。 错误背景 此错误通常发生在尝试执行一个存…

国货美妆进入新纪元之际,毛戈平打好“高端牌”了吗?

当前&#xff0c;国内美妆市场的格局已发生较大变化。 一边是国际品牌的“退场”&#xff0c;据统计&#xff0c;2023年退出中国市场的海外美妆品牌有20多个&#xff1b;一边是国内美妆品牌正在迎来自己的时代。 根据魔镜洞察数据&#xff0c;2024年一季度&#xff0c;国货彩…

【Linux】Linux线程

一、Linux线程的概念 1.什么是线程 1.一个进程的一个执行线路叫做线程&#xff0c;线程的一个进程内部的控制序列。 2.一个进程至少有一个执行线程 3.线程在进程内部&#xff0c;本质是在进程地址空间内运行 4.操作系统将进程虚拟地址空间的资源分配给每个执行流&#xff0…

GoLang实战——微服务网关

1. 网关 1.1. 网关应该具备的基本功能 支持多种协议代理&#xff1a;tcp/http/websocket/grpc支持多种负载均衡策略&#xff1a;轮询/权重轮询/hash一致性支持下游服务发现&#xff1a;主动探测/自动服务发现支持横向扩容&#xff1a;加机器就能解决高并发 1.2. 借助网关处理…

ldap对接jenkins

ldap结构 配置 - jenkins进入到 系统管理–>全局安全配置 - 安全域 选择ldap - 配置ldap服务器地址&#xff0c;和配置ldap顶层唯一标识名 配置用户搜索路径 - 配置管理员DN和密码 测试认证是否OK

MCU做死循环时,到底应该用for(;;) 还是wihile(1)

MCU做死循环时 for while stm32中老工程师用forfor while背景for版本while版本正方观点&#xff1a;哪有好的编译器&#xff1a;反方观点&#xff1a;这种代码过时了工程师实地测试&#xff1a;和编译器和优化有关 建议还是用for参考 stm32中老工程师用for /* Start scheduler …

数据库系统理论——绪论

文章目录 前言一、数据库四个基本概念1、数据2、数据库3、数据库管理系统&#xff08;DBMS&#xff09;4、数据库系统&#xff08;DBS&#xff09; 二、数据模型1、概念数据模型2、逻辑数据模型3、物理数据模型 三、三级模式1、图片解析2、二级映像 前言 最近很长时间没更新学…

windows 双网卡同时接入内外网

在公司使用wifi接入使用桌面云&#xff0c;但是公司wifi不能上外网&#xff0c;查资料不方便&#xff0c;通过手机同时接入外网。 同一台电脑设置同时连接内外网&#xff08;wifi或共享的网络&#xff09;_win7电脑同时使用手机和usb网卡使用wifi-CSDN博客 route print查看当前…

开启智能新纪元:揭秘现代化仓储物流园区的数字孪生魅力

在数字化浪潮的推动下&#xff0c;物流行业正迎来前所未有的变革&#xff0c;现代化仓储物流园区数字孪生系统正以其独特的魅力引领着物流行业迈向更加智能、高效的新时代。 图源&#xff1a;山海鲸可视化 一、数字孪生&#xff1a;物流行业的“虚拟镜像” 数字孪生技术作为工…

5.合并两个有序数组

文章目录 题目简介题目解答解法一 &#xff1a;合并后排序解法二&#xff1a;双指针排序 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 合并两个有序数组 相关的讲解&#xff01;&#x1f600; 题目简介 题目解答 解法一 &#xff1a;合并后排序 假设我们要合…

科研学习|可视化——ggplot2版本的网络可视化

ggplot2是R语言中一个非常流行的数据可视化包&#xff0c;它也可以用于网络可视化。以下是三个基于ggplot2并专门用于网络可视化的R包&#xff1a; ggnet2: 这个包的使用方法与传统的plot函数相似&#xff0c;易于使用。更多信息可在其官方页面查看&#xff1a;ggnet2 geomnet…

【Linux网络】PXE批量网络装机

目录 一、系统装机 1.1 三种引导方式 1.2 系统安装过程 1.3 四大重要文件 二、PXE 2.1 PXE实现原理 2.2 PXE手动搭建过程 2.3 kickstart配合pxe完成批量自动安装 一、系统装机 1.1 三种引导方式 硬盘光驱(U盘)网络启动 1.2 系统安装过程 加载boot loader加载启动安…

《安富莱嵌入式周报》第336期:开源计算器,交流欧姆表,高性能开源BLDC控制器,Matlab2024a,操作系统漏洞排名,微软开源MS-DOS V4.0

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 本周更新一期视频教程&#xff1a; BSP视频教程第30期&#xff1a;UDS ISO14229统一诊断服务CAN总线专题&#xff0c;常…

学习和分析各种数据结构所要掌握的一个重要知识——CPU的缓存利用率(命中率)

什么是CPU缓存利用率&#xff08;命中率&#xff09;&#xff0c;我们首先要把内存搞清楚。 硬盘是什么&#xff0c;内存是什么&#xff0c;高速缓存是什么&#xff0c;寄存器又是什么&#xff1f; 我们要储存数据就要运用到上面的东西。首先里面的硬盘是可以无电存储的&#…

记一次DNS故障导致用户无法充值的问题(上)

背景&#xff1a; 刚刚过去了五一劳动节&#xff0c;回来后一上班接到客服运营团队反馈的节日期间的问题&#xff0c;反馈有部分用户无法充值。拿到的反馈资料有&#xff1a; 无法充值操作视频、问题时间、手机机型、手机网络情况。 1、从视频中看到用户点击支付后没有任何反…

[CISCN2019 华北赛区 Day1 Web2]ikun

看到提示说一定要找到lv6 这要写脚本来爆破了&#xff0c;用bp是爆破不出来的 发现LV等级都是有参数挂着的 写个脚本看一下 import requests for i in range(1,1000):payload"http://node4.anna.nssctf.cn:28150/shop?page%d"%(i)resrequests.get(payload)if "…

怎么ai解答问题?这三个方法都可以

怎么ai解答问题&#xff1f;在数字化飞速发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;技术已经渗透到我们生活的方方面面&#xff0c;尤其是在解答问题方面&#xff0c;AI展现出了令人瞩目的能力。那么&#xff0c;哪些软件可以利用AI技术解答问题呢&#xff1f;…

【西瓜书机器学习】第五章 神经网络

一起啃西瓜书(5)-神经网络《机器学习-周志华》 - 知乎 (zhihu.com)参考进行自我复习整理&#xff0c;侵删&#xff01; 1、神经元模型 神经网络定义&#xff1a;神经网络是由 具有适应性 的 简单单元 组成的广泛 并行互连 的网络。M-P神经元模型&#xff1a;输入、处理、输出 …