lv6 嵌入式开发-Flappy bird项目(功能实现)

这篇文章详细描述了一个使用C语言和Ncurses库开发的简单游戏,涉及小鸟的显示、移动、清除以及管道的创建、移动和游戏结束条件判断。项目分为三个阶段,包括初始化Ncurses库、定时器设置和小鸟与管道的游戏逻辑。
摘要由CSDN通过智能技术生成

目录

项目安排:

1 阶段

        1.1 初始化Ncurses库

        1.2 设置定时时间

        1.3 实现小鸟功能(显示小鸟、清除小鸟、移动小鸟)

2 阶段

        2.1 创建链表

        2.2 显示管道

        2.3 清除管道

        2.4 移动管道

3 阶段

        3.1 判断游戏结束:小鸟与管道碰到

        3.2 循环创建管道

        3.3 为管道和小鸟添加色彩

4 完整代码:


项目安排:

阶段1:初始化工作,小鸟功能实现

阶段2:管道功能实现

阶段3:完善代码,进行项目总结

1 阶段

        1.1 初始化Ncurses库

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <curses.h>
#include <stdlib.h>

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

        1.2 设置定时时间

int set_timer(int ms_t)//设置定时器--ms
{
	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;

}

        1.3 实现小鸟功能(显示小鸟、清除小鸟、移动小鸟)

#define BIRD '@'
#define BLANK ' '
#define PIPE '+'

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);
			}
		}
	}
}

2 阶段

        2.1 创建链表

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 = 	 + 5; // (5-15行)
		new->next = NULL;
		p->next = new;
		p = new;
	}
	tail = p;

}

        2.2 显示管道

/*定义关于管道的结构体*/
typedef struct Pipe{
	int x;//列坐标
	int y;//横坐标
	struct Pipe *next;
}Pipe_node, *Pipe_list;

Pipe_list head, tail;


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));
}

        2.3 清除管道

即把显示管道的字符改为空格

void clear_pipe()
{

	Pipe_list p;
	int i,j;

	p = head->next;
	while(p != NULL)
	{
		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;

	}

}

        2.4 移动管道

void move_pipe()
{
	Pipe_list p;
	p = head->next;
	while(p)
	{
		p->x--;
		p = p->next;
	}

}

3 阶段

        3.1 判断游戏结束:小鸟与管道碰到

void handle(int sig)
{
	Pipe_list p, new;
	int i,j;
	

	//小鸟自动下落
	clear_bird();
	g_bird_y++;
	show_bird();

	//判断游戏是否结束
	if((char)inch() == PIPE)
	{
		set_timer(0);
		endwin();
		exit(1);
	}
	
	//管道自动左移
	p = head->next;
	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();

}

        3.2 循环创建管道

同上

        3.3 为管道和小鸟添加色彩

同上

4 完整代码:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <curses.h>
#include <stdlib.h>

#define BIRD '@'
#define BLANK ' '
#define PIPE '+'

typedef struct _Pipe_node
{
	int x;
	int y;
	struct _Pipe_node * next;
}Pipe_node, *Pipe_list;

int g_bird_y,g_bird_x;
Pipe_list head,tail;



void init_curses();  
int set_timer(int ms);
void handle(int sig);   //闹钟信号回调处理
void show_bird();
void clear_bird();
void move_bird();

void creat_list();
void show_pipe();
void clear_pipe();
void move_pipe();

int main(int argc,char *argv[])
{
	g_bird_y = 15;
	g_bird_x = 20;

	init_curses();
	signal(SIGALRM, handle);
	set_timer(300);

	srand(time(0));  //随机种子,不然每次开机都是一样的路线
	creat_list();
    
	show_bird();
	move_bird();


	while(1)
	{

	}

	return 0;
}

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

int set_timer(int ms)
{
	struct itimerval timer;
	long t_sec,t_usec;
	int ret;

	t_sec = ms / 1000; //s
	t_usec = (ms % 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(g_bird_y,g_bird_x);
	addch(BIRD);
	refresh();
	attroff(COLOR_PAIR(1));
}

void clear_bird()
{
	move(g_bird_y,g_bird_x);
	addch(BLANK);
	refresh();
}

void move_bird()
{
	char ch;

	while(1)
	{
		ch = getch();
		if(ch == BLANK)
		{
			clear_bird();
			g_bird_y--;
			show_bird();
		}


	}
}

void creat_list()
{
	Pipe_list p, new;
	int i;

	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 + 2) * 20;    //20 40 60 80 100 
		new->y = rand() % 11 + 5;  // (0 + 5) <= y < (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 != NULL)
	{
		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 != NULL)
	{
		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;
	}

}


