|
有很多人问过我,想做好一个游戏策划,应该从哪儿开始学起,我都会告诉他们从做一个《仓库番》开始,至今都有很多人并不明白为什么我要说从仓库番做起。事实上,仓库番背后藏着很多有价值的好东西。
麻雀虽小五脏俱全
别看仓库番只是一个小游戏,如果你真要动手去做,那么有很多开发游戏的基础知识,你会需要先去掌握。之所以说这些是基础知识,是因为你在任何游戏开发中都会用得到它们。这些知识包括且不限于:
基础知识:游戏的常见数据结构
首先,你逃不掉的是必须了解一些游戏的数据结构,没有他们游戏是运作不起来的。在仓库番这个游戏中,你需要第一个接触的概念就是2维数组的地图。你可能从一些书籍中看到过仓库番的代码(大多教你程序入门的书里都有仓库番这个范例,至少……17年前的书是这样),他们的地图用了int[][] Map,为什么是二维数组,因为它的下标正好映射到地图的横轴纵轴,比如左起第3列和上起第4行的格子,通常是Map[2][3] (一般来说下标都是0开始的,当然也有Lua这样从1开始的),而之所以是int,因为它是一个枚举,代表了这个格子是什么东西(可以过的地板,还是不可以过的墙壁,还是箱子的目的地),通常教科书里会把这个数字代表了所有这些功能,当然这不是一个好主意,这在后面会说到。
以上是无比基础的知识,但是由这个知识引出了一个话题——通常我们国游策总觉得地图编辑器是个神奇的东西,只要在地图编辑器里面拼好了地图在游戏里面就会出现,所以总认为地图编辑器是一个魔法盒子,你往里面输入了东西游戏马上就会生效。事实上并不是这样的,地图编辑器这是一个可视化(让人类看起来更简单的)环境,让你输入了一整张地图的这个int[][]信息而已,他从来就不是什么魔法盒子,所以当你做了仓库番之后,你就应该会明白这些基础常识。
这里还会有一个细节,一些教科书里,你会发现地图上除了可以过、不可以过、目的地这3种类型的格子,还会有箱子、放好的箱子、主角这样的单元格。事实上这样的抽象是错误的,因为恰好人和箱子总是可以站在可以过的地形上,并且可以过得地形都是一样的。而好的做法应该是(伪代码):
主角的数据:
- Player: {
- X : int,
- Y : int.
- faceTo: enum //面向应该是一个enum,如果用int那就是一个magicnumber
- }
- 箱子的数据:
- Box: {
- X:int,
- Y:int
- }
- 箱子目的地的数据:
- BoxTarget: {
- X:int.
- Y:int
- }
复制代码
而整个游戏中主角只有一个,箱子是Array的。为什么这么做?如果你只是奔着克隆一个简陋的,30年前水平的仓库番,那么上面的做法也可以,不过这是标准的IJW的代码(it just work),时不提倡的,我说的这种做法是正确的,因为角色并不属于地图,箱子和箱子的目标也一样不属于地图,从程序的角度来说,这就是一个对象之间的依赖性关系决定的,地图不依赖于这些,没有主角、没有箱子、没有箱子的目标地图一样可以存在,但是相反的,没有地图,这3个存在就没有价值,他们依赖于地图,至少目前这个游戏中是这样。
所以,我希望新人可以做一下仓库番,这样你就不会困惑一些奇怪的问题(比如认为地图编辑器是一个魔法盒子),并且你对游戏常用的一些数据结构也会有一定的基础。
基础知识:视觉依赖于逻辑
当你写完了逻辑部分代码的时候,这个游戏还跑不起来,因为没有视觉的部分,没错,但是如果让计算机玩,只要有了关卡数据,那就能玩的起来。所以,但就这点来说,没有视觉元素,游戏一样可以存在,但是只有视觉元素,没有逻辑的部分,那些视觉元素不过就是没有灵魂的图片罢了,这就是视觉依赖于逻辑的核心所在。
当然实际操作中,我们很多时候会把视觉和逻辑混做一谈,罪魁祸首就是我们认为我们肉眼看到的那个角色,就是实际上的逻辑角色。但是如果你这样写过仓库番,并且真的思考过,你就会发现,实际上真正的角色是哪个逻辑上的Player这个struct,画面上,他是一个圆圈,是一个等腰直角三角形(直角代表面向),或者是一个小人,一个小狗,一辆汽车都是可以的;同样的,你的角色、场景什么的是2D和3D的都没关系,他们的信息都来自于逻辑层的这些数据(Map Player Box BoxTarget)但是不管他看起来是什么,他的位置、面向全部是依赖于Player这个信息的,而不是等于Player这个信息的,并且Player这个信息更不应该是属于这个贴图的。在没有游戏框架(没有unity,没有cocos等)的年代里,甚至早期传奇时代,还有人用GDI渲染的时代,OOPer们已经有人开始自作聪明的走弯路,走Image等派生出角色,包含了player信息,正因为这个“自作聪明的错误”,结合现在“所见即所得的渴望”,产生了逻辑反过来依赖视觉的错误,最常见的是做动作游戏的时候甚至有人拿角色的图片做hitTest……
所以、我希望新人能做一下仓库番,这样你会领悟出很多游戏开发中的基础依赖关系,不至于越走越偏。
基础知识:操作不等于命令
很多教科书里的仓库番,有这样一个错误,他们在按键的地方直接写了角色移动的逻辑。事实上我们思考一个问题,如果没有操作,我们做一个放置类的仓库番可以吗?假如我们做的是一个仓库番的攻略视频一样的小软件,没有了操作,所以角色就应该不能移动了么?不是的,我们依然会有“命令”让角色移动,这些命令实现方法很多,但是很明显,他是对于角色的一个操作,比如最常见的是Player.Move(direction),让角色向某个方向尝试移动。而操作,仅仅只是根据按键来决定怎么调这个函数而已。虽然感觉这是绕了一步,但是也只有这样绕一步才是对的,因为接下来,我们就要思考的一个问题,会证明那些不负责的教科书里的做法,纯属瞎扯淡。
思考与扩展从了解开始
当你会写仓库番之后(我相信熟练的话,比如我,1、2个小时就能做出一个仓库番游戏了,当然,是只抄袭了1关的那种),你就有了对仓库番做手术,把它变成另外一个游戏的资格了,接下来我们要从传统理解的策划的角度来思考一些问题:
符合平台的操作:点击地面走路
在2017年的今天,我们大多80后用的还是PC,而对于90后00后或者更早的人,他们用的更多的则是手机。仓库番的大多版本(尤其是教科书版),他的操作都是4方向按键的,上下左右,并不符合Smart的设计,现在的设计,就应该是你点选了地面,然后角色就走过去(如果可以走过去的话),这是一个并不过分的需求,也应该是一个策划理所当然就想到的。
那么,接下来我们就要考虑这个方案能不能行?答案肯定是可以的,但是这里就不仅仅是简单的引入AStar来巡路了,你还要把原来的Player.Move(direction)这个接口改了,变成Player.Move(targetX, targetY)。当然,事情还是并非那么简单的,你还需要思考这个轨迹应该如何?如果我帮玩家定制了轨迹,是不是这就代表玩家可以不用动脑筋了?因为从哪个方向推动箱子,可是仓库番的重要玩点。那么有没有一种寻路方法可以避免这个帮玩家自动选择推箱子方向的寻路?事实上不存在,因为这里的核心是推箱子的角度的策略,是一个必须由人脑思考的问题,所以最后,这个设想并不理想——我们不应直接使用AStar来做一个简单的寻路,让玩家点那儿角色就往哪儿走。
那么是不是这个Smart的操作就不该要了?其实鼠标和手势操作都有一个可接受的方案,就是让用户划出一条要走的路径,而我们要做的就是判断这条路径是否靠谱,如果OK,就替玩家执行,执行到不能执行,就结束(比如玩家划得线一直划到墙外了,我们只要保证主角走到墙边就行了)。
所以,事实上一个策划的设计,并不应该是拍脑袋的,如果你说我只是点击一下然后角色走过去,我相信那一定是拍脑袋想出来的“好主意”,但是如果你是划线的设计,不仅程序轻松,而且方案还靠谱,这关键在于你思考过了,基于你了解实现方式。
扩展,从地图多样性开始
30年乃至20年前,我们还能接受所有的可以走的地形都长一样,所有不可以走的地形也都长得一样,甚至连转角和普通的墙都可以不分,但是到了今天,这个思想一定是不行的。所以我们开始为仓里番进行追加设计了,我们是不是应该不同的关卡,用不同的场景,比如前5关在森林里,各种树木是障碍这样?然后后几关在沙漠,仙人掌是阻挡?
是的,当你想到这里,只是视觉上的变化,你的地图信息还只是int[][] Map还是足够的,事实上足够的意思是,你企图用一个int代表一种贴图的tile,所以才会有了这个思想。如果我们允许放开脑洞,大胆思考——比如我地图加一种格子,每m个回合(之所以用m,是因为m可以在不同的条件下不同)变换成阻挡地形持续n个回合;再比如当有m个箱子就位(放在箱子目标上)了,有些地形就会从不可过变成可过。我们先不说这样的设计好不好,不要因此去阻碍一个策划思考,那么这个时候你的int[][]还“够”么?
所以,是时候你该想到了,这不应该是一个int[][] Map,而是gridInfo[][],而gridInfo,这才是真正的地图信息。而在很多游戏中,比如火纹、高战,他们也都是tilebased的地图,地图数据结构和这个仓库番可以是一样的思路,但是他们的单元格就像我这里说的是gridInfo[][]的,只是不同的需求下,GridInfo可以是不同的,比如高战里的:
- gridInfo{
- Cost: {
- foot : int,
- wheel: int,
- flight: int,
- pedrail: int
- }.
- Defense: int,
- Type: enum
- }
复制代码
他要记录的是每一种移动方式经过这个格子的cost值(如果很大基本就是不可过),这个格子的防御星级,他的类型(普通、老家、楼房、兵工厂……)。
所以,当你先学会写仓库番之后,你就开始真的会写游戏了,也真的开始知道怎么设计游戏了,你还可以基于这些知识,合理的开始发挥创意了。
作为一个游戏人,所谓的术业有专攻,说的术业就是如何做出游戏,而不是策划工作或者程序工作什么的,就好比你如果是学电子专业的,整个电子技术才是你的术业,而数字电路、模拟电路不过都是一门学科,你总不能说你的术业专攻的是数字电路吧。所以学会写代码,是你作为一个策划最基础的条件,同样的,上面也给你介绍了为什么要你学会代码的一些原因。那么最后我还有一句警告的话要送你——即使你能写出仓库番了,就像我说的那样,随便你用什么语言写出来了,但你真别以为你就是程序员了。同样的,你身边那些领着程序员工牌写着代码的人也未必是真的能是程序员。如果你不信,我随便出个程序员的问题你回答看看:Java 8 (JDK1.8)引入的一个新特性是什么?它意味着什么?
|
|