基于EasyX的推箱子游戏

一、预备知识

1.使用EasyX必须要知道的一些基础函数
2.选择结构 if , switch
3.循环结构 for, while
4.多维数组 arr1[N], arr2[N][N] , arr3[N][N][N]
5.函数封装

二、游戏逻辑

想要写出推箱子,首先要知道推箱子游戏都有哪些元素和规则

1.推箱子元素

游戏元素

1.小人 2.箱子 3.空地 4.墙壁 5.目的地 6.到达目的地的箱子

2.推箱子规则

1.“小人”只能在“空地”和“目的地”上行走
2.“小人”可以推“箱子后面是 ‘空地’和‘目的地’ ”的“箱子”
3.所有“箱子”到达“目的地”游戏获胜

三、游戏设计

知道游戏元素和规则就可以开始设计游戏了

1.地图设计

首选需要知道的是,游戏地图是一个二维数组
根据玩推箱子的经验可以知道,游戏中会出现哪些组合情况

  1. “小人”在“目的地”
  2. “箱子”在“目的地”

下面我们给这些情况定义一些变量,数字大家可以随意,对应就好

enum material
{
	space=0,//空地
	wall=1,//墙壁
	box=3, //箱子
	person=4,//小人
	aim=5,//目的地	
	box_aim=8,//箱子在目的地 3+5=8
	person_aim=9,//小人在目的地  4+5=9
};

元素和数字已经对应起来了,先写一个初始化加载图片函数Loadimg(),素材就放在源文件旁边

#define SIZE 35//每个元素的大小

IMAGE img[10];//存放小图片

void Loadimg()//加载资源
{
	loadimage(&img[0],L"./images/0.jpg",SIZE,SIZE);//空地
	loadimage(&img[1],L"./images/1.jpg",SIZE,SIZE);//墙壁
	loadimage(&img[3],L"./images/3.jpg",SIZE,SIZE);//箱子
	loadimage(&img[4],L"./images/4.jpg",SIZE,SIZE);//小人
	loadimage(&img[5],L"./images/5.jpg",SIZE,SIZE);//目的地
	loadimage(&img[8],L"./images/8.jpg",SIZE,SIZE);//箱子在目的地	
}

然后你就知道为什么游戏地图是一个二维数组

在这里插入图片描述

是不是switch,case根据数字贴图就完事了,就是这么easy,一关怎么能行呢,当然要很多关,二维不够三维来凑,定义一个全局变量map三维数组,和全局变量number存放关卡数

int number=0;//存放关卡数,当前第一关
int map[3][7][7]=
{   //第一关
	1,1,1,1,1,1,1,
	1,5,0,0,0,5,1,
	1,0,3,0,3,0,1,
	1,0,0,4,0,0,1,
	1,0,3,0,3,0,1,
	1,5,0,0,0,5,1,
	1,1,1,1,1,1,1,
	//第二关
	1,1,1,1,1,1,1,
	1,5,5,5,5,5,1,
	1,0,0,3,0,0,1,
	1,0,3,3,3,0,1,
	1,0,0,3,0,0,1,
	1,0,0,4,0,0,1,
	1,1,1,1,1,1,1,
	//第三关
	1,1,1,1,1,1,1,
	1,0,0,0,0,0,1,
	1,5,1,5,1,3,1,
	1,0,3,0,5,0,1,
	1,3,1,3,1,0,1,
	1,4,0,0,0,5,1,
	1,1,1,1,1,1,1,
};

地图定义好了,那就贴图吧,写一个Drawmap()函数画地图

#define ROWS 7//行数
#define COLS 7//列数

void Drawmap()
{
	int i,j,x,y;
	for (i = 0; i < ROWS; i++)
	{
		for (j = 0; j < COLS; j++)
		{
			x=0;y=0;
			x += j * SIZE, y += i * SIZE;//确定每个图片的坐标
			switch (map[number][i][j])
			{
				case space://空地
					putimage(x, y, &img[space]);
					break;
				case wall://墙壁
					putimage(x, y, &img[wall]);
					break;
				case box://箱子
					putimage(x, y, &img[box]);
					break;
				case person://小人
					putimage(x, y, &img[person]);
					break;
				case aim://目的地
					putimage(x, y, &img[aim]);
					break;
				case box_aim://箱子在目的地
					putimage(x, y, &img[box_aim]);
					break;
				case person_aim://人在目的地还是人
					putimage(x, y, &img[person]);
					break;
			}
		}
		printf("\n");
	}
	system("cls");//清屏
}

2.移动设计

上文提到

1.“小人”只能在“空地”和“目的地”上行走
2.“小人”可以推“箱子后面是 ‘空地’和‘目的地’ ”的“箱子”

那么每次移动完都需要确定小人的位置,再判断能否移动

先定义全局变量记录小人位置,再写一个获取小人位置的函数Getpersonxy()

int ipos,jpos;//记录小人位置

void Getpersonxy()
{
	int i,j;
	for (i = 0; i < ROWS; i++)
	{	
		for (j = 0; j < COLS; j++)
		{
			if(map[number][i][j]==person || map[number][i][j]==person_aim)
			{//找到小人 或者 小人在目的地
				ipos=i;
				jpos=j;//找到小人位置
				break;
			}
		}
	}
}

找到小人位置后判断小人是否能移动,写一个Moveperson()函数,这个就要划重点了

