前言
使用easyX库,基于c/c++实现推箱子小游戏。
作者使用的是VS2010版本。
目录
前言
一、游戏截图
二、easyX库安装
三、代码实现
1.所有代码
2.具体实现过程
总结
一、游戏截图
代码中使用了两张图片,分别是熊猫头像,还有箱子,像素都是40x40;可以直接截图保存到工程目录下。图片名字请分别命名为 "player.png" "box.png" 。
二、easyX库安装
EasyX Graphics Library for C++
进入以上链接,下载并安装easyX库
三、代码实现
1.所有代码
可直接拷贝,并运行推箱子小游戏
#include "stdafx.h"
#include<graphics.h>
#include<conio.h>
#include<stdio.h>#define TOTALWIDTH 400
#define TOTOALHEIGHT 500
#define MAP1 0
#define MAP2 100
#define MAP3 400
#define MAP4 500
#define ESC 27#define WIDTH 10
#define HEIGHT 10
#define TOTALLEVEL 2typedef struct _GAME_PUTBOX
{char direction; // 储存键盘按的方向:上 下 左 右int x,y; // 玩家当前坐标int boxs; // 玩家需要完成的箱子数:箱子数为0时,跳到下一关int level; // 玩家当前关卡数
}GAME_PUTBOX;enum MOVE_DIRECTION
{NONE, // 无方向MOVEUP, // 向上移动MOVELEFT, // 向左移动MOVEDOWN, // 向下移动MOVERIGHT, // 向右移动
};enum MEMBER_ARRAY
{EMPTY, // 0 表示空地WALL, // 1 表示墙壁PLAYER, // 2 表示玩家BOX, // 3 表示箱子AIM, // 4 表示目的地FINISH, // 5 表示箱子站在目的地上AIMPLAYER, // 6 表示人站在目的地上
};const int boxMap[TOTALLEVEL][HEIGHT][WIDTH] =
{ // 游戏总关卡// level 1{{WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL},{WALL, WALL, WALL, WALL, AIM, WALL, WALL, WALL, WALL, WALL},{WALL, WALL, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, WALL, WALL},{WALL, WALL, EMPTY, EMPTY, BOX, EMPTY, BOX, AIM, WALL, WALL},{WALL, WALL, AIM, EMPTY, BOX, PLAYER, EMPTY, EMPTY, WALL, WALL},{WALL, WALL, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, WALL, WALL},{WALL, WALL, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, WALL, WALL},{WALL, WALL, EMPTY, EMPTY, EMPTY, BOX, EMPTY, EMPTY, WALL, WALL},{WALL, WALL, WALL, WALL, WALL, AIM, WALL, WALL, WALL, WALL},{WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL}},// level 2{{WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, EMPTY, WALL},{WALL, WALL, WALL, AIM, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY},{WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, EMPTY, EMPTY},{WALL, WALL, EMPTY, EMPTY, BOX, EMPTY, BOX, AIM, EMPTY, WALL},{WALL, WALL, AIM, EMPTY, BOX, PLAYER, EMPTY, EMPTY, EMPTY, WALL},{WALL, WALL, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, WALL, WALL},{WALL, WALL, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, WALL, WALL},{WALL, WALL, EMPTY, EMPTY, EMPTY, BOX, EMPTY, EMPTY, WALL, WALL},{WALL, WALL, WALL, WALL, WALL, AIM, WALL, WALL, WALL, WALL},{WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL}}
};GAME_PUTBOX player; // 玩家数据
IMAGE img_player; // 玩家图片
IMAGE img_box; // 箱子图片int currentMap[HEIGHT][WIDTH] =
{ // 当前显示的地图,根据玩家游戏进程,实时更新};void putboxrun(void); // 推箱子游戏主函数
void putboxinit(void); // 初始化地图及数据
void resetputbox(void); // 重置本关卡
void drawMap(void); // 绘制地图
void putboxMove(void); // 玩家移动处理int main(void)
{putboxrun();return 0;
}/*****************//*****************//*****************//***********************
//* 函数名称:putboxrun
//* 功能描述:推箱子主函数
//*****************//*****************//*****************//************************/
void putboxrun(void)
{int key;putboxinit(); // 初始化地图、数据while(1){drawMap(); // 每次按键之后都会更新地图if(!player.boxs){ // 完成全部箱子,等级加1,进行下一关player.level++;if(player.level > TOTALLEVEL){ // 如果完成了所有关卡,则结束游戏break;}resetputbox(); // 更新下一关数据continue;}key = _getch(); // 获取用户按键player.direction = NONE; // 先清除移动方向switch(key){case 'w':case 'W':player.direction = MOVEUP;break;case 'a':case 'A':player.direction = MOVELEFT;break;case 's':case 'S':player.direction = MOVEDOWN;break;case 'd':case 'D':player.direction = MOVERIGHT;break;case ESC:return;case 'r':case 'R':resetputbox();continue;break;default:break;}putboxMove(); // 根据玩家移动方向,进行处理}_getch();
}/*****************//*****************//*****************//***********************
//* 函数名称:putboxinit
//* 功能描述:推箱子初始化
//*****************//*****************//*****************//************************/
void putboxinit()
{initgraph(TOTALWIDTH, TOTOALHEIGHT); // 初始化窗口,设置窗口大小HWND window = GetHWnd(); // 获取当前窗口SetWindowText(window, "推箱子 - by耒阳阿杰"); // 设置当前窗口的标题outtextxy(5,5,"ESC: 退出"); // 设置提示信息outtextxy(80,5,"R: 重置本关");outtextxy(5,30,"W: 上 A:左 S:下 D:右");fillrectangle(MAP1,MAP2,MAP3,MAP4); // 划分游戏区域player.level = 1; // 初始等级为1loadimage(&img_player,"player.png",40,40); // 加载玩家图片loadimage(&img_box,"box.png",40,40); // 加载玩家图片resetputbox();
}/*****************//*****************//*****************//***********************
//* 函数名称:resetputbox
//* 功能描述:重置本关
//*****************//*****************//*****************//************************/
void resetputbox()
{int i,j;int uy,ux;uy = (MAP4 - MAP2) / HEIGHT;ux = (MAP3 - MAP1) / WIDTH;player.boxs = 0;for(i = 0; i < HEIGHT;i++){for(j = 0; j < WIDTH; j++){currentMap[i][j] = boxMap[player.level - 1][i][j];if(currentMap[i][j] == BOX){ // 每检测到一次箱子,箱子数加1player.boxs++;}if(currentMap[i][j] == PLAYER){ // 记录玩家位置player.x = j;player.y = i;}}}}/*****************//*****************//*****************//***********************
//* 函数名称:drawMap
//* 功能描述:绘制关卡地图
//*****************//*****************//*****************//************************/
void drawMap()
{int i,j;int uy,ux;char ch[10];uy = (MAP4 - MAP2) / HEIGHT;ux = (MAP3 - MAP1) / WIDTH;sprintf_s(ch, "%1s%1u", "level: ",player.level);settextcolor(LIGHTRED);settextstyle(30,30,0);outtextxy(100,60,ch); // 显示当前等级// 绘制地图for(i = 0; i < HEIGHT;i++){for(j = 0; j < WIDTH; j++){switch(currentMap[i][j]){case EMPTY: // 空地setfillcolor(CYAN); // 选择填充颜色fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy); // 填充相应区域break;case WALL: // 墙墙setfillcolor(DARKGRAY);fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);break;case PLAYER: // 玩家//setfillcolor(RED);//fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);putimage(MAP1 + j*ux,MAP2 + i*uy,&img_player);break;case BOX: // 箱子//setfillcolor(BROWN);//fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);putimage(MAP1 + j*ux,MAP2 + i*uy,&img_box);break;case AIM: // 目标点setfillcolor(GREEN);fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);break;case FINISH: // 箱子站在目标点上//setfillcolor(WHITE);//fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);putimage(MAP1 + j*ux,MAP2 + i*uy,&img_box);break;case AIMPLAYER: // 玩家站在目标点上//setfillcolor(RED);//fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);putimage(MAP1 + j*ux,MAP2 + i*uy,&img_player);break;}}}}/*****************//*****************//*****************//***********************
//* 函数名称:putboxMove
//* 功能描述:移动处理
//*****************//*****************//*****************//************************/
void putboxMove(void)
{int ux,uy,uux,uuy;switch(player.direction){ // 根据移动的方向,计算移动一格的位置,和移动两格的位置case NONE:break;case MOVEUP:ux = player.x;uy = player.y - 1;uux = ux;uuy = uy - 1;break;case MOVELEFT:ux = player.x - 1;uy = player.y;uux = ux - 1;uuy = uy;break;case MOVEDOWN:ux = player.x;uy = player.y + 1;uux = ux;uuy = uy + 1;break;case MOVERIGHT:ux = player.x + 1;uy = player.y;uux = ux + 1;uuy = uy;break;}if( (ux < 0 || ux > HEIGHT)|| (uy < 0 || uy > WIDTH) ){ // 如果移动后的x或y坐标超过范围,则无效return;}switch(currentMap[uy][ux]){ // 根据下一格的内容,作出相应处理case EMPTY: // 下一格为空地,则移动到空地currentMap[uy][ux] = PLAYER;if(currentMap[player.y][player.x] == AIMPLAYER){ // 如果玩家刚好站在目标点上,则移动后的格子为目标点currentMap[player.y][player.x] = AIM;}else{ // 如果玩家站在空地上,则移动后的格子为空地currentMap[player.y][player.x] = EMPTY;}player.y = uy;player.x = ux;break;case WALL: // 下一格为墙或者玩家(玩家:黑人脸问号?),则无效退出case PLAYER:break;case FINISH: // 下一格为站在目标点上的箱子case BOX: // 下一格为箱子,则根据箱子的下一格内容,作出不同处理switch(currentMap[uuy][uux]){ // 根据箱子的下一格内容,作出相应处理case EMPTY: // 箱子的下一格为空,则玩家与箱子都前进一格currentMap[uuy][uux] = BOX;if(currentMap[uy][ux] == FINISH){ // 如果箱子刚好站在目标点上,则移动后的格子为人站在目标点上currentMap[uy][ux] = AIMPLAYER;player.boxs++; // 箱子数++ 因为箱子离开了目标点}else{ // 如果箱子站在空地上,则移动后的格子玩家currentMap[uy][ux] = PLAYER;}if(currentMap[player.y][player.x] == AIMPLAYER){ // 如果玩家刚好站在目标点上,则移动后的格子为目标点currentMap[player.y][player.x] = AIM;}else{ // 如果玩家站在空地上,则移动后的格子为空地currentMap[player.y][player.x] = EMPTY;}player.y = uy;player.x = ux;break;case WALL: // 箱子的下一格为墙、玩家(玩家:再次黑人脸问号?)、箱子,则无效退出case PLAYER:case BOX:break;case AIM: // 箱子的下一格为目标点,nice,玩家和箱子都前进一格,完成一个小目标,currentMap[uuy][uux] = FINISH;if(currentMap[uy][ux] == FINISH){ // 如果箱子刚好站在目标点上,则移动后的格子为人站在目标点上currentMap[uy][ux] = AIMPLAYER;player.boxs++; // 箱子数++ 因为箱子离开了目标点}else{ // 如果箱子站在空地上,则移动后的格子玩家currentMap[uy][ux] = PLAYER;}if(currentMap[player.y][player.x] == AIMPLAYER){ // 如果玩家刚好站在目标点上,则移动后的格子为目标点currentMap[player.y][player.x] = AIM;}else{ // 如果玩家站在空地上,则移动后的格子为空地currentMap[player.y][player.x] = EMPTY;}player.y = uy;player.x = ux;player.boxs--;break;case FINISH:break;}break;case AIM:currentMap[uy][ux] = AIMPLAYER;currentMap[player.y][player.x] = EMPTY;player.y = uy;player.x = ux;break;case AIMPLAYER: // 玩家与目标点重合break;}
}
2.具体实现过程
2.1初始化函数 putboxinit()
绘制游戏的窗口、提示信息、游戏地图等
void putboxinit()
{initgraph(TOTALWIDTH, TOTOALHEIGHT); // 初始化窗口,设置窗口大小HWND window = GetHWnd(); // 获取当前窗口SetWindowText(window, "推箱子 - by耒阳阿杰"); // 设置当前窗口的标题outtextxy(5,5,"ESC: 退出"); // 设置提示信息outtextxy(80,5,"R: 重置本关");outtextxy(5,30,"W: 上 A:左 S:下 D:右");fillrectangle(MAP1,MAP2,MAP3,MAP4); // 划分游戏区域player.level = 1; // 初始等级为1loadimage(&img_player,"player.png",40,40); // 加载玩家图片loadimage(&img_box,"box.png",40,40); // 加载玩家图片resetputbox(); // 根据玩家等级,重置相应关卡
}
2.2重置关卡函数 resetputbox()
根据玩家当前level(默认为1),从地图库boxMap数组中读取相应的地图,写入到当前游戏地图数组currentMap;并记录玩家坐标、需要完成的箱子数量
void resetputbox()
{int i,j;int uy,ux;uy = (MAP4 - MAP2) / HEIGHT;ux = (MAP3 - MAP1) / WIDTH;player.boxs = 0;for(i = 0; i < HEIGHT;i++){for(j = 0; j < WIDTH; j++){currentMap[i][j] = boxMap[player.level - 1][i][j];if(currentMap[i][j] == BOX){ // 每检测到一次箱子,箱子数加1player.boxs++;}if(currentMap[i][j] == PLAYER){ // 记录玩家位置player.x = j;player.y = i;}}}}
2.3绘制地图函数 drawMap()
玩家每次按下按键之后,都会执行此函数。
游戏区域总像素是400x400;将游戏区域分为10x10,也就是分为100个像素小块,每个像素块都是40x40像素,根据currentMap数组的每个成员,对每个像素小块进行填充或贴图。
注意:玩家和箱子是直接读取的图片,所以要保证工程目录下有这两张图片!
void drawMap()
{int i,j;int uy,ux;char ch[10];uy = (MAP4 - MAP2) / HEIGHT;ux = (MAP3 - MAP1) / WIDTH;sprintf_s(ch, "%1s%1u", "level: ",player.level);settextcolor(LIGHTRED);settextstyle(30,30,0);outtextxy(100,60,ch); // 显示当前等级// 绘制地图for(i = 0; i < HEIGHT;i++){for(j = 0; j < WIDTH; j++){switch(currentMap[i][j]){case EMPTY: // 空地setfillcolor(CYAN); // 选择填充颜色fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy); // 填充相应区域break;case WALL: // 墙墙setfillcolor(DARKGRAY);fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);break;case PLAYER: // 玩家//setfillcolor(RED);//fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);putimage(MAP1 + j*ux,MAP2 + i*uy,&img_player);break;case BOX: // 箱子//setfillcolor(BROWN);//fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);putimage(MAP1 + j*ux,MAP2 + i*uy,&img_box);break;case AIM: // 目标点setfillcolor(GREEN);fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);break;case FINISH: // 箱子站在目标点上//setfillcolor(WHITE);//fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);putimage(MAP1 + j*ux,MAP2 + i*uy,&img_box);break;case AIMPLAYER: // 玩家站在目标点上//setfillcolor(RED);//fillrectangle(MAP1 + j*ux,MAP2 + i*uy,MAP1 + (j+1)*ux,MAP2 + (i+1)*uy);putimage(MAP1 + j*ux,MAP2 + i*uy,&img_player);break;}}}}
2.4玩家移动处理函数 putboxMove
根据玩家按下的移动指令,作出相应处理,改变当前游戏地图数组currentMap的内容。
此函数稍微有点复杂,需要考虑的情况比较多,请理解清楚。
第一步,先根据移动的方向,得到移动方向下一格的坐标ux,uy,和移动方向下下格的坐标uux,uuy;
第二步,判断移动方向下一格的坐标ux,uy是否超出游戏地图范围,如果超过了,本次移动指令无效。
第三步,根据移动方向下一格ux,uy所在坐标的内容,作出不同处理;
如果下一格ux,uy为空地,则玩家x,y与空地ux,uy交换位置,并保存到当前游戏地图数组currentMap中;
如果下一格ux,uy为墙,或者玩家(不可能),则本次操作无效;
如果下一格ux,uy为目的地,则玩家与目的地重合,ux,uy记录为AIMPLAYER,,x,y记录为EMPTY,保存到currentMap数组中;
如果下一格为箱子,则又需要根据箱子的下一格的内容,分别进行处理:
如果下下格uux,uuy为空地,则箱子ux,uy移动到空地uux,uuy,uux,uuy记录为BOX;此时又要分别考虑箱子ux,uy原来是站在空地上,还是站在目的地上;如果箱子原来站在目的地上,则箱子从目的地离开后,需要特殊处理,需要完成的箱子数量加1,玩家x,y则与目的地ux,uy重合,ux,uy记录为AIMPLAYER;如果箱子原来站在空地上,则箱子ux,uy从空地离开后,玩家站在空地ux,uy上,ux,uy记录为PLAYER。此时又需要考虑玩家,原来是站立的位置;如果玩家原来站在目的地上,则玩家从目的地上离开后,x,y记录为AIM;如果玩家站在空地上,则x,y记录为EMPTY,并将新的uux,uuy;ux,uy; x,y保存到数组currentMap中。
如果下下格uux,uuy为墙、玩家(不可能)、箱子,则本次操作无效。
如果下下格uux,uuy为目的地,则箱子移动到目的地,uux,uuy记录为FINISH;此时又要分别考虑箱子ux,uy原来是站在空地上,还是站在目的地上;如果箱子ux,uy原来站在目的地上,则箱子从目的地离开后,需要特殊处理,需要完成的箱子数量减1,玩家则与目的地重合,ux,uy记录为AIMPLAYER。此时又需要考虑玩家,原来是站立的位置;如果玩家原来站在目的地上,则玩家从目的地上离开后,x,y记录为AIM;如果玩家站在空地上,则x,y记录为EMPTY,并将新的uux,uuy;ux,uy; x,y保存到数组currentMap中。
void putboxMove(void)
{int ux,uy,uux,uuy;switch(player.direction){ // 根据移动的方向,计算移动一格的位置,和移动两格的位置case NONE:break;case MOVEUP:ux = player.x;uy = player.y - 1;uux = ux;uuy = uy - 1;break;case MOVELEFT:ux = player.x - 1;uy = player.y;uux = ux - 1;uuy = uy;break;case MOVEDOWN:ux = player.x;uy = player.y + 1;uux = ux;uuy = uy + 1;break;case MOVERIGHT:ux = player.x + 1;uy = player.y;uux = ux + 1;uuy = uy;break;}if( (ux < 0 || ux > HEIGHT)|| (uy < 0 || uy > WIDTH) ){ // 如果移动后的x或y坐标超过范围,则无效return;}switch(currentMap[uy][ux]){ // 根据下一格的内容,作出相应处理case EMPTY: // 下一格为空地,则移动到空地currentMap[uy][ux] = PLAYER;if(currentMap[player.y][player.x] == AIMPLAYER){ // 如果玩家刚好站在目标点上,则移动后的格子为目标点currentMap[player.y][player.x] = AIM;}else{ // 如果玩家站在空地上,则移动后的格子为空地currentMap[player.y][player.x] = EMPTY;}player.y = uy;player.x = ux;break;case WALL: // 下一格为墙或者玩家(玩家:黑人脸问号?),则无效退出case PLAYER:break;case FINISH: // 下一格为站在目标点上的箱子case BOX: // 下一格为箱子,则根据箱子的下一格内容,作出不同处理switch(currentMap[uuy][uux]){ // 根据箱子的下一格内容,作出相应处理case EMPTY: // 箱子的下一格为空,则玩家与箱子都前进一格currentMap[uuy][uux] = BOX;if(currentMap[uy][ux] == FINISH){ // 如果箱子刚好站在目标点上,则移动后的格子为人站在目标点上currentMap[uy][ux] = AIMPLAYER;player.boxs++; // 箱子数++ 因为箱子离开了目标点}else{ // 如果箱子站在空地上,则移动后的格子玩家currentMap[uy][ux] = PLAYER;}if(currentMap[player.y][player.x] == AIMPLAYER){ // 如果玩家刚好站在目标点上,则移动后的格子为目标点currentMap[player.y][player.x] = AIM;}else{ // 如果玩家站在空地上,则移动后的格子为空地currentMap[player.y][player.x] = EMPTY;}player.y = uy;player.x = ux;break;case WALL: // 箱子的下一格为墙、玩家(玩家:再次黑人脸问号?)、箱子,则无效退出case PLAYER:case BOX:break;case AIM: // 箱子的下一格为目标点,nice,玩家和箱子都前进一格,完成一个小目标,currentMap[uuy][uux] = FINISH;if(currentMap[uy][ux] == FINISH){ // 如果箱子刚好站在目标点上,则移动后的格子为人站在目标点上currentMap[uy][ux] = AIMPLAYER;player.boxs++; // 箱子数++ 因为箱子离开了目标点}else{ // 如果箱子站在空地上,则移动后的格子玩家currentMap[uy][ux] = PLAYER;}if(currentMap[player.y][player.x] == AIMPLAYER){ // 如果玩家刚好站在目标点上,则移动后的格子为目标点currentMap[player.y][player.x] = AIM;}else{ // 如果玩家站在空地上,则移动后的格子为空地currentMap[player.y][player.x] = EMPTY;}player.y = uy;player.x = ux;player.boxs--;break;case FINISH:break;}break;case AIM:currentMap[uy][ux] = AIMPLAYER;currentMap[player.y][player.x] = EMPTY;player.y = uy;player.x = ux;break;case AIMPLAYER: // 玩家与目标点重合break;}
}
2.5 推箱子游戏主题函数 putboxrun()
此函数整合了整个推箱子游戏的所有函数;
初始化后,会进入死循环,并根据currentMap数组的成员,绘制当前游戏画面;
之后会进行游戏结束判断,根据需要完成的箱子数量player.boxs,如果数量为0,则当前关卡完成,等级level加1;
如果等级level超过了最大等级TOTALLEVEL,则判断游戏结束,退出游戏
如果等级level没有超过最大等级TOTALLEVEL,更新下一关卡的游戏数据,并重新开始循环
如果需要完成的箱子数量不为0,则等待玩家操作键盘;
玩家按下键盘后,读取输入的值,进行处理:
如果按下了移动键(W、S、A、D),则进入移动处理函数;
如果按下了重置键(R),则重新开始本关卡;
如果按下了退出键(ESC),则退出推箱子游戏。
void putboxrun(void)
{int key;putboxinit(); // 初始化地图、数据while(1){drawMap(); // 每次按键之后都会更新地图if(!player.boxs){ // 完成全部箱子,等级加1,进行下一关player.level++;if(player.level > TOTALLEVEL){ // 如果完成了所有关卡,则结束游戏break;}resetputbox(); // 更新下一关数据continue;}key = _getch(); // 获取用户按键player.direction = NONE; // 先清除移动方向switch(key){case 'w':case 'W':player.direction = MOVEUP;break;case 'a':case 'A':player.direction = MOVELEFT;break;case 's':case 'S':player.direction = MOVEDOWN;break;case 'd':case 'D':player.direction = MOVERIGHT;break;case ESC:return;case 'r':case 'R':resetputbox();continue;break;default:break;}putboxMove(); // 根据玩家移动方向,进行处理}_getch();
}
总结
此游戏还有很多可以完善的地方:
比如地图只采用了简单的像素填充不够美观,只有玩家和箱子是贴图。后续大家可以自己制作或去网上找到更合适的图片,将游戏制作的更加精美;
游戏地图暂时只有两个,没有开始游戏、游戏结束的动画界面等。
本人也只是一枚小菜鸟,希望与大家一起学习进步。