在游戏开发中,会出现一种对格子之间逻辑要求严密的游戏;或者是由于使用的工具封装度较低,为了方便而不得不使用的一种方法。
当游戏的空间排布是网格状的时候,我们就可以使用ASCII来表示格子上东西的含义,并且只需要一个承装这些字符串的文件即可,然后再通过一些方法把它们读取到游戏中。之后,用至少一个二维数组把这些东西装起来,然后再去处理这些东西直接的逻辑关系。
逻辑严密 #
最简单的例子当然还是推箱子或者是俄罗斯方块这种游戏了,推箱子而言,可以把每个关卡的地图用ASCII表示并且存在独立的文件里面,比如说有一个这样的文件,叫level_1.txt。里面可能是这个样子的。
######
#..@..#
#...^.#
#.`...#
#..###
##
随便写的,没有难度。
然后’@‘是玩家的意思,’#‘是墙壁的意思,’.‘是地板的意思,’^‘是坑的意思,’`‘是箱子的意思。
为了让这些东西成为意思,所以我们需要在导入的时候做一些工作。
去读取每一格的东西,如果是某个要素就做什么。
比如这一格的字符串是’#’,那么我们就知道这是一个墙,就可以new一个墙的对象出来,保存到用于保存整个地图的数组里面。
你也可以保存某个字符串或者id,但是我觉得这样缺少明确的意义。
当然这里会给出示例代码(C#):
if (array[iter] == '#')
{
Wall wall = new Wall();
gridObjects[width, height, 0] = wall;
}
之后,我们可以调用gridObjects,然后去判断每一格上下左右之间的关系,写出逻辑判断。
工具封装度低 #
如果你使用的工具没有Tilemap工具,或者是不想用Tiled这是一个免费开源的瓷砖工具,适配很多引擎和框架。
那么你仍然可以考虑使用ASCII Map,并且在之后用于写非网格的逻辑。
比如说,现在打算做一个简单的RPG游戏,我们可以这样绘制一个ASCII Map:
###################
#......E........1.#
#1.........1......#
#..@.....1........#
#........1......E.#
#....1........1...#
#.......1.........#
###################
比如说,这个’@‘是玩家的意思,‘1’是树的意思,’.‘是地板的意思,’#‘是墙的意思,‘E’是敌人的意思。
把这个文件读取之后,再分配到对应的地方,创建对应的实例,赋予其对应坐标的属性。
我自己的部分写完了,但是有一个东西我想可以拿出来看一下。
有一个叫Recursed的平台跳跃解密游戏,这个游戏的地图就是用ASCII Map做的,虽然这是个商业游戏,但是游戏的源代码在游戏文件夹里面就能看得到,所以我想应该可以拿来引用一下:
local castle = { o = "brick", n = "brick_u", u = "brick_d", ["["] = "brick_l", ["]"] = "brick_r",
x = "wall", ["="] = "trim", ["#"] = "bars",
[":"] = "chain_u", ["'"] = "chain_d", ["*"] = "pillar_u", ["|"] = "pillar_d"}
function start()
ApplyTiles(castle, 0, 0, [[
xxxxu............nxx
xxxxn............u[]
xxxxu..............*
xxxxn..............|
[][]u..............|
*..................|
|...............====
|...............n[][
==========......uxxx
xxxxxxxxxn......nxxx
xxxxxxxxxun.....uxxx
xxxxxxxxxxu.....nxxx
xxxxxxxxxxn=====uxxx
xxxxxxxxxxu[][][]xxx
xxxxxxxxxxnxxxxxnxxx
]])
Spawn("crystal", 2.5, 6.5)
Spawn("lock", 4.2, 6.5)
Spawn("player", 7.8, 7)
Spawn("chest", 13.2, 11.5, "hole")
Spawn("key", 17.5, 5.5)
end
顺便一说,这是个很有意思很优秀的解密游戏,整个游戏围绕递归这一思路作为Gameplay,和Patrick’s Parabox的机制很像。如果对解谜游戏感兴趣的朋友可以试试。