void Moveperson()
{
	PlaySound(L"./images/move.wav", nullptr, SND_FILENAME | SND_ASYNC);//播放移动音乐
	char ch = _getch();
	switch (ch)//控制小人走
	{
		case 'w':
		case 'W':
		case 72://小键盘键值
		if (map[number][ipos-1][jpos] == space || map[number][ipos-1][jpos] == aim)
		{//人前面是空地或者目的地
			map[number][ipos-1][jpos]+=person;//人来了
			map[number][ipos][jpos]-=person;//人走了
		}
		else if (map[number][ipos-1][jpos] == box || map[number][ipos-1][jpos] == box_aim)
		{//人前面是箱子或者箱子在目的地
			//判断箱子是否能走
			if (map[number][ipos-2][jpos] == space || map[number][ipos-2][jpos] == aim)//箱子前面是空地或者目的地 才能走
			{
				map[number][ipos-2][jpos]+=box ; //箱子来了
				map[number][ipos-1][jpos]+=person-box ;//人来了 箱子走了 
				map[number][ipos][jpos]-=person;//人走了
			}
		}
		break;
	case 's':
	case 'S':
	case 80://小键盘键值
	    if (map[number][ipos+1][jpos] == space || map[number][ipos+1][jpos] == aim)
		{//人前面是空地或者目的地
			map[number][ipos+1][jpos]+=person;//人来了
			map[number][ipos][jpos]-=person;//人走了
		}
		else if (map[number][ipos+1][jpos] == box || map[number][ipos+1][jpos] == box_aim)
		{//人前面是箱子或者箱子在目的地
			//判断箱子是否能走
			if (map[number][ipos+2][jpos] == space || map[number][ipos+2][jpos] == aim)//箱子前面是空地或者目的地 才能走
			{
				map[number][ipos+2][jpos]+=box ; //箱子来了
				map[number][ipos+1][jpos]+=person-box;//人来了 箱子走了 
				map[number][ipos][jpos]-=person;//人走了
			}
		}
		break;
	case 'a':
	case 'A':
	case 75://小键盘键值
		if (map[number][ipos][jpos-1] == space || map[number][ipos][jpos-1] == aim)
		{//人前面是空地或者目的地
			map[number][ipos][jpos-1]+= person;//人来了
			map[number][ipos][jpos]-= person;//人走了
		}
		else if (map[number][ipos][jpos-1] == box || map[number][ipos][jpos-1] == box_aim)
		{//人前面是箱子或者箱子在目的地
			//判断箱子是否能走
			if (map[number][ipos][jpos-2] == space || map[number][ipos][jpos-2] == aim)//箱子前面是空地或者目的地 才能走
			{
				map[number][ipos][jpos-2]+=box ; //箱子来了
				map[number][ipos][jpos-1]+=person-box ;//人来了 箱子走了 
				map[number][ipos][jpos]-=person;//人走了
			}
		}
		break;
	case 'd':
	case 'D':
	case 77://小键盘键值
		if (map[number][ipos][jpos+1] == space || map[number][ipos][jpos+1] == aim)
		{//人前面是空地或者目的地
			map[number][ipos][jpos+1]+=person;//人来了
			map[number][ipos][jpos]-=person;//人走了
		}
		else if (map[number][ipos][jpos+1] == box || map[number][ipos][jpos+1] == box_aim)
		{//人前面是箱子或者箱子在目的地
			//判断箱子是否能走
			if (map[number][ipos][jpos+2] == space || map[number][ipos][jpos+2] == aim)//箱子前面是空地或者目的地 才能走
			{
				map[number][ipos][jpos+2]+=box ; //箱子来了
				map[number][ipos][jpos+1]+=person-box ;//人来了 箱子走了 
				map[number][ipos][jpos]-=person;//人走了
			}
		}
		break;
	}
}

3.结束设计

上文提到

3.所有“箱子”到达“目的地”游戏获胜**

也就是判断地图上是否有box,如果有,游戏继续,没有box,进入下一关,写一个Gameover()函数

int Gameover()
{
	int i, j;
	for (i = 0; i < ROWS; i++)
	{
		for (j = 0; j < COLS; j++)
		{
			//遍历地图是否有箱子 
			if (map[number][i][j] == box)
			{
				return 0;//有箱子退出循环 继续
			}
		}
	}
	return 1;
}

4.整体设计

下面把上面的函数组合起来就是推箱子游戏,再来点音乐

#include<stdio.h>
#include<easyx.h>//图形库
#include<conio.h>//按键
#include<mmsystem.h>//音乐
#pragma comment(lib,"winmm.lib")//库文件

int main()
{
	initgraph(SIZE*7,SIZE*7);//创建地图大小的窗口
	Loadimg();//加载资源
	//循环播放背景音乐
	mciSendString(L"open ./images/bg.mp3 ", 0, 0, 0);
	mciSendString(_T("play ./images/bg.mp3 repeat"), 0, 0, 0);
	while(true){
		//绘制界面
		BeginBatchDraw();
		Drawmap();//贴地图
		EndBatchDraw();
		if (Gameover())
		{	
			PlaySound(L"./images/success.wav", nullptr, SND_FILENAME | SND_ASYNC);//播放胜利音乐
			number++;//进入下一关
			Sleep(500);
			if (number>= 3)
				break;//第三关玩完结束
		}
		if (_kbhit())//获取按键消息
		{
			Getpersonxy();//找到小人位置
			Moveperson();//小人移动
		}	
	}
	mciSendString(L"close ./images/bg.mp3",0,0,0);//关闭背景音乐
	setbkmode(0);//设置文字背景透明
	settextcolor(RGB(167, 48, 48));//设置字体颜色
	settextstyle(30, 0, _T("宋体"));//64是字体大小 0是自适应 双引号里可以填字体名字
	outtextxy(0, 110, _T("游戏结束,你真棒!"));
	Sleep(5000);
	closegraph();//关闭窗口
	return 0;
}

把上面所有代码复制到一个cpp文件里,再把素材改好命名放到images文件夹里,images文件夹在cpp文件旁边,就可以编译运行了!

图片音乐素材及可执行程序需要的点击下载

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值