欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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游戏界面

C语言Flappy bird——Windows下基于EasyX且支持键盘操作

1.2游戏结束界面

C语言Flappy bird——Windows下基于EasyX且支持键盘操作

二、游戏源码

将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 日