天天看点

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

一、游戏窗口

PS:此游戏为c语言开发,因EasyX库需要.cpp文件才能编译,所以工程文件后缀为.cpp,并未使用cpp的语法。

VS2013工程百度云链接:

链接:https://pan.baidu.com/s/16k2AvvEC_4NM_sFQHXgW1w

提取码:2333

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 日

继续阅读