C语言Flappy bird——Windows下基于EasyX且支持键盘操作
程序员文章站
2022-04-07 17:22:51
...
一、游戏窗口
PS:此游戏为c语言开发,因EasyX库需要.cpp文件才能编译,所以工程文件后缀为.cpp,并未使用cpp的语法。
VS2013工程百度云链接:
链接:https://pan.baidu.com/s/1rzyHp6wskyaB7YEo4bTkdA
提取码:mecs
1.1游戏界面
1.2游戏结束界面
二、游戏源码
将flb.cpp、flb.h、main.cpp文件添加到工程里
2.1 flb.cpp
#include "flb.h"
#define Blank 0
#define Wall 1
#define Bird_Body 2
#define BIRD_HIGH 7
#define length 700
#define Door_WID 20
#define Wall_COLOR YELLOW
#define KB_COLOR CYAN
int WALL_DISTAN = 30;//墙壁间隔
IMAGE img;//存储bird图片
IMAGE pWall_Img;//存储Wall的图片
int Bird_MAP[100][100];//地图
int Bird_pos[2] = { 9, 30 };//bird位置 Bird_pos[0]为横坐标不变 Bird_pos[1]为纵坐标
int SUM_SCORE = -1;//总分数
int num_rand[20] = { 16, 45, 40, 10, 40, 55, 15, 0, 46, 15, 12, 60, 10, 45, 12, 50, 8, 35, 18, 47 };//墙的缝隙位置
int Door_pos = 0;//墙的缝隙位置数组下标
int t = 1;//下降时间
int t_count = 0;//下降时间计数
void OninitAll()
{
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
Bird_MAP[i][j] = 0;//地图清零
//初始化bird的初始位置
Bird_pos[0] = 9;
Bird_pos[1] = 30;
SUM_SCORE = -1;//分数清空
Door_pos = 0;//门的位置num_rand数组下标清空
WALL_DISTAN = 30;//重置墙的距离
t = 1;//下降时间(距离)归1
t_count = 0;//下降时间计数清空
}
void Restart_Game()
{
char str[50];//游戏结束 弹出窗口显示分数
if (SUM_SCORE > 0)
sprintf(str, "游戏结束,得分:%d,是否重开?", SUM_SCORE);
else
sprintf(str, "游戏结束,得分:%d,是否重开?", 0);
int res = MessageBoxA(0, str, "Flappy bird", MB_YESNO | MB_SYSTEMMODAL);
if (res == IDYES)//选择是 则初始化参数再重开
{
OninitAll();
Start_Game();
}
else//选择否 关闭游戏
{
closegraph();
char str[30];
sprintf(str, "taskkill /f /im \"%s\"", "Flappy bird.exe");
system(str);
}
}
void Create_WALL(int i, int Door_pos)
{
int pos = 70;//门的上方位置为 pos - num_rand[Door_pos]
for (int j = 0; j < 100; j++)
{
for (int k = 1; k <= 6; k++) //墙壁宽6
Bird_MAP[100 - k - WALL_DISTAN * i][j] = Wall;
if (j == (pos - num_rand[Door_pos]))
{
j += Door_WID;//到达门的上方位置则j + Door_WID 即留出门的距离Door_WID
}
}
}
void judgegame()
{
if (Bird_pos[1] > 100 || Bird_pos[1] < 0)//上或者下出地图则游戏结束
Restart_Game();
for (int i = 0; i <= 3; i++)//bird长宽为3倍BIRD_HIGH 此范围下的数组是Wall则结束
for (int j = 0; j <= 3; j++)
if (Bird_MAP[Bird_pos[0] + i][Bird_pos[1] + j] == Wall)
{
Restart_Game();
}
}
void Draw_Map()
{
cleardevice();
for (int i = 1; i < 100; i++)
{
for (int j = 9; j < 90; j++)
{
if (Bird_MAP[i][j] == Wall
&&Bird_MAP[i - 1][j] != Wall
&&Bird_MAP[i][j + 1] != Wall
&&i - Bird_pos[0] >= -7)/* Bird_pos[2]*/
{ //墙 上半部分
putimage(i * BIRD_HIGH - BIRD_HIGH / 2,
0,
40,
j * BIRD_HIGH + BIRD_HIGH / 2,
&pWall_Img, 0, 0);
//墙 下半部分
putimage(i * BIRD_HIGH - BIRD_HIGH / 2,
(j + Door_WID) * BIRD_HIGH + BIRD_HIGH / 2,
40,
length,
&pWall_Img, 0, 0);
}
}
}
putimage(Bird_pos[0] * BIRD_HIGH - BIRD_HIGH / 2, Bird_pos[1] * BIRD_HIGH - BIRD_HIGH / 2, &img);//输出bird图片
char str[10];//左上角显示分数
if (SUM_SCORE > 0)
sprintf(str, "%d", SUM_SCORE);
else
sprintf(str, "%d", 0);
outtextxy(10, 10, str);
judgegame();//判断游戏是否结束
}
void MOVE_WALL()
{
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 100; j++)
{
int wallnum = 0;
if (Bird_MAP[i][j] == Wall)//此处为墙 则下一步让左侧为墙
{
Bird_MAP[i - 1][j] = Wall;
wallnum++;
Bird_MAP[i][j] = Blank;//前面的设为墙 此处设为墙
}
if (wallnum == 100)
{
i += 5;
}
if (i == 0)//到达最左侧出地图就清空墙壁
Bird_MAP[i][j] = Blank;
}
}
}
void Change_Birdpos()
{
t_count++;
if (t_count % 4 == 0)//每下降四次 下降时间(距离)加1
{
if (t < 3) t++; //下降时间(距离)≤3
}
Bird_pos[1] += t;
}
void MOVE_BIRD()//移动鸟
{
int key;
if (_kbhit() != 0) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0
{
while (_kbhit() != 0) //可能存在多个按键,要全部取完,以最后一个为主
key = _getch(); //将按键从控制台中取出并保存到key中
if (GetAsyncKeyState(VK_SPACE) & 0x8000)
{
t = 1;//重新开始下降 因此下降时间(距离)设为最小
Bird_pos[1] -= 10;
}
}
}
int Move_Speed()
{
int res = 45 - SUM_SCORE / 10;//每过十道墙 Sleep等待的时间减1
if (res >= 25)//最快不低于25
return res;
else return 25;
}
void change_wallpos(int num)
{
for (int j = 0; j < num; j++)//随机打乱门的距离数组num_rand
{
int randnum = rand() % 10;
int temp = num_rand[j];
num_rand[j] = num_rand[j + randnum];
num_rand[j + randnum] = temp;
}
}
void Start_Game()
{
initgraph(length, length);//初始化窗口 length默认为700
HWND hwnd = GetHWnd();
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE));
MoveWindow(hwnd, 0, 0, length, length, TRUE);//设置为左上角显示
setbkcolor(KB_COLOR);//设置背景色
cleardevice();
char s[10];
sprintf(s, "1.png");
loadimage(&img, s);//加载bird图片 名称为1.png
char wall_str[10] = "wall.bmp";
loadimage(&pWall_Img, wall_str);
change_wallpos(3);
for (int i = 0; i < 2; i++)//先生成三道墙
Create_WALL(i, i);
for (int stepnum = 0;; stepnum++)
{
if (stepnum == WALL_DISTAN)//此时移动距离等于墙的距离WALL_DISTAN
{
change_wallpos(3);
Create_WALL(0, Door_pos % 20);//地图最右侧产生一道墙
Door_pos++;//门的位置num_rand数组下标加一
SUM_SCORE++;//分数加一
stepnum = 0;//移动距离清零
if ((Door_pos + 1) % 10 == 0) //每过十道墙 距离减2
if (WALL_DISTAN > 20) //墙之间的距离不能小于20
WALL_DISTAN -= 2;
}
Draw_Map();//显示地图
Change_Birdpos();//监听键盘输入 控制bird向上移动
MOVE_WALL();//移动墙壁
MOVE_BIRD();//移动bird
Sleep(Move_Speed());//等待
}
}
2.1 flb.h
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <Windows.h>
#include <graphics.h>
void OninitAll();//初始化参数
void Restart_Game();//判断重新开始游戏
void Create_WALL(int i, int Door_pos);//生成墙壁
void judgegame();//判断游戏是否结束
void Draw_Map();//墙 bird
void MOVE_WALL();//地图移动
void MOVE_BIRD(); //移动鸟
void Change_Birdpos(double t);//改变鸟的位置
int Move_Speed();//墙移动速度
void change_wallpos(int num);//改变墙的位置
void Start_Game();//开始游戏
2.1 main.cpp
#include "flb.h"
#define Wall_COLOR YELLOW
#define KB_COLOR CYAN
int main()
{
Start_Game();
system("pause");
return 0;
}
由 LiangJian 写于 2019 年 10 月 15 日