实现游戏逻辑
角色的位置
在让角色动起来之前,我们需要先知道他在哪,在哪这个位置性概念我们通过定义一个POS结构来个表达。
// 以行列存储的位置信息
typedef struct tagPOS
{
char r;
char c;
} POS;
现在我们来定位它在哪?从之前的分析中可以知道,关卡中数字4代表的是角色,为此我们就可以在载入关卡时保存这个位置。
// 玩家位置
POS g_player_pos;
// 载入关卡
bool Load_Map(int level)
{
// 记录玩家初始位置
if (map[r][c] == PLAYER)
{
g_player_pos.r = r;
g_player_pos.c = c;
}
}
游走起来
角色在我们的操控下可以向四个方向游走,这些方向我们通过枚举来表达。
enum MOVEDIR
{
MOVE_LEFT,
MOVE_RIGHT,
MOVE_UP,
MOVE_DOWN
};
角色的移动是通过键盘操控来实现的;我们使用上下左右键实现四个方向的游走。
void Keyboard(E2DKeyboardEvent kbe, E2DScancode sc)
{
if (kbe == E2D_KEYDOWN)
{
switch (sc)
{
case E2D_SCANCODE_LEFT:
Player_Move(MOVE_LEFT);
break;
case E2D_SCANCODE_RIGHT:
Player_Move(MOVE_RIGHT);
break;
case E2D_SCANCODE_UP:
Player_Move(MOVE_UP);
break;
case E2D_SCANCODE_DOWN:
Player_Move(MOVE_DOWN);
break;
}
}
}
函数Player_Move是整个控制的核心.
void Player_Move(MOVEDIR dir)
{
POS p1 = g_player_pos;
POS p2 = g_player_pos;
switch (dir)
{
case MOVE_LEFT:
p1.c -= 1;
p2.c -= 2;
g_player_tex = TEX_PLAYER_LEFT;
break;
case MOVE_RIGHT:
p1.c += 1;
p2.c += 2;
g_player_tex = TEX_PLAYER_RIGHT;
break;
case MOVE_UP:
p1.r -= 1;
p2.r -= 2;
g_player_tex = TEX_PLAYER_UP;
break;
case MOVE_DOWN:
p1.r += 1;
p2.r += 2;
g_player_tex = TEX_PLAYER_DOWN;
break;
}
if (p1.c < 0) return;
if (p1.r < 0) return;
if (p1.c >= MAP_COLUMNS) return;
if (p1.r >= MAP_ROWS) return;
if (g_map[p1.r][p1.c] == WALL)
return;
if (g_map[p1.r][p1.c] == BOX || g_map[p1.r][p1.c] == GOAL)
{
int e2 = g_map[p2.r][p2.c];
if (e2 == WALL || e2 == BOX || e2 == GOAL)
return;
if (e2 == ROAD)
g_map[p2.r][p2.c] = BOX;
else if (e2 == TARGET)
g_map[p2.r][p2.c] = GOAL;
}
// 玩家移动到此位置
g_map[p1.r][p1.c] = PLAYER;
// 通过测试
if (Level_Clear())
{
Load_Map(g_cur_level + 1);
}
}
函数一开始定义了p1、p2两个位置信息,分别表示玩家所处方向的下一个及下下一个位置。然后依据这些位置在索引地图中的元素,以此判断是行走、推箱子或其它行为,如下一个位置是障碍物时,角色不可移动。
if (g_map[p1.r][p1.c] == WALL)
return;
当角色移动了一步后,我们就可以判断是否通关,Level_Clear的逻辑比较简单,如果所有的目标点上有箱子,就说明通关了,然后程序载入下一关。
显示更新
当玩家将箱子推到目标点后,渲染的结果依然是箱子,也就是说箱子在与不在目标点上,看不出差别。为此我们增加一点渲染效果,以区分两者,增加游戏体验,这里的做法是,当箱子在目标点上时,为箱子混入红色。
void Render()
{
if (!blend)
{
E2D_RenderTexture(t->tex, x - t->dx, y - t->dy, E2D_FLIP_NONE);
}
else
{
E2DColor color = {255, 0, 0, 255};
E2D_SetTextureBlend(t->tex, color, E2D_BLENDMODE_BLEND);
E2D_RenderTexture(t->tex, x - t->dx, y - t->dy, E2D_FLIP_NONE);
E2D_ResetTextureBlend(t->tex);
}
}
