main()
函数
在 main()
函数中,我们首先调用初始化函数 init()
,然后进入 while()
循环。该循环主要由三部分组成:
- 检查用户输入:如果按下 “w” 键或空格键,小鸟将向上移动两行。如果按下 “q” 键,游戏将退出。如果按下 “z” 键,游戏将暂停。
- 移动小鸟并重新绘制它。
- 检查小鸟是否撞到管道。
让我们看看代码:
int main()
{
char ch;
init();
while(1)
{
ch = getch(); // 获取键盘输入
if(ch == ' ' || ch == 'w' || ch == 'W') // 如果按下空格键或 “w” 键
{
// 移动小鸟并重新绘制它
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);
}
}
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” 键或空格键,小鸟将向上移动两行。如果按下 “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()
,并设置了定时器间隔。
让我们看看每个初始化子函数。
init_bird()
函数初始化小鸟的位置:
void init_bird()
{
bird_x = 5;
bird_y = 15;
move(bird_y, bird_x);
addch(CHAR_BIRD);
refresh();
sleep(1);
}
init_head()
和 init_wall()
函数初始化一个链表来存储管道:
void init_head()
{
Node tmp;
tmp = (node *)malloc(sizeof(node));
tmp->next = NULL;
head = tmp;
tail = head;
}
void init_wall()
{
int i;
Node tmp, p;
p = head;
for(i = 0; i < 5; i++)
{
tmp = (node *)malloc(sizeof(node));
tmp->x = (i + 1) * 19;
tmp->y = rand() % 11 + 5;
p->next = tmp;
tmp->next = NULL;
p = tmp;
}
tail = p;
}
init_draw()
函数初始化屏幕:
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);
}
for(j = p->y+5; j <= 23; j++)
{
move(j, i);
addch(CHAR_STONE);
}
}
refresh();
sleep(1);
}
}
至此,我们的《飞扬的小鸟》游戏就完成了。