C语言+easyx图形库 推箱子游戏1.0

本人编程小白,在学完C语言后尝试学习制作了推箱子小游戏,途中收获颇多,在此对于整个过程做一回顾梳理,若有写的不对的地方,还望各位大佬指正。

本篇文章为1.0版本,没有关卡,但拥有推箱子游戏较核心的功能。


目录

一、开始前的准备

二、游戏设计思路梳理

 1.小Tip

2.概述

三、详细过程

1.地图绘制

2.玩家移动模块

3.输赢判断模块

4.开始页面及音乐的添加

5.main函数部分

 四、效果展示

五、作者的话


一、开始前的准备

        本文使用的工具是vs2010+easyx编程。由于我之前没有安装easyx,所以去官网进行了安装。

官网链接:进入官网后,找到 下载easyx 并按照提示完成安装。点击进入官网

备注:安装时最好安装帮助文档,并去网上对于easyx进行简单的学习,了解常见函数的用法,以便更好地操作。

帮助文档:(可通过该文档了解学习)点击进入


二、游戏设计思路梳理

 1.小Tip

        首先我们可以分析一下这个游戏需要哪些模块,比如地图绘制,开始页面,玩家移动模块,输赢判断模块等等,再大概想一想各个模块都需要用到哪些东西,做一些准备,然后再开始上手。

2.概述

在概述这里简单说一下各模块都要什么:

1.地图绘制  通过easyx的相关功能把图片绘制出来,当然,要提前准备好素材以及地图(可以在网上随便搜一个)。

2.开始页面    这个页面看需求吧,需要的话可以根据自己的喜好设计一下。

3.玩家移动模块   这里要涉及到移动设计的逻辑问题,玩家在什么情况下可以移动,最简单的就是玩家前面是空地或者目的地,这个可以直接过去,其次就是当玩家面前有箱子(或箱子在目的地上)时,这就需要考虑箱子能不能推动,若箱子后面是空地或目的地,那可以过,若后面是墙或者还是箱子,这就过不去。设计的核心就在这里。

4.输赢判断模块    这里可设定的规则挺多,时间限制,步数限制,或者死角无法推动(本文用的这一个)等等,可以自行设计。


三、详细过程

1.地图绘制

        首先我们要用图片加载函数把图片加载,然后才能开始在控制台上贴图。

IMAGE img[6];//图片对象指针
void begin()
{    
    loadimage(&img[0],L"land.jpg",60,60);//加载图片
	loadimage(&img[1],L"wall.jpg",60,60);//(IMAGE 对象指针,图片文件名,宽度,高度)
	loadimage(&img[2],L"BoxYellow.jpg",60,60);
	loadimage(&img[3],L"ManDOWN1.jpg",60,60);
	loadimage(&img[4],L"aim.jpg",60,60);
	loadimage(&img[5],L"BoxRed.jpg",60,60);//箱子在目的地时
}

加载完图片,就该绘制地图。但在此之前,我们需要规定一些数字来表示图片,以方便后续操作。

我们做出如下规定:

空地  0  ,墙  1,  箱子  2,  人物  3,  目的地  4,
很自然的, 人站在目的地 就是 3+4=7,而箱子到达目的地 便为  2+4=6。

 规定完图片之后,我们就可以用数字把地图先搞出来:(地图上网随便找一个,按规定来就行)

int map[11][13] = {      //初始化地图   
  0,0,0,1,1,1,1,1,1,1,0,0,0,
  1,1,1,1,0,0,0,0,0,1,0,0,0,
  1,0,0,0,4,1,1,1,0,1,0,0,0,
  1,0,1,0,1,0,0,0,0,1,1,0,0,
  1,0,1,0,2,0,2,1,4,0,1,0,0,
  1,0,1,0,0,6,0,0,1,0,1,0,0,
  1,0,4,1,2,0,2,0,1,0,1,0,0,
  1,1,0,0,0,0,1,0,1,0,1,1,1,
  0,1,0,1,1,1,4,0,0,0,0,0,1,
  0,1,0,0,0,0,0,1,1,0,0,3,1,
  0,1,1,1,1,1,1,1,1,1,1,1,1
};

这下万事俱备,可以开始贴图,造地图了。

