***效果如图所示
一、资源的获取
首先的获取墙壁,地板,人,箱子目的的的图片
注意:需要VS安装easyX插件,安装过程参照之前文章
二、项目分析
1、地图初始化
2、热键控制
3、逻辑判断
4、游戏结束
三、具体实现
1、地图初始化
IMAGE image[ALL];
//初始化地图
int map[LINE][COLMON]{
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,0,1,1,1,1,1,1,1,0,0},
{0,1,4,1,0,2,1,0,2,1,0,0},
{0,1,0,1,0,1,0,0,1,1,1,0},
{0,1,0,2,0,1,1,4,1,1,1,0},
{0,1,1,1,0,3,1,1,1,4,1,0},
{0,1,2,1,1,4,1,1,1,1,1,0},
{0,1,0,0,1,0,1,1,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0},
};
//图片的句柄
IMAGE bg_img;
//创建窗口
initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
//加载图片
loadimage(&bg_img, L"blackground.bmp", SCREEN_WIDTH, SCREEN_HEIGHT, true);
putimage(0, 0, &bg_img);
//加载道具
loadimage(&image[Wall], L"wall_right.bmp", RATIO, RATIO, true);
loadimage(&image[FLOOR], L"floor.bmp", RATIO, RATIO, true);
loadimage(&image[BOX_DEX], L"des.bmp", RATIO, RATIO, true);
loadimage(&image[MAN], L"man.bmp", RATIO, RATIO, true);
loadimage(&image[BOX], L"box.bmp", RATIO, RATIO, true);
loadimage(&image[HIT], L"box.bmp", RATIO, RATIO, true);
//地图的加载
for (int i = 0; i < LINE; i++)
{
for (int j = 0; j < COLMON; j++)
{
putimage(START_X + j * RATIO, START_Y + i * RATIO, &image[map[i][j]]);
//确定小人的位置
if (map[i][j] == MAN)
{
man.x = i;
man.y = j;
}
}
}
2、定义游戏热键
//定义游戏热键
bool quit = false;
do {
if (_kbhit())
{
char ch = _getch();
if (ch == KEY_LEFT)
{
getControl(LEFT);
}
else if (ch == KEY_RIGHT)
{
getControl(RIGHT);
}
else if (ch == KEY_UP)
{
getControl(UP);
}
else if (ch == KEY_down)
{
getControl(DOWN);
}
else if (ch == KEY_QUIT)
{
quit = true;
}
if (isGameOver())
{
gameoverScreen(&bg_img);
quit = true;
}
}
Sleep(100);
} while (quit == false);
3、逻辑判断
*
改变游戏中视图中一格道具并重新显示
输入: line-地图数组的行下标 column-地图数组的列下标 prop道具的类型
输出:无
*/
void change_Map(POS* next_POS , PROPOS prop)
{
map[next_POS->x][next_POS->y] = prop;
putimage(START_X + next_POS->y * RATIO, START_Y + next_POS->x * RATIO, &image[map[next_POS->x][next_POS->y]]);
}
/*====================================
实现小人的控制
输入:deriect
输出: 无
====================================*/
void getControl(Decoration dricit)
{
POS next_POS = man;
POS next_next_POS = man;
switch (dricit)
{
case UP:
next_POS.x--;
next_next_POS.x -= 2;
break;
case DOWN:
next_POS.x++;
next_next_POS.x += 2;
break;
case LEFT:
next_POS.y--;
next_next_POS.y -= 2;
break;
case RIGHT:
next_POS.y++;
next_next_POS.y += 2;
break;
}
//人的前方是地板
if (isValid(next_POS) && map[next_POS.x][next_POS.y] == FLOOR)
{
change_Map(&next_POS, MAN); //小人前进一格
change_Map(&man, FLOOR);
man = next_POS;
}
//人的前方是箱子
else if (isValid(next_next_POS) && map[next_POS.x][next_POS.y] == BOX)
{
if (map[next_next_POS.x][next_next_POS.y] == FLOOR)
{
change_Map(&next_next_POS, BOX);
change_Map(&next_POS, MAN);
change_Map(&man, FLOOR);
man = next_POS;
}
else if (map[next_next_POS.x][next_next_POS.y] == BOX_DEX)
{
change_Map(&next_next_POS, HIT);
change_Map(&next_POS, MAN);
change_Map(&man, FLOOR);
man = next_POS;
}
}
}
4、游戏结束
//判断游戏是否结束
bool isGameOver()
{
for (int i = 0; i < LINE; i++)
{
for (int j = 0; j < COLMON; j++)
{
if (map[i][j] == BOX_DEX) return false;
}
}
return true;
}
//游戏结束
void gameoverScreen(IMAGE *bg)
{
putimage(0, 0, bg);
settextcolor(WHITE);
RECT rec = { 0,0,SCREEN_WIDTH,SCREEN_HEIGHT };
settextstyle(20, 0, _T("宋体"));
drawtext(_T("恭喜您~\n您终于成为一个合格的老司机了!!!"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
四、完整的代码
1、为了方便,编写头文件,将定义好的变量放入
***** man_box.h 的编写
#pragma once
#define RATIO 61 //图片的尺寸
#define SCREEN_WIDTH 960 //背景宽度
#define SCREEN_HEIGHT 768 //背景高度
#define LINE 9
#define COLMON 12
#define START_X 100
#define START_Y 150
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'
#define KEY_UP 'w'
#define KEY_down 's'
constexpr auto KEY_QUIT = 'q';
typedef enum _PROPOS PROPOS;
typedef enum _Decoration Decoration;
typedef struct _POS POS;
2、源文件的实现
#include<iostream>
#include<stdio.h>
#include<string>
#include<graphics.h>
#include<conio.h>
#include"box_man.h"
#define isValid(pos) pos.x>=0 && pos.x < LINE && pos.y >=0 && pos.y < COLMON
using namespace std;
//定义小人的结构体
struct _POS{
int x;
int y;
};
//道具表示
// 0--墙 1--地板 2--箱子目的地 3--小人 4--箱子 5--箱子命中目标
//定义一个枚举类型,为了初始化地图
enum _PROPOS {
Wall, //墙
FLOOR, //地板
BOX_DEX,//箱子目的地
MAN, //小人
BOX, //箱子
HIT, //箱子目的地
ALL,
};
//游戏方向控制
enum _Decoration
{
UP,
DOWN,
LEFT,
RIGHT,
};
//创建一个小人的结构体
POS man;
IMAGE image[ALL];
//初始化地图
int map[LINE][COLMON]{
{0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,0,1,1,1,1,1,1,1,0,0},
{0,1,4,1,0,2,1,0,2,1,0,0},
{0,1,0,1,0,1,0,0,1,1,1,0},
{0,1,0,2,0,1,1,4,1,1,1,0},
{0,1,1,1,0,3,1,1,1,4,1,0},
{0,1,2,1,1,4,1,1,1,1,1,0},
{0,1,0,0,1,0,1,1,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0},
};
//判断游戏是否结束
bool isGameOver()
{
for (int i = 0; i < LINE; i++)
{
for (int j = 0; j < COLMON; j++)
{
if (map[i][j] == BOX_DEX) return false;
}
}
return true;
}
//游戏结束
void gameoverScreen(IMAGE *bg)
{
putimage(0, 0, bg);
settextcolor(WHITE);
RECT rec = { 0,0,SCREEN_WIDTH,SCREEN_HEIGHT };
settextstyle(20, 0, _T("宋体"));
drawtext(_T("恭喜您~\n您终于成为一个合格的老司机了!!!"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
/*
改变游戏中视图中一格道具并重新显示
输入: line-地图数组的行下标 column-地图数组的列下标 prop道具的类型
输出:无
*/
void change_Map(POS* next_POS , PROPOS prop)
{
map[next_POS->x][next_POS->y] = prop;
putimage(START_X + next_POS->y * RATIO, START_Y + next_POS->x * RATIO, &image[map[next_POS->x][next_POS->y]]);
}
/*====================================
实现小人的控制
输入:deriect
输出: 无
====================================*/
void getControl(Decoration dricit)
{
POS next_POS = man;
POS next_next_POS = man;
switch (dricit)
{
case UP:
next_POS.x--;
next_next_POS.x -= 2;
break;
case DOWN:
next_POS.x++;
next_next_POS.x += 2;
break;
case LEFT:
next_POS.y--;
next_next_POS.y -= 2;
break;
case RIGHT:
next_POS.y++;
next_next_POS.y += 2;
break;
}
//人的前方是地板
if (isValid(next_POS) && map[next_POS.x][next_POS.y] == FLOOR)
{
change_Map(&next_POS, MAN); //小人前进一格
change_Map(&man, FLOOR);
man = next_POS;
}
//人的前方是箱子
else if (isValid(next_next_POS) && map[next_POS.x][next_POS.y] == BOX)
{
if (map[next_next_POS.x][next_next_POS.y] == FLOOR)
{
change_Map(&next_next_POS, BOX);
change_Map(&next_POS, MAN);
change_Map(&man, FLOOR);
man = next_POS;
}
else if (map[next_next_POS.x][next_next_POS.y] == BOX_DEX)
{
change_Map(&next_next_POS, HIT);
change_Map(&next_POS, MAN);
change_Map(&man, FLOOR);
man = next_POS;
}
}
}
int main()
{
//图片的句柄
IMAGE bg_img;
//创建窗口
initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
//加载图片
loadimage(&bg_img, L"blackground.bmp", SCREEN_WIDTH, SCREEN_HEIGHT, true);
putimage(0, 0, &bg_img);
//加载道具
loadimage(&image[Wall], L"wall_right.bmp", RATIO, RATIO, true);
loadimage(&image[FLOOR], L"floor.bmp", RATIO, RATIO, true);
loadimage(&image[BOX_DEX], L"des.bmp", RATIO, RATIO, true);
loadimage(&image[MAN], L"man.bmp", RATIO, RATIO, true);
loadimage(&image[BOX], L"box.bmp", RATIO, RATIO, true);
loadimage(&image[HIT], L"box.bmp", RATIO, RATIO, true);
//地图的加载
for (int i = 0; i < LINE; i++)
{
for (int j = 0; j < COLMON; j++)
{
putimage(START_X + j * RATIO, START_Y + i * RATIO, &image[map[i][j]]);
//确定小人的位置
if (map[i][j] == MAN)
{
man.x = i;
man.y = j;
}
}
}
//定义游戏热键
bool quit = false;
do {
if (_kbhit())
{
char ch = _getch();
if (ch == KEY_LEFT)
{
getControl(LEFT);
}
else if (ch == KEY_RIGHT)
{
getControl(RIGHT);
}
else if (ch == KEY_UP)
{
getControl(UP);
}
else if (ch == KEY_down)
{
getControl(DOWN);
}
else if (ch == KEY_QUIT)
{
quit = true;
}
if (isGameOver())
{
gameoverScreen(&bg_img);
quit = true;
}
}
Sleep(100);
} while (quit == false);
system("pause");
closegraph();
return 0;
}
3、当然,只有一关啦,但在此基础上可以拓展别的关卡呀。。。。。。
----------------------------------------------------
创作不易,望各位多多点赞哈!!!
以上仅代表个人观点!!