Flappy bird小游戏

一、Ncurses库

        (1):Ncurses向用户提供了一个灵活高效的应用程序接口(API),它提供了创建窗口界面,移动光标,产生颜色以及处理键盘按键等功能。通俗点来说,它就是一个管理应用程序在字符终端显示的函数库。

        (2):安装Ncurses库的命令--> sudo apt-get install libncurses5-dev

        (3):在本项目中使用到的函数

 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 <stdlib.h>
#include <curses.h>
#include <signal.h>
#include <sys/time.h>

#define BIRD '@'    //@表示小鸟
#define BLANK ' '   //空格表示空格
#define PIPE '+'   //+表示管道
int bird_y,bird_x;    //小鸟坐标


/*定义关于管道的结构体*/
typedef struct Pipe{
    int x;  //列坐标
    int y;  //横坐标
    struct Pipe *next;
}Pipe_node,*Pipe_list;
Pipe_list head,tail;   //头尾结点
                       
/*创建链表*/
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<6;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;
    }
}


/*初始化Ncurses库*/
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);   //设置管道颜色
    
}
/*设置定时器,参数为毫秒(ms)*/
int set_timer(int ms_t){
    struct itimerval timer;
    long t_sec,t_usec;
    int ret;
    t_sec = ms_t / 1000;  //s
    t_usec = (ms_t % 1000) * 1000;  //us
    
    timer.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;
}


/*显示小鸟*/
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(0);    //结束程序
            }
        }
    }
}

void handler(int sig){
    Pipe_list p,new;
    //小鸟下落
    clear_bird();
    bird_y++;
    show_bird();
    //管道的循环创建
    p = head->next;
    if(p->x==0){
        int i,j;
        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;
    }
    /*游戏结束判断*/
    if((char)inch()==PIPE){
        set_timer(0);   //停止定时
        endwin();    //退出模式
        exit(0);    //结束程序            
    }
    //管道左移
    clear_pipe();
    move_pipe();
    show_pipe();
}

/*主函数*/
int main(int argc,const char *argv[]){
    bird_y = 15; //行
    bird_x = 15; //列
    init_curses();
    signal(SIGALRM,handler);
    set_timer(500);  //定时时间为500毫秒
    srand(time(0));  //随机种子:每次启动的管道长度不一样
    creat_list();
    show_pipe();
    show_bird();
    move_bird();
    return 0;
}
 

编译程序时要链接到Ncurses库即添加参数  -lncurses

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鯨觞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值