游戏实现步骤:数组勾画地图–控制人物移动–人物移动推动箱子移动。
数组勾画地图:
int map[20][10][10];//设置10*10的地图,设置20关
int mubiao[20][5][2];//用一个三维数组记录目的地的坐标
int iftab=0;//在游戏中利用这个变量记录是否重置关卡
int guan;
int makeitback=0;//为人站在空位和目的地上进入目的地作不同的移动
IMAGE img[5];
IMAGE zhuyebj, guanqiabj;
void setmapdate()//地图数据放在txz_map_in.txt,先输入数据
{
freopen("D:\\cpp\\终极推箱子\\Debug\\txz_map_in.txt", "r", stdin);//打开文件
for (int i = 0; i < 20; i++)//20关
{
for (int j = 0; j < 10; j++)//纵向
{
for (int k = 0; k < 10; k++)//横向
{
cin >> map[i][j][k];//输入每个数据
if (map[i][j][k] == 6 && iftab==0)//其中6就是目的地,将目的地的坐标记录入mubiao数组
{
for (int L = 0; L < 5; L++)
{
if (mubiao[i][L][0] == 0 && mubiao[i][L][1] == 0)//找到数组中空的位置
{
mubiao[i][L][0] = k;
mubiao[i][L][1] = j;
break;
}
}
}
}
}
}
loadimage(img + 0, _T("D:\\cpp\\终极推箱子\\Debug\\image\\1.jpg"));//加载若干图片
loadimage(img + 1, _T("D:\\cpp\\终极推箱子\\Debug\\image\\3.jpg"));
loadimage(img + 2, _T("D:\\cpp\\终极推箱子\\Debug\\image\\5.jpg"));
loadimage(img + 3, _T("D:\\cpp\\终极推箱子\\Debug\\image\\6.jpg"));
loadimage(img + 4, _T("D:\\cpp\\终极推箱子\\Debug\\image\\背景.jpg"), 640, 640);
loadimage(&zhuyebj, _T("D:\\cpp\\终极推箱子\\Debug\\image\\主页背景.jpg"), 640, 640);
loadimage(&guanqiabj, _T("D:\\cpp\\终极推箱子\\Debug\\image\\关卡背景.png"), 640, 640);
fclose(stdin);//关闭文件
}
void mapcreate()//开始绘画地图
{
putimage(0, 0, &img[4]);//输出背景图片
for (int i = 0; i < 10; i++)
{
int x, y;
for (int j = 0; j < 10; j++)
{
x = 64 * j;//64是图片大小
y = 64 * i;
switch (map[guan][i][j])
{
case 1: {putimage(x, y, &img[0]);
break; } //墙
case 0: {
cout << " "; break; }//空位
case 5: {putimage(x + 16, y, &img[2]);
break; }//人
case 3: { putimage(x, y, &img[1]);
break; }//箱子
case 6: { putimage(x + 16, y + 16, &img[3]);
break; }//箱子目标位置
}
if (map[guan][i][j] == 5)//获取人物初始位置
{
nowmany = i;
nowmanx = j;
}
}
}
}
人物移动:
int makieback2=0;//为箱子站在空位和目的地上进入目的地作不同的移动
void manmove(char a, int& x, int& y)
{
int temp;
if (total_mubiao == 3)
makeitback = 0;
switch (a)
{
case 'w':
{
if (map[guan][y - 1][x] != 1)//当人移动前方不是墙时,直接交换位置
{
if (map[guan][y - 2][x] != 1 && map[guan][y - 1][x] == 3)//当人移动前方是箱子且箱子前不是墙时,让箱子移动
{
nowboxx = x;
nowboxy = y - 1;
boxmove(a, nowboxx, nowboxy);//箱子移动
}
if (map[guan][y - 1][x] == 0 || map[guan][y - 1][x] == 6)当是空位或者是目的地的时
{
if (map[guan][y - 1][x] != 6 && makeitback == 0)//当是空位时,直接交换数组两个元素位置
{
temp = map[guan][y][x];
map[guan][y][x] = map[guan][y - 1][x];
map[guan][y - 1][x] = temp;
}
else // 当是目的地时
{
if (makeitback == 0)//原本人站的地方不是目的地时
{
map[guan][y][x] = 0;
map[guan][y - 1][x] = 5;
makeitback = 1;
total_mubiao--;
}
else//原本人站的地方时目的地时
{
if (map[guan][y - 1][x] != 6)//作判断
total_mubiao++;
map[guan][y][x] = 6;
map[guan][y - 1][x] = 5;
}
}
}
}
break;
}//其他方向移动
**箱子移动:**原理同人物移动
void boxmove(char a, int& x, int& y)
{
int temp;
if (!ifthesame(x, y)) //推的箱子不是在目的地上
{
makeitback2 = 0;
}
else//推的箱子在目的地上
{
makeitback2 = 1;
}
switch (a)
{
case 'w':
{
if (map[guan][y - 1][x] == 3)//箱子前时箱子时,直接返回
return;
if (map[guan][y - 1][x] != 6 && makeitback2==0 )//箱子前不是目的地时,直接交换数组两元素的位置
{
temp = map[guan][y][x];
map[guan][y][x] = map[guan][y - 1][x];
map[guan][y - 1][x] = temp;
total_mubiao2--;
}
else
{
if (makeitback2 == 0)//当箱子站在空位上时
{
map[guan][y][x] = 0;
map[guan][y - 1][x] = 3;
makeitback2 = 1;
total_mubiao2--;
}
else//当箱子站在目的地上时
{
map[guan][y][x] = 6;
map[guan][y - 1][x] = 3;
total_mubiao2 = 3;
makeitback2 = 0;
}
}
break;
}//其他方向同上
```
**获取人物的位置:**
```
int getmanx()//得到人物的x坐标
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (map[guan][i][j] == 5)
{
nowmanx = j;
}
}
}
return nowmanx;
}
int getmany()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (map[guan][i][j] == 5)
{
nowmany = i;
}
}
}
return nowmany;
}
bool ifthesame(int x, int y)//判断箱子是否站在目的地上
{
for (int i = 0; i < 5; i++)
{
if (mubiao[guan][i][0] == x && mubiao[guan][i][1] == y)
return 1;
}
return 0;
}
判断胜利的函数:
void win()
{
int countmb = 0, totalmb = 0;//countmb是人物完成了几个目的地,totalmb是总共有几个目的地
if (guan < 10)//1-10关设置了2个目的地
{
totalmb = 2;
}
else//11-20关设置3个目的地
{
if (guan < 20)
totalmb = 3;
}
for (int i = 0; i < 5; i++)
{
if (map[guan][mubiao[guan][i][1]][mubiao[guan][i][0]] == 3)//当目的地的坐标上的时箱子时
countmb++;
}
if (countmb == totalmb)//当人物完成了总的目的地时
{
settextstyle(32, 0, 0);//设置字体的大小
outtextxy(150, 320, _T("通过此关,进入下一关请按Enter"));//输出文字
if (_getch() == 13)//当玩家按下enter。
{
guan++; jguan++;
}
}
}
制作游戏界面:
主界面:
bool a;//退出鼠标循环事件
void mainsite()
{
guan = 0;//回到主界面重置关卡
cleardevice();//清屏
putimage(0, 0, &zhuyebj);//输出主页的背景图片
settextcolor(GREEN);//字体颜色
settextstyle(0, 0, 0);
outtextxy(230, 0, _T("欢迎来到[终极推箱子]"));
settextcolor(RED);
outtextxy(275, 100, _T("主菜单"));
settextcolor(YELLOW);
outtextxy(260, 200, _T("1.开始游戏"));
outtextxy(260, 240, _T("2.选择关卡"));
outtextxy(260, 280, _T("3.游戏帮助"));
system("pause");
a = 0;
mousecontrol();//设置鼠标事件
}
void mousecontrol()
{
MOUSEMSG m;
while (1)
{
m = GetMouseMsg();//获取鼠标的信息
if (m.uMsg == WM_LBUTTONDOWN)//当鼠标按下左键
{
a = 1
if ((m.x >= 260 && m.x <= 340) && (m.y >= 200 && m.y <= 215))//判断鼠标左键的位置是否在“开始游戏”上
{
guan = 0;
gamesite();
}
if ((m.x >= 260 && m.x <= 340) && (m.y >= 240 && m.y <= 255))判断鼠标左键的位置是否在“选择关卡”上
{
guanchoose();
}
if ((m.x >= 260 && m.x <= 340) && (m.y >= 280 && m.y <= 295))//判断鼠标左键的位置是否在“游戏帮助”上
{
gamehelp();
}
}
if (a == 1)break//按下左键后结束循环
}
}
关卡选择界面:
void guanchoose()//进入选择关卡界面
{
cleardevice();//清屏
putimage(0, 0, &guanqiabj);//输出界面图片
system("pause");
int inix = 10, iniy = 70, count = 0, x, y;//
bool ifback = 0;
MOUSEMSG m;
while (1)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN)//按下左键时
{
for (int i = 0; i < 8; i++)//设置每个关卡点击有效的位置
{
for (int j = 0; j < 9; j++)
{
x = 70 * (j + 1) + inix;
y = 70 * (i + 1) + iniy;
if (m.x >= inix && m.x <= x && m.y >= iniy && m.y <= y)//当点击的位置在某个关卡的范围里
{
guan = 8 * i + j; ifback = 1; break;
}
}
if (ifback == 1)break;//若选择了关卡则退出循环
}
if (m.x >= 0 && m.x <= 140 && m.y >= 0 && m.y <= 70)//判断点击在“返回”上
{
mainsite(); ifback = 1; break;
}
}
if (ifback == 1)break;//退出循环
}
}
游戏界面:
bool iftab=0;
void gamesite()
{
while (1)
{
cleardevice();//清屏
mapcreate();//勾画地图
instruct = _getch();//等待按下按键
if (instruct == 27)//当按下esc时返回主界面
mainsite();
if (instruct == 9)//当按下tab时重置此关卡
{
iftab = 1;
setmapdate();
cleardevice();
mapcreate();
instruct = _getch();
}
nowmanx = getmanx();//实时获取人物的坐标
nowmany = getmany();
manmove(instruct, nowmanx, nowmany);//人物移动
cleardevice();//清屏
mapcreate();//输出地图,显示人物移动
win();//判断是否胜利
}
}
游戏帮助界面:
void gamehelp()
{
cleardevice();
putimage(0, 0, &zhuyebj);
settextstyle(30, 0, 0);
outtextxy(250, 0, _T("游戏帮助"));
settextstyle(20, 0, 0);
settextcolor(GREEN);
outtextxy(90, 100, _T("1.向上移动:w"));
outtextxy(220, 100, _T("向下移动:s"));
outtextxy(340, 100, _T("向左移动:a"));
outtextxy(460, 100, _T("向右移动:d"));
outtextxy(90, 130, _T("2.按下ESC返回"));
outtextxy(90, 160, _T("3.游戏进行时按下TAB重置关卡"));
instruct = _getch();
if (instruct == 27)//按下esc返回
mainsite();
}
```
主函数:
int main()
{
setmapdate(); //设数据
system("title 终极推箱子");//设置标题
initgraph(640, 640);//初始化窗口
PlaySound(_T("D:\\cpp\\终极推箱子\\Debug\\背景音乐.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//循环播放背景音乐
while (1)//进入游戏
{
mainsite();
gamesite();
}
closegraph();//关闭窗口
system("pause");
return 0;
}
这是游戏效果图:
利用简单的easyx图形库做出来的,就只能做到这种效果了。
记录这个小游戏的收获:
一.EasyX图形库的使用:
要包括头文件<graphics.h>
图像
:IMAGE img;
loadimage( img,//图片地址//,width,height)//保存图片;图片对象,图片名,宽度,长度;图片名用LPCTSTR类型
putimage(x,y,&img)//输出图片;绘制的x坐标,绘制的y坐标,图片名
getimage(&img,sx,sy,x,y)//从当前绘图设备获取图像;图片名,要获取图像左上角x坐标,y坐标,要获取图像区域的宽度
cleardevice()//清空屏幕,用当前前景色清空屏幕。
initgraph(w,h)//初始化屏幕;宽度,高度
closegraph()//关闭图形环境
文字:
outtextxy(x,y,str)//xy是头字母的坐标,str是 LPCTSTR类型
gettextcolor(COLORREF);//获取当前字体字体颜色
settextcolor(COLORREF);//设置字体颜色
settextstyle()//设置字体样式
鼠标:
MOUSEMSG m;
m=GetMouseMsg()//获取鼠标信息
MouseHit();//检测是否有鼠标信息
struct MOUSEMSG
{
UINT uMsg; // 当前鼠标消息
bool mkCtrl; // Ctrl 键是否按下
bool mkShift; // Shift 键是否按下
bool mkLButton; // 鼠标左键是否按下
bool mkMButton; // 鼠标中键是否按下
bool mkRButton; // 鼠标右键是否按下
int x; // 当前鼠标 x 坐标(物理坐标)
int y; // 当前鼠标 y 坐标(物理坐标)
int wheel; // 鼠标滚轮滚动值
};
值
含义
WM_MOUSEMOVE
鼠标移动消息。
WM_MOUSEWHEEL
鼠标滚轮拨动消息。
WM_LBUTTONDOWN
左键按下消息。
WM_LBUTTONUP
左键弹起消息。
WM_LBUTTONDBLCLK
左键双击消息。
WM_MBUTTONDOWN
中键按下消息。
WM_MBUTTONUP
中键弹起消息。
WM_MBUTTONDBLCLK
中键双击消息。
WM_RBUTTONDOWN
右键按下消息。
WM_RBUTTONUP
右键弹起消息。
WM_RBUTTONDBLCLK
右键双击消息。
有问题或者意见的可以加我QQ一起讨论。QQ:295390431
有想要体验这个游戏的也可以找我要!
二:打开文件
FILE *freopen(char *filename, char *type, FILE *stream);
type:”r”读文件,”w”写文件
stream:stdin读文件,stdout写文件
利用cin输入文件里的每个数据
fclose(stdin;
fclose(stdout);
三:播放音乐函数
PlaySound函数:
#include<windows.h>
#include <mmsystem.h>
#pragma comment(lib, “WINMM.LIB”)
BOOL PlaySound(LPCSTR pszSound, HMODULE hwnd,DWORD fdwSound);
pszSound是文件名的字符串,必须是wav类型的音乐
hwnd是应用程序的实例句柄,除非pszSound的指向一个资源标识符(即fdwSound被定义为SND_RESOURCE),否则必须设置为NULL。
一般循环播放:PlaySound(//名字//, NULL,SND_FILENAME | SND_ASYNC | SND_LOOP);
有问题或者意见的朋友可以加我QQ:295390431
有想体验这个游戏的也可以找我要!