void drawmap()
{
	BeginBatchDraw();// 防止贴图过快
	for(int i=0;i<11;i++)//行
	{
		for(int j=0;j<13;j++)//列
		{
			//每行单独贴图
			switch(map[i][j])
			{
			case 0://空地  
				putimage(j*60,i*60,&img[0]);//(x坐标,y坐标,对象指针)
				break;
			 case 1://墙 
				putimage(j*60,i*60,&img[1]);
				break;
			case 2://箱子  
				putimage(j*60,i*60,&img[2]);
				break;
			case 3:
			case 7://人物  
					putimage(j*60,i*60,&img[3]);
				break;
			case 4://目的地  
				putimage(j*60,i*60,&img[4]);
				break;
			case 6://箱子到达目的地  
				putimage(j*60,i*60,&img[5]);
				break;
			default:
				break;
			}
		}
	}
	EndBatchDraw();
}

备注:1.有关坐标的信息,可以在帮助文档中学习了解。

            2.在绘制地图时,不要忘记加上easyx的头文件:

#include<easyx.h>
//或者这个#include <graphics.h>

             3.在贴图前要注意把素材图片和项目代码放在同一个文件夹。

 到了这里,地图的绘制就基本结束了。下面开启第二部分,也是最重要的一部分,玩家移动。

2.玩家移动模块

        想要让玩家移动,首先我们要对玩家进行定位。

//找人的位置
	int x,y;
	for(int i=0;i<11;i++)
	{
		for(int j=0;j<13;j++)
		{
			if(map[i][j] == 3|| map[i][j] == 7)
			{
				x=i;
				y=j;
			}
		}
	}

有了玩家的位置之后,我们便开始设计移动。

这里我们首先要获取玩家的按键,从而让玩家能够控制人物移动。

获取按键:这里要用到getch()  ,不要忘记添加头文件

#include<conio.h> //getch() 头文件

 然后便开始设计按键的移动。这里需要注意的是:我们是通过数字的加减来实现玩家的移动的。

即:当玩家离开当前位置时,该位置减去3,而玩家即将到达的位置加上3。

然后我们开始设计移动,当玩家想要向上移动时,我们分情况来看:(在这里我们可以只考虑什么情况下玩家可以移动,不需要考虑无法移动的情况)

第一种:当玩家上方是空地或目的地时,玩家可以直接移动。

if(map[x-1][y]==0||map[x-1][y]==4)   //人上方是空地或目的地
{
	map[x-1][y]+=3;//人走上去 +3
	map[x][y]-=3;//原位置-3
}

第二种:当玩家上方为箱子或箱子在目的地上时,有两种可能性:

                1.箱子上方为空地或目的地,人可以和箱子一起上去;

                2.箱子上面为箱子或者墙壁(此时玩家不能移动,这种情况我们不做考虑)

if(map[x-1][y]==2||map[x-1][y]==6) //上方为箱子或箱子在目的地上
{
	if(map[x-2][y]==0||map[x-2][y]==4)  //箱子上方是空地或目的地
	{
		//人走上去,箱子也推上去
		map[x-2][y]+=2;
		map[x-1][y]+=1;//-2  +3 --+1
		map[x][y]-=3;
	}
}

到这个时候,我们便完成了向上这一按键的移动设计,而玩家也可以顺利向上移动。

至于向左,向右,向下三种情况与之类似,只需要改动一些坐标,所以我们不做详细分析,仅提供源代码以供参考。

玩家移动设计函数的完整代码:(这里我们使用wasd进行移动操作)

