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

c语言小游戏 flybird Easyx编程 项目源码讲解

程序员文章站 2024-03-18 14:59:10
...

分享一个c语言小游戏可以帮助大家更好的熟悉c语言
这个就是前几年很火的手机小游戏飞行的小鸟
1.游戏流程:小鸟不断下落使用按键让其飞起来不断的穿过两个管子。
2.游戏框架:采用老师提供的框架和重要模块分开编写,使用easyx图形系统。
a.核心算法:使用了坐标的判断,和判断语句的熟练运用。
b.程序调度。
c.透明贴图消除图片的背景方框
d.文件的使用
3.代码优化。

先看一下游戏效果
c语言小游戏 flybird Easyx编程 项目源码讲解c语言小游戏 flybird Easyx编程 项目源码讲解

c语言小游戏 flybird Easyx编程 项目源码讲解
现在开始上代码

先上流程图
c语言小游戏 flybird Easyx编程 项目源码讲解c语言小游戏 flybird Easyx编程 项目源码讲解



//
//
//flybrid小游戏
//	主要玩法:
//		使用空格键让不断下落的小鸟在管子中间穿梭
//		若碰到了地板,顶部,管子游戏结束
//		保存最高分数



#include"head.h"

int x = 0;//分数
int max;//最高分

IMAGE back;//背景图
IMAGE per;//小鸟图
IMAGE bird1;//小鸟底图
IMAGE up;//管子图
IMAGE down;//管子图
IMAGE lend;//地板图
IMAGE over;//游戏结束图
IMAGE over1;//游戏结束底图
IMAGE began;//开始游戏图
IMAGE began1;//开始游戏底图
IMAGE diff;//困难模式游戏图
IMAGE again1;//重新开始游戏图
IMAGE out;//退出图
IMAGE open;//开机动画的图
//IMAGE again;

MOUSEMSG k;

//小鸟的结构体
struct Bird {
	int x;		//小鸟的横坐标
	int y;		//小鸟的纵坐标	
	int speed;	//小鸟下坠的高度
}bird = { 100,250,30 };	//初始化

//管子的结构体
struct pipe {
	int x;		//管子的横坐标
	int y;		//管子的纵坐标
	int h;		//管子的高度
};

//加载资源
void loadRescue() {
	loadimage(&back, "bg_night.png");		//加载背景图
	loadimage(&per, "bird.png",30,30);	//加载小鸟图
	loadimage(&bird1, "bird1_1.png", 30, 30);
	loadimage(&lend, "land.png");			//加载地板图
	loadimage(&over, "game_over.png");		//加载游戏结束图
	loadimage(&over1, "text_game_over_1.png");		//加载游戏结束图
	loadimage(&down, "down.png");	//加载管子图
	loadimage(&up, "up.png");//加载上管子图
	loadimage(&began, "button_play.png");//简单模式游戏图
	//loadimage(&again, "again.png");
	loadimage(&again1, "again1.png");//重新开始图
	loadimage(&began, "button_play.png");
	loadimage(&began1, "button_play_1.png");
	loadimage(&out, "back.png");

}

//开始的按钮
void Booton() {
	Startmove();
	MOUSEMSG m;//鼠标定义
	MOUSEMSG g;//
	loadimage(&back, "bg_night.png");		//加载背景图
	putimage(0, 0, &back);
	rectangle(120, 210, 200, 250);//简单模式
	rectangle(120, 310, 200, 350);//困难模式
	loadimage(&began, "button_play.png",80,40);
	loadimage(&diff, "diff.png",80,40);
	putimage(120, 310, &diff);
		putimage(120,210, &began);
	while (1) {
		m = GetMouseMsg();//获取鼠标
		if (m.uMsg == WM_LBUTTONDOWN /*|| _kbhit()*/) {
			if (((m.x > 100 && m.x < 216) && (m.y > 200 && m.y < 270))//简单模式范围
				/*|| _getch() == 'e'*/) {
				Begin();
			}
			
				}
		g = GetMouseMsg();
		if (g.uMsg == WM_LBUTTONDOWN /*|| _kbhit()*/) {
			if (((g.x > 120 && g.x < 216) && (g.y > 300 && g.y < 370))//困难模式范围
				/*|| _getch() == 'd'*/) {
				Diffcult_Began();
			}
		}
		if (_kbhit()) {
			if (_getch() == 'e') {
				Begin();
			}
			else if (_getch() == 'd') {
				Diffcult_Began();
			}
		}
	}
	return;
}

