IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言+easyx图形库 推箱子游戏1.0 -> 正文阅读

[C++知识库]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?


五、作者的话

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

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

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-05 21:32:58  更:2022-02-05 21:33:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:44:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码