switch(getch())
{
	case 'W':
	case 'w':
		//往上
		if(map[x-1][y]==0||map[x-1][y]==4)   //人上方是空地或目的地
		{
			map[x-1][y]+=3;//人走上去 +3
			map[x][y]-=3;//原位置-3
		}
		else if(map[x-1][y]==2||map[x-1][y]==6) //上方为箱子或箱子在目的地上
		{
			if(map[x-2][y]==0||map[x-2][y]==4)  //箱子上方是空地或目的地
			{
				//人走上去,箱子也推上去
				map[x-2][y]+=2;
				map[x-1][y]+=1;//-2  +3 --+1
				map[x][y]-=3;
			}
		}
		break;
	case 'S':
	case 's':
		//往下
		if(map[x+1][y]==0||map[x+1][y]==4)   //人下方是空地或目的地
		{
			map[x+1][y]+=3;//人走下去 +3
			map[x][y]-=3;//原位置-3
		}
		else if(map[x+1][y]==2||map[x+1][y]==6) //下方为箱子或箱子在目的地上
		{
			if(map[x+2][y]==0||map[x+2][y]==4)  //箱子下方是空地或目的地
			{
				//人走下去,箱子也推下去
				map[x+2][y]+=2;
				map[x+1][y]+=1;//-2  +3 --+1
				map[x][y]-=3;
			}
		}
		break;
	case 'A':
	case 'a':
		//往左
		if(map[x][y-1]==0||map[x][y-1]==4)   //人左方是空地或目的地
		{
			map[x][y-1]+=3;//人往左走 +3
			map[x][y]-=3;//原位置-3
		}
		else if(map[x][y-1]==2||map[x][y-1]==6) //左方为箱子或箱子在目的地上
		{
			if(map[x][y-2]==0||map[x][y-2]==4)  //箱子左方是空地或目的地
			{
				//人往左走,箱子也推向左边
				map[x][y-2]+=2;
				map[x][y-1]+=1;//-2  +3 --+1
				map[x][y]-=3;
			}
		}
		break;
	case 'D':
	case 'd':
		//往右
		if(map[x][y+1]==0||map[x][y+1]==4)   //人右方是空地或目的地
		{
			map[x][y+1]+=3;//人往右走 +3
			map[x][y]-=3;//原位置-3
		}
		else if(map[x][y+1]==2||map[x][y+1]==6) //右方为箱子或箱子在目的地上
		{
			if(map[x][y+2]==0||map[x][y+2]==4)  //箱子右方是空地或目的地
			{
				//人往右走,箱子也推向右边
				map[x][y+2]+=2;
				map[x][y+1]+=1;//-2  +3 --+1
				map[x][y]-=3;
			}
		}
		break;
	default :
		break;
}

备注:移动函数为模块的核心,至关重要。

 此时玩家移动的设计便可以告一段落了,我们即将开始第三部分,输赢的判断。

3.输赢判断模块

有了地图,并且玩家可以移动,我们的游戏便成功了一半,而另一半来自于输赢的判断,大家玩游戏都希望赢,所以一个判断标准也很重要。上面我有提到几种可能性,在这里我用的标准是 :  

【箱子碰到死角无法推动】为输,【地图上没有箱子】为赢

在这里我们可以用变量来标记三种状态:flag=0 游戏继续;flag=1 游戏失败;flag=2,游戏获胜。

下面做分类讨论: 

首先是赢的条件:当地图上没有箱子时,游戏即获胜。即数字里面找不到2时;

其次是输的情况:要构成死角,则至少四个面中要有两个面是墙,如此之下,便无法移动。

下面是输赢判断标准部分的代码:

int flag;
void  judge()
{
	flag=2;//初值
	for(int i=0;i<11;i++)//行
	{
		for(int j=0;j<13;j++)//列
		{
			if(map[i][j]==2)
			{
				//表明未结束
				flag=0;
				if(map[i-1][j]==1||map[i+1][j]==1)
				{
					//找死角的墙
					if(map[i][j-1]==1||map[i][j-1]==1)
					{
						//游戏结束                   
						flag=1;						//flag 分类
						return;						//=0 继续 
													//=1 结束
													//=2  赢
						
					}
				}
			}
		}
	}
}

 有了判断标准,我们还需要提示框来告知玩家他是输是赢,所以需要再加上一些提示盒子。

void  box()
{
	if(flag==1)
	{
		MessageBox(GetHWnd(),L"抱歉,你输了。",L"LOSE",MB_OK);//头文件为windows.h   有图形库时可不加
	}
	else
	{
		MessageBox(GetHWnd(),L"恭喜,你赢了!",L"VICTORY",MB_OK); 
	}
}

备注: 这里我们用到了MessageBox函数,使用该函数后将会弹出提示窗体,方便玩家看到结果,至于该函数的详细信息可以自行了解。

到了这里,整个输赢判断模块便真正结束了,而整个游戏的模块也基本成型了,下面我们将再添加一些优化,比如开始页面的添加,音乐的添加等。

4.开始页面及音乐的添加

               我们在最开始可以添加一个开始页面,给玩家一些提示,并且进一步完善游戏的模块。

备注:该模块的添加可根据需求自行设计。

我所添加的开始页面代码如下:


IMAGE iae;
void tip()
{
	loadimage(&iae,L"logo.jpg",780,360);
	putimage(0,0,&iae);
	settextcolor(LIGHTCYAN);
	settextstyle(24,0,_T("黑体"));
	outtextxy(240,360,_T("开始游戏    请按 B/b "));
	outtextxy(240,420,_T("移动请按   wasd/WASD"));
	outtextxy(240,480,_T("!试试把箱子推到目的地!"));
	outtextxy(480,600,_T("------拾光异世出品------"));
}

备注:这里有用到在图形库下的文字输出及格式和颜色设置。 

除了开始页面,我们还可以加一些音乐,比如游戏进行时的音乐,玩家移动时的音乐,游戏胜利时的音乐等。

在添加音乐之前我们需要添加一些头文件和库:

//加音乐的头文件与库
#include<mmsystem.h>
#pragma comment(lib,"WINMM.LIB")

然后是加音乐:可以分别在图片加载函数,移动设计函数,提示盒子函数里添加相对应的音乐。

//图片加载函数
mciSendString(L"open back.mp3  alias bgm",0,0,0);//具体用法可从帮助文档中了解
mciSendString(L"play bgm repeat",0,0,0);
//移动设计函数
PlaySound(L"Boxmove.WAV",nullptr,SND_FILENAME | SND_ASYNC);
//提示盒子函数
PlaySound(L"success.wav",nullptr,SND_FILENAME | SND_ASYNC);

进行完上述四个部分,我们便完成了大部分的设计任务,只剩下最后一步,把各个模块之间通过main函数组合起来。

5.main函数部分

在用main函数组合之前,我们需要考虑一个问题,我们要如何组织这几大模块,

仔细思考,应该先是开始页面,再然后的话,因为我们是要每移动一次便绘制一次地图,所以应该是在一个循环里面绘图(初始化),移动,绘图。判断,移动······

main函数部分代码(考虑到与开始页面的衔接,我们可以加一些衔接代码):

int main()
{
	initgraph(780,660);//每个方块大小60*60   窗口大小780*660
	tip();
	if(getch()=='B'||getch()=='b')
	{
		begin();

		while(1)
		{
			drawmap();
			judge();
			if(flag)  break;//判断是否结束
			play();
		}
	
		box();
	}
	getchar();
	closegraph();//关闭窗口
	return 0;
}

备注:用easyx进行绘图时,要先建立绘图窗口,并且在游戏结束后关闭该窗口。

 在将几大模块组合在一起时,整个设计过程便可以说接近尾声,我们的游戏便可以正常运行了。


 四、效果展示

最后我们一起看看效果图:

 

如果需要素材或者参考源码的话,可以通过网盘提取:

链接:https://pan.baidu.com/s/153nVLE8htqaeDuBSzYuyMA 
提取码:a8u1 


五、作者的话

                虽然说上面的游戏到最后仍然很简陋,有着各种问题,诸如无法重新开始,判断机制不够完善等,但是也实现了推箱子游戏的最基本的功能,任务呢,也算是圆满完成啦。至于后续的优化,代码添加,我会继续努力的!!!

最后再说一句:希望自己在学习编程的道路上继续前进!  加油,少年!!!

  • 12
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
餐饮管理系统是用C语言EasyX和MFC开发的一款软件。它主要用于餐饮企业进行订单管理、库存管理、财务管理和人事管理等各项业务的管理工作。 首先,餐饮管理系统可以实现订单管理功能。通过系统,餐饮企业可以方便地记录客户的订单信息,包括订单编号、下单时间、商品种类和数量等。同时,系统还可以自动计算订单的总金额,并生成相应的发票,方便企业进行财务结算。 其次,餐饮管理系统还可以进行库存管理。系统可以记录每一种商品的库存数量,并根据销售情况进行动态调整。一旦库存不足,系统会自动生成补货提醒,以便及时补充商品,保证供应链的畅通。 此外,餐饮管理系统还拥有财务管理功能。它可以自动生成各类财务报表,如销售额报表、成本报表和利润报表等,为企业提供全面的财务数据分析。同时,系统还可以进行财务流水账的记账工作,方便企业进行日常的财务管理。 最后,餐饮管理系统还可以进行人事管理。系统可以记录员工的基本信息、考勤情况和薪资结算等。通过系统,企业可以方便地进行员工的薪资发放和考勤统计管理,提高人力资源的利用效率。 总之,餐饮管理系统利用C语言EasyX和MFC开发,具备订单管理、库存管理、财务管理和人事管理等多项功能。它可以帮助餐饮企业提高运营效率,降低成本,实现科学管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值