//设定鸟
void drawperson(int x, int y) {
	putimage(x,y,&per,SRCAND);//底图
	putimage(x, y, &bird1, SRCPAINT);//正图
	bird.y += 5; //鸟一直往下坠落5
}


//多线程 否则会卡顿
//加载按键音乐 
DWORD WINAPI playMusic(LPVOID IpParamer) {
	mciSendString("open correct.mp3", 0, 0, 0);
	mciSendString("play correct.mp3 wait", 0, 0, 0);
	mciSendString("close correct.mp3", 0, 0, 0);
	return 0;
}

//加载游戏结束音乐
DWORD WINAPI OverMusic(LPVOID IpParamer) {
	mciSendString("open 12321.mp3", 0, 0, 0);
	mciSendString("play 12321.mp3 wait", 0, 0, 0);
	mciSendString("close 12321.mp3", 0, 0, 0);
	return 0;
}

//加载地板
void drawland() {
	putimage(0,414, &lend, SRCAND);
	putimage(0,414, &lend, SRCPAINT);

}


//鸟的按键处理
void Down() {

	char userkey = _getch();
	switch (userkey) {
	//按下空格键时鸟向上弹跳
	case ' ':						
		bird.y -= bird.speed;
		CreateThread(NULL,NULL,playMusic,NULL,NULL,NULL); //按下空格键时的音效
		break;
	default:
		break;
	}
}
//撞击地板后
int hitland() {
	if (bird.y <= 0 || bird.y >= (512 - 96)) {
		return 1;
	}
	return 0;
}

//游戏死亡后的弹出的图标
void GameOver() {
//图标的坐标
	int x = 50; 
	int y = 512;
//图标从底层出现 提留在中间层5s
	while (y >= 200) {
		putimage(0, 0, &back);
		putimage(x, y, &over1, SRCAND);
		putimage(x, y, &over, SRCPAINT);
		y -= 30;
		Sleep(100);
	}
	CreateThread(NULL, NULL, OverMusic, NULL, NULL, NULL); //游戏结束后的音效
	Again();//重新开始游戏图标选项
	Sleep(5000);
	
	
}

//定义管子
void printpipe(struct pipe pip[], int i) {
	pip[i].h = rand() % 100 + 130; //管子在屏幕的高度 随机显示在130—230之间
	pip[i].x = 288;
	pip[i].y = 0;
}


//画出管子
void drawpip(struct pipe pip) {
	//上方的管子
	putimage(pip.x, 0, 52, pip.h, &down, 0, 320 - pip.h);// xy轴坐标 长框 图片指针名 图片开始从哪画的xy轴
	//下方的管子
	putimage(pip.x, 412-(320-pip.h), 52, 320 - pip.h, &up, 0, 0);
	
}

//简单模式管子的移动和刷新
void Movetube(struct pipe pip[], int i) {
	pip[i].x -= 5;


	//当管子被刷出屏幕外时加载新管子
	if (pip[i].x < (-52 - 150)) //第一个出去150后 重新载第四跟管子 屏幕永远都有两个管子
	{
		printpipe(pip, i);
	}
	return;
}

//困难模式下管子的移动和刷新
void Diff_Movetube(struct pipe pip[], int i) {
	pip[i].x -= 10;


	//当管子被刷出屏幕外时加载新管子
	if (pip[i].x < (-52 - 150))
	{
		printpipe(pip, i);
	}
	return;
}

//是否碰撞到了上面的柱子
int HItUp(struct pipe pip[],int i) {
	//判断鸟的坐标与上方柱子坐标之间的关系
	if ((bird.y <= pip[i].h) && (bird.x + 30 >= pip[i].x) && (pip[i].x <= pip[i].x + 52)) { 
		return 1;//1表示撞到了
	}
	return 0;
}


//是否碰撞到了下面的柱子
int HItDown(struct pipe pip[], int i) {
	//判断鸟的坐标与下方柱子坐标之间的关系
	if ((bird.y + 30 >= 412 - (320 - pip[i].h)) && (bird.x + 30 >= pip[i].x) && (pip[i].x <= pip[i].x + 52)) {
		return 1;
	}
	return 0;
}

