补充项目 - 推箱子游戏
第 1 节 项目需求
实现一款推箱子游戏,效果如下图所示,具体规则: 1. 箱子只能推动而不能拉动; 2.如果箱子前一格是地板或箱子目的地,则可以推动一个箱子往前走一格,如果箱子已经在 箱子目的地则不能再推动; 3.推箱子的小人不能从箱子目的地上直接穿过; 4.注意不要把箱子推到死角上,不然就无法再推动它了; 5.所有箱子都成功推到箱子目的地,游戏结束,过关成功!
美工资源:
链接:https://pan.baidu.com/s/1MZv8pDBXdNDbXxuAAPSM-A **提取码:
**2syq
图形库:
www.easyx.cn
第 2 节 项目实现
2.1 模块划分
(作用:1.化繁为简 2.适合团队协作 3.高质量代码)
2.1.1 地图初始化
搭台唱戏
戏台坐标系(650 x 650):
地图表示:
使用二维数组
1、游戏道具显示(墙、箱子、箱子目的地、小人、地板)
2、便于程序在游戏过程中进行逻辑判断和控制小人向前一步的动作控制
3、判断游戏结果
道具表示:
墙: 0,地板: 1,箱子目的地: 2, 小人: 3, 箱子: 4, 箱子命中目标: 5
编码实现:
box_man.cpp
#include "box_man.h"
#include <iostream>
#include <stdlib.h>
#include <string>
#include <conio.h>
#include <graphics.h>
#include "box_man.h"
using namespace std;
IMAGE images[ALL];
struct _POS man; /* 小人在二维数组的位置 */
int map[LINE][COLUMN] =
{
{WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL},
{WALL, FLOOR, WALL, FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, WALL, WALL},
{WALL, FLOOR, BOX, FLOOR, WALL, BOX_DES, FLOOR, WALL, BOX_DES, FLOOR, WALL, WALL},
{WALL, FLOOR, WALL, FLOOR, WALL, FLOOR, FLOOR, WALL, FLOOR, FLOOR, FLOOR, WALL},
{WALL, FLOOR, WALL, BOX_DES, WALL, FLOOR, FLOOR, BOX, FLOOR, FLOOR, FLOOR, WALL},
{WALL, FLOOR, FLOOR, FLOOR, WALL, MAN, FLOOR, FLOOR, FLOOR, BOX, FLOOR, WALL},
{WALL, FLOOR, BOX_DES, FLOOR, FLOOR, BOX, FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, WALL},
{WALL, FLOOR, WALL, WALL, FLOOR, WALL, FLOOR, FLOOR, WALL, WALL, FLOOR, WALL},
{WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL},
};
/*****************************************************
* 判断游戏是否结束, 如果不存在任何一个箱子目的地, 就代表游戏结束
* 输入: 无
* 返回值:
* true - 游戏结束 false - 游戏继续
*****************************************************/
bool isGameOver()
{
for (int i = 0; i < LINE; i++)
{
for (int j = 0; j < COLUMN; 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("恭喜你, 通关了!!!"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
/*************************************************
* 功能: 改变游戏地图视图中一格对应的道具并重新显示
* 输入:
* pos - 道具在地图数组的行列下标
* prop - 道具的类型
* 返回值: 无
*************************************************/
void changeMap(POS* pos, PROPS prop)
{
map[pos->x][pos->y] = prop;
putimage(START_X + pos->y * RATIO, START_Y + pos->x * RATIO, &images[prop]);
}
/**********************************************
* 功能: 实现游戏四个方向 (上, 下, 左, 右) 的控制
* 输入:
* direct - 人前进的方向
* 输出: 无
**********************************************/
void gameControl(DIRECTION direct)
{
POS next_pos = man; /* man 类型(结构体) 与 next_pos 相同 */
POS next_next_pos = man;
switch (direct)
{
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;
}
/* 宏展开 next_pos.x >= 0 && next_pos.x < LINE && next_pos.y >= 0 && next_pos.y < COLUMN */
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_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;
}
}
}
int main(void)
{
IMAGE bg_img;
/* 搭台 */
initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
loadimage(&bg_img, _T("blackground.bmp"), SCREEN_WIDTH, SCREEN_HEIGHT);
putimage(0, 0, &bg_img);
/* 加载道具 */
loadimage(&images[WALL], _T("wall_right.bmp"), RATIO, RATIO, true);
loadimage(&images[FLOOR], _T("floor.bmp"), RATIO, RATIO, true);
loadimage(&images[BOX_DES], _T("des.bmp"), RATIO, RATIO, true);
loadimage(&images[MAN], _T("man.bmp"), RATIO, RATIO, true);
loadimage(&images[BOX], _T("box.bmp"), RATIO, RATIO, true);
loadimage(&images[HIT], _T("box.bmp"), RATIO, RATIO, true);
for (int i = 0; i < LINE; i++)
{
for (int j = 0; j < COLUMN; j++)
{
if (map[i][j] == MAN)
{
man.x = i;
man.y = j;
}
putimage(START_X + j * RATIO, START_Y + i * RATIO, &images[map[i][j]]);
}
}
/* 游戏环节 */
bool quit = false;
do
{
if (_kbhit())
{
char ch = _getch();
if (ch == KEY_UP)
{
gameControl(UP);
}
else if (ch == KEY_DOWN)
{
gameControl(DOWN);
}
else if (ch == KEY_LEFT)
{
gameControl(LEFT);
}
else if (ch == KEY_RIGHT)
{
gameControl(RIGHT);
}
else if (ch == KEY_QUIT)
{
quit = true;
}
if (isGameOver())
{
gameOverScene(&bg_img);
quit = true;
}
}
Sleep(100);
} while (quit == false);
::system("pause");
closegraph();
return 0;
}
box_man.h
#pragma once
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 650
#define RATIO 50
/* 控制键 上 下 左 右 控制方向 */
#define KEY_UP 'w'
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'
#define KEY_DOWN 's'
#define KEY_QUIT 'q'
#define LINE 9
#define COLUMN 12
#define START_X 100
#define START_Y 100
enum _PROPS /* 道具 */
{
WALL, /* 墙 */
FLOOR, /* 地板 */
BOX_DES, /* 箱子的目地 */
MAN, /* 小人 */
BOX, /* 箱子 */
HIT, /* 箱子命中目标 */
ALL
};
/* 游戏控制方向 */
enum _DIRECTION
{
UP,
DOWN,
LEFT,
RIGHT
};
struct _POS /* 位置 */
{
int x; /* 小人所在二维数组的行 */
int y; /* 小人所在二维数据在列 */
};
typedef enum _PROPS PROPS; /* 道具 */
typedef enum _DIRECTION DIRECTION; /* 控制方向 */
typedef struct _POS POS; /* 道具的位置 */
#define isValid(pos) pos.x>=0 && pos.x<LINE && pos.y>=0 && pos.y < COLUMN
结语:
时间: 2020-07-15