void handle(int sig)
{
	Pipe_list p, new;
	int i,j;
	

	//小鸟自动下落
	clear_bird();
	g_bird_y++;
	show_bird();

	//判断游戏是否结束
	if((char)inch() == PIPE)
	{
		set_timer(0);
		endwin();
		exit(1);
	}
	
	//管道自动左移
	p = head->next;
	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();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
#include "world.h" #include <QPainter> #include <QFile> #include <QTextStream> #include <QDataStream> #include "bird.h" #include <QDebug> World::World(QWidget* parent): QWidget(parent) { //this->resize(432, 644); this->setGeometry(400,200, 432,644); bird = new Bird; ground = new Ground; c1 = new Column(0); c2 = new Column(1); gameoverImage.load(":gameover"); bgImage.load(":bg"); startImage.load(":start"); gameOver = false; startGame = false; score = 0; score_label = new QLabel(this); score_label->setGeometry(QRect(270,10,120,40)); score_label->setStyleSheet(QString::fromUtf8("font: 20pt \"Khmer OS System\";\n" "color: rgb(85, 0, 255);")); timer.setInterval(1000/70); connect(&timer, SIGNAL(timeout()), this, SLOT(run())); //一会写run // timer.start(); QFile file("./score.dat"); if(!file.open(QFile::ReadOnly | QFile::Text)){ best_score = 0; }else{ //QTextStream in(&file); QDataStream in(&file); in >> best_score; qDebug() << "read..."; } file.close(); } World::~World(){ if(score > best_score) save(score); } void World::save(unsigned short best){ QFile file("./score.dat"); if(!file.open(QFile::WriteOnly | QFile::Text)){ return; }else{ // QTextStream out(&file); QDataStream out(&file); out << best; //qDebug() << "write"; } file.close(); } //哑元函数 void World::paintEvent(QPaintEvent*){ QPainter painter(this); painter.drawImage(0,0,bgImage); //将画笔传给bird对象,由bird对象画出当前小鸟的图片 c1->paint(&painter); c2->paint(&painter); bird->paint(&painter); ground->paint(&painter); if(!startGame){ painter.drawImage(0,0,startImage); } if(gameOver){ painter.drawImage(0,0,gameoverImage); } if(!startGame){ painter.setFont(QFont("Khmer OS System",20,QFont::Bold)); painter.drawText(QRect(QPoint(145,390), QPoint(320,445)), QString::fromUtf8("历史最高:")+=QString::number(best_score)); } score_label->setText(QString("score:")+=QString::number(score)); } void World::run(){ bird->fly();//飞 bird->step();//小鸟下落 c1->step(); c2->step(); ground->step(); if(bird->pass(*c1) || bird->pass(*c2)){ qDebug("pass"); score++; } if(bird->hit(*c1,*c2,*ground)){ timer.stop(); gameOver = true; //gameover ... //TODO /** 1)加载gameover图片,实现点击图片 的开始按钮重新开始游戏。 2)将开始画面加入,点击鼠标或者键盘的 空格键才开始游戏 完成上两步后做以下工作: 3)加入评分机制。 通过一根柱子得1分 */ } this->repaint();//重新绘制 } void World::mousePressEvent(QMouseEvent *p){ //点击鼠标让当前速度保持为初始速度 //speed = v0; //bird->speed = bird->v0; bird->flappy(); //restart()之前 starGame = false; if(!startGame){ startGame = true; timer.start(); } if(gameOver){ QRect rect(QPoint(135,331), QPoint(281,408)); QPoint point = p->pos(); if(rect.contains(point)){ restart(); } } } //实现restart void World::restart(){ gameOver = false; startGame = false; if(score > best_score){ best_score = score; save(best_score); } score = 0; delete bird; delete c1; delete c2; bird = new Bird; c1 = new Column(0); c2 = new Column(1); qDebug()<< "restart..."; this->repaint();//定时器停止需要手动重绘 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

4IOT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值