项目需求
实现一款推箱子游戏,效果如下图所示,具体规则:
- 箱子只能推动而不能拉动;
- 如果箱子前一格是地板或箱子目的地,则可以推动一个箱子往前走一格,如果箱子已经在 箱子目的地则不能再推动;
- 推箱子的小人不能从箱子目的地上直接穿过;
- 注意不要把箱子推到死角上,不然就无法再推动它了;
- 所有箱子都成功推到箱子目的地,游戏结束,过关成功!
项目资源显示
墙 地板 箱子目的地 小人 箱子 箱子命中目标
项目实现
说明:有关图像处理该项目使用的是easyX图形库
txz.h
#pragma once
using namespace std;
/*游戏窗口宽高设置*/
#define SCREEN_WIDTH 960
#define SCREEN_HEIGHT 768
/*游戏地图行列设置*/
#define LINE 9
#define COLUNM 12
/*游戏地图与窗口的偏移*/
#define START_X 100
#define START_Y 50
/*表示热键<上下左右与退出>*/
#define KEY_UP 'w'
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'
#define KEY_DOWN 's'
#define KEY_QUIT 'q'
#define isValid(pos) pos.x >= 0 && pos.x < LINE && pos.y >= 0 && pos.y < COLUNM
/*枚举地图元素*/
enum _PROPS {
WALL, //墙0
FLOOR, //地板1
BOX_DES,//箱子目的地2
MAN, //小人3
BOX, //箱子4
HIT, //箱子命中目标5
MAN_HIT,//小人击中目的地6
ALL //地图元素的总数
};
/*枚举小人方向控制*/
enum _DIRECTION {
UP, //上
DOWN, //下
LEFT, //左
RIGHT //右
};
/*定义一个全局地图数组(表示有ALL<6>个地图道具)*/
IMAGE images[ALL];
/*定义小人结构体<在地图中的位置>*/
struct _POS {
int x;//表示小人的列坐标
int y;//表示小人的行坐标
}man;
/*二维数组游戏地图*/
int map[LINE][COLUNM] = {
{ 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, 2, 4, 1, 0 },
{ 0, 1, 2, 1, 1, 4, 1, 2, 2, 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 } };
/***************按键后地图道具的改变的函数*****************
*实现小人移动后道具的改变
*输入:line-地图数组的行下标
column-地图数组的列下标
prop-道具的类型
*输出:无
**********************************************************/
void changeMap(struct _POS* pos, enum _PROPS prop) {
map[pos->x][pos->y] = prop;
putimage(pos->y * 61 + START_X, pos->x * 61 + START_Y, &images[prop]);
}
/**************小人方向控制函数实现*************************
*实现游戏四个方向(上、下、左、右)的控制
* 输入: direct - 人前进方向
* 输出: 无
***********************************************************/
void gameControl(enum _DIRECTION direct)
{/*
int x = man.x;
int y = man.y;
if (direct == UP) //小人向上走
{
if ((x-1)>=0&&map[x-1][y]==FLOOR) {
changeMap(x - 1, y, MAN);//小人前进一格
man.x = x - 1; //小人位置坐标前进一格
changeMap(x, y, FLOOR);//人所在的位置为地板
}
}
else if(direct == DOWN)//小人向下走
{
if ((x+1) <LINE && map[x +1][y] == FLOOR) {
changeMap(x +1, y, MAN);//小人后退一格
man.x = x + 1; //小人位置坐标前进一格
changeMap(x, y, FLOOR);//人所在的位置为地板
}
}
else if (direct == LEFT)//小人向左走
{
if ((y-1)>= 0 && map[x ][y-1] == FLOOR) {
changeMap(x , y-1, MAN);//小人左走一格
man.y = y- 1; //小人位置坐标左走一格
changeMap(x, y, FLOOR);//人所在的位置为地板
}
}
else if (direct == RIGHT)//小人向右走
{
if ((y+1)<= COLUNM && map[x ][y+1] == FLOOR)
{
changeMap(x , y+1, MAN);//小人右走一格
man.y = y +1; //小人位置坐标右走一格
changeMap(x, y, FLOOR);//人所在的位置为地板
}
}
*/
//优化后的小人热键控制
struct _POS next_pos = man; //小人前一格的道具
struct _POS next_next_pos = man; //小人前两格的道具
switch (direct)
{
case UP:
//next_next_pos=next_next_pos-1
next_pos.x--;
//next_next_pos.x = next_next_pos.x - 2;
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 (next_pos.x >= 0 && next_pos.x < LINE && next_pos.y >= 0 && next_pos.y < COLUNM && map[next_pos.x][next_pos.y] == FLOOR) {
if (isValid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR)
{
changeMap(&next_pos, MAN);
changeMap(&man, FLOOR);
man = next_pos;
}
//(二)小人前进方向为箱子
else if (isValid(next_pos) && map[next_pos.x][next_pos.y] == BOX) {
//小人前两格(箱子前面)为地板
if (map[next_next_pos.x][next_next_pos.y] == FLOOR) {
//小人原位置前两格改为箱子
changeMap(&next_next_pos, BOX);
//小人原位置前一格改为小人
changeMap(&next_pos, MAN);
//小人原位置改为地板
changeMap(&man, FLOOR);
man = next_pos;
}
//小人前两格(箱子前面)为目的地
else if (map[next_next_pos.x][next_next_pos.y] == BOX_DES) {
//小人原位置前两格改为箱子
changeMap(&next_next_pos, HIT);
//小人原位置前一格改为小人
changeMap(&next_pos, MAN);
//小人原位置改为地板
changeMap(&man, FLOOR);
man = next_pos;
}
}
//(三)小人前方是目的地
else if (isValid(next_pos) && map[next_pos.x][next_pos.y] == BOX_DES) {
//小人原位置前一格改为小人
changeMap(&next_pos, MAN);
//小人原位置改为地板
changeMap(&man, FLOOR);
man = next_pos;
//小人所地图位置改为6
map[man.y][man.x] = 6;
if ( map[next_pos.x][next_pos.y] == FLOOR) {
//小人原位置前一格改为小人
changeMap(&next_pos, MAN);
//小人原位置改为地板
changeMap(&man, BOX_DES);
man = next_pos;
//map[][] = 5;
}
}
}
/**********************************************
*判断游戏是否结束,如果不存在任何一个箱子目的地,就代表游戏结束
*输入: 无
*返回值:
* true - 游戏结束 false - 游戏继续
**********************************************/
bool isGameOver()
{
for (int i = 0; i < LINE; i++) {
for (int j = 0; j < COLUNM; j++) {
if (map[i][j] == BOX_DES) return false;
}
}
return true;
}
/**********************************************
*游戏结束场景,在玩家通关后显示
*输入:
* bg - 背景图片变量的指针
*返回值: 无
**********************************************/
void gameOverScene(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);
}
main.cpp
#include<Windows.h>
#include<string>
#include<iostream>
#include<graphics.h>
#include<conio.h>//获取热键头文件
#include"txz.h"
int main(void) {
/**************地图场景初始化*************/
//声明一个图片句柄
IMAGE bg_img;
//设置游戏场景
initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
//把图片加载到bg_img中并指明所加载的图片和图片的宽 高 是否拉升图片
loadimage(&bg_img,"blackground.bmp", SCREEN_WIDTH, SCREEN_HEIGHT,true);
//把图片放在场景中(放在场景的左上角)
putimage(0,0,&bg_img);
/*************地图道具初始化**************/
/*
道具加载: 墙0 地板1 箱子目的地2
小人3 箱子4 箱子命中目标5
*/
//加载图片并指明图片宽与高的像素和是否拉升图片
loadimage(&images[WALL], "wall_right.bmp",61,61, true);
loadimage(&images[FLOOR], "floor.bmp",61, 61, true);
loadimage(&images[BOX_DES], "des.bmp", 61, 61, true);
loadimage(&images[MAN], "man.bmp", 61, 61, true);
loadimage(&images[BOX], "box.bmp", 61, 61, true);
loadimage(&images[HIT], "box.bmp", 61, 61, true);
loadimage(&images[MAN_HIT], "man.bmp", 61, 61, true);
//显示地图
for (int i = 0; i < LINE; i++) {
for (int j = 0; j < COLUNM; j++) {
if (map[i][j]==MAN) {
man.x = i;
man.y = j;
}
putimage(j * 61 + START_X, i * 61 + START_Y, &images[map[i][j]]);
}
}
/**************小人热键操作***************/
//控制键 上w、下s、左a、右d 控制方向,'q' 退出
bool quit = false;
do {
if (_kbhit()) //检测玩家是否有按键
{
char ch = _getch();
if (ch== KEY_UP) {
gameControl(UP);
}
else if(ch == KEY_LEFT ){
gameControl(LEFT);
}
else if(ch == KEY_RIGHT){
gameControl(RIGHT);
}
else if(ch == KEY_DOWN){
gameControl(DOWN);
}
else if(ch == KEY_QUIT ){
quit = true;
}
if (isGameOver()) {
gameOverScene(&bg_img);
quit = true;
}
}
Sleep(100);
} while(quit==false);//!quit
/*****************************************/
system("pause");
return 0;
}
[奇牛学院]