//是否撞到管子
void Hittube(struct pipe pip[], int i) {
	//判断鸟穿过当前这个管子
	if (pip[i].x + 52 <= bird.x) {
		return;
	}
				
			//与下一个管子比较
				else if (HItUp(pip, i) == 1) {
					GameOver();
					return;
				}
				else if (HItDown(pip, i) == 1) {
				GameOver();
				return;
			}

}
//记录分数
void Score(struct pipe pip[], int i){
	
	char s[10];
	sprintf_s(s, " %d", x);//将整型数字转成字符保存在s中
	//settextcolor(RED);
	outtextxy(72, 0, s);
	outtextxy(0, 0, "你的分数: ");
	if (pip[i].x + 52 == bird.x){ //判断鸟是否串过管子了
		x++;
		sprintf_s(s, " %d", x);
		outtextxy(0, 0, "你的分数: ");
		outtextxy(72, 0, s);
	}
}

//简单分数管理 
void ChangeMaxScore(int x) {
	FILE* fp = fopen("Score.txt", "r+"); //存放普通模式下的最高分文件
	fscanf(fp, "%d", &max); //取出保存在max中
	char s1[10];
	sprintf_s(s1, " %d", max);//转换类型 用outtextxy输出到游戏界面
	outtextxy(72, 16, s1);
	outtextxy(0, 16, "最高分数: ");
	FlushBatchDraw();
	fclose(fp);
	if (x > max) {//在数据库中存入最高分
		FILE* fp = fopen("Score.txt", "w+");
		fprintf(fp, "%d", x);
		fclose(fp);
	}
	
}

//困难模式分数管理 
void Diff_ChangeMaxScore(int x) {
	FILE* fp = fopen("Diff_Score.txt", "r+");//困难模式最高分的文件
	fscanf(fp, "%d", &max);
	char s1[10];
	sprintf_s(s1, " %d", max);
	outtextxy(72, 16, s1);
	outtextxy(0, 16, "最高分数: ");
	fclose(fp);
	if (x > max) {//在数据库中存入最高分
		FILE* fp = fopen("Diff_Score.txt", "w+");
		fprintf(fp, "%d", x);
		fclose(fp);
	}

}

//游戏开始
void Begin() {
	
	struct pipe pip[3];//三个管子
	//初始化三个管子
	for (int i = 0; i < 3; i++) {
		printpipe(pip, i);//在屏幕中显示管子
		pip[i].x = 288 + i * 150;//每个管子之间的间隔150
	}
	loadRescue();	//加载资源
	while (1) {
		putimage(0, 0, &back); //画出背景图
		drawland();			   //画出地板
		drawperson(bird.x, bird.y);	//画出鸟
		for (int i = 0; i < 3; i++) {
			drawpip(pip[i]);//画出管子
			Movetube(pip, i);
		}
		FlushBatchDraw();
		//判断是否撞上了管子
		for (int i = 0; i < 3; i++) {
			Hittube(pip, i);
			Score(pip, i);	//显示当前分数
		}
		
		//MaxScore();//显示最高分
		ChangeMaxScore(x);

		//判断按键是否按下
		if (_kbhit()) {
			Down();
		}

		//判断是否撞击地板
		if (hitland()) {
			GameOver();
			break;
		}
		Sleep(100);

	}
}

void Diffcult_Began() {

	struct pipe pip[3];//三个管子
	//初始化三个管子
	for (int i = 0; i < 3; i++) {
		printpipe(pip, i);//在屏幕中显示管子
		pip[i].x = 288 + i * 150;//每个管子之间的间隔150
	}
	loadRescue();	//加载资源
	while (1) {
		putimage(0, 0, &back); //画出背景图
		drawland();			   //画出地板
		drawperson(bird.x, bird.y);	//画出鸟
		for (int i = 0; i < 3; i++) {
			drawpip(pip[i]);//画出管子
			Diff_Movetube(pip, i);
		}
		FlushBatchDraw();
		//判断是否撞上了管子
		for (int i = 0; i < 3; i++) {
			Hittube(pip, i);
			Score(pip, i);	//显示当前分数
		}

		//MaxScore();//显示最高分
		Diff_ChangeMaxScore(x);

		//判断按键是否按下
		if (_kbhit()) {
			Down();
		}

		//判断是否撞击地板
		if (hitland()) {
			GameOver();
			break;
		}
		Sleep(100);

	}
}

//重新开始
void Again() {
	
	rectangle(70, 310,240, 380);
	putimage(70, 310, &again1);
	putimage(100, 100, &out);
	//putimage(80, 310, &again, SRCPAINT);
	MOUSEMSG k;
	while (1) {
	
		k = GetMouseMsg();
		if (k.uMsg == WM_LBUTTONDOWN) {
			if (((k.x > 80 && k.x < 240) && (k.y > 300 && k.y < 380))
				) {
				x = 0;
				bird.y = 250;
				Begin();//重新开始游戏
			}
			
		}
		if (_kbhit()) {
			if (_getch() == 'k') {
				x = 0;
				Begin();//重新开始游戏
			}
			else if (_getch() == 'q') {
				Endmove();
			}

		}
	}
}

void Startmove() {//开机动画
	clearrectangle(0, 0, 288, 512);
	setbkcolor(BLACK);
	
	int i;
	for (i = 0; i < 5; i++) {
		//随机出现图画
		int x = rand() % 180;
		int y = rand() % 480;
		loadimage(&open, "open.png");
		putimage(x, y, &open);
		Sleep(50);
	}
}


void Endmove() { //关机动画 
	clearrectangle(0, 0, 288, 512);//清屏
	setbkcolor(BLACK);//背景颜色
	 int y = 100;
	for (int x = 50; x < 288; x += 20) {
		settextcolor(BLUE);
		settextstyle(32, 0, NULL);//高度 宽度0自适应 字体样式无
		outtextxy(100, y,"GOOD BYE");
		y += 52;//下移
		setcolor(YELLOW);
		setfillstyle(BLUE);
		fillellipse(x, 50, 10, 10);
		Sleep(500);
		setcolor(GREEN);
		setfillstyle(RED);
		fillellipse(x, 50, 10, 10);

	}
	closegraph();
}




//头文件
#define  _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>
#include<graphics.h> //图形库文件
#include<conio.h> //按键头文件
#include<time.h>
#include<mmsystem.h>//调用音乐的头文件
#pragma comment(lib,"winmm.lib")
/*全局变量*/
extern int x;//分数
extern int max;//最高分

/*游戏资源的加载初始化*/
void loadRescue();//加载资源

void drawperson(int x, int y);//画鸟

void Booton();//开始的按钮

DWORD WINAPI playMusic(LPVOID IpParamer);//加载按键音乐   多线程 否则会卡顿

DWORD WINAPI OverMusic(LPVOID IpParamer);//加载游戏结束音乐

void drawland();//加载地板

void printpipe(struct pipe pip[], int i);//定义管子

void drawpip(struct pipe pip);//画出管子





/*游戏过程的处理*/
void Down();//鸟的按键处理

int hitland();//撞击地板后

void Movetube(struct pipe pip[], int i);//管子的移动和刷新

int HItUp(struct pipe pip[], int i);//是否碰撞到了上面的柱子

int HItDown(struct pipe pip[], int i);//是否碰撞到了下面的柱子

void Hittube(struct pipe pip[], int i);//是否撞到管子

void Diff_Movetube(struct pipe pip[], int i);//困难模式下的管子移动



/*分数管理*/
void Diff_ChangeMaxScore(int x);//最高分的记录

void Score(struct pipe pip[], int i);//记录分数

void ChangeMaxScore(int x);//分数管理


/*游戏的几种模式*/
void Diffcult_Began();//困难模式

void Begin();//游戏开始

void Again();//重新开始

void GameOver();//游戏死亡后的弹出的图标




/*开关机动画*/
void Endmove();//关机动画

void Startmove();//开机动画

//主函数
#include"head.h"

int main() {
initgraph(288, 512);//初始化图形系统
setbkcolor(BLACK);
Booton(); //开始按钮 点击开始后进入游戏
return 0;
}

//刚刚学的c语言如果有不对的地方欢迎大家给我提出
//不懂的地方可以评论提问 我尽量解答
//需要图片资源的可以留下邮箱

相关标签: c c语言 游戏