作者:tony
博客:http://blog.sina.com.cn/auroratony


  弹性对游戏逻辑层至关重要,因为我永远无法预知需求,只能在仅知晓有限既有需求的情况下尽可能的写出富有弹性的代码并希望不断解决新的需求和挑战时不要让代码越来越凌乱。健康的游戏逻辑模块粒度(包括源码文件数量、功能片数量、函数数量、单函数大小)适中,不会太细以至于要完成一个功能需要在脑袋里联想起根本记不住那么多的接口,也不会太粗以至于对于新的需求总是发现已有接口不能组合出来。逻辑模块只提供机制,数据驱动组装出功能。按情境不同配置文件和脚本都能充当驱动源。

  designer们一般在和programmer谈论一个问题的解决方案时是宁可让programmer做出个有GUI的编辑器也不愿学习怎样写脚本的,即使两者使用上的复杂度不见得相差多大而且脚本应对变化时更灵活。可以理解。一路苦逼的学写代码容易让人觉得山重水复而放弃。我最初学编程时面对那么多概念,领会起来还是苦逼了很久的。如果一个没有程序经验的新手一点一滴的积累,学一点尝一点甜头,学多少尝多少,会柳暗花明的。

  最近我就干了这么一件事儿:原本的需求只需要我写出一些小的机制然后让designer填些配置文件就能驱动功能运转起来,但是后面又有了新的需求,我发现单调的配置项越来越乏力了,于是我把原本的配置山寨成了一个领域特定脚本语言。本来新需求最初用配置是可以解决的,而且就当时最直接的需求而言用配置效率要高些,但是你知道programmer的洁癖或脾气上来了是不好拦住的,于是我写了一个现在已支持import、refer、if-then-elif-else、脚本接口调用、注释、数组的小语言,虽然if不支持嵌套,它也不是图灵完备的语言,但是对于从那时到项目结束的需求会足够简单够用了,写起来上手读起来上口。现在来看当时的决定也是明智的,牺牲一点点效率换取弹性是很值得的。当我给designer解释这么一个东西之前designer先和我说了他所设想的配置文件的解决方案,然后我对他解释完这个东西(当时我还把它称为配置而不是脚本以避免人家排斥)后,designer对我说“这种方案还是非常灵活的”,于是延用下来的这套东西就从最初只支持脚本接口调用演变成了现在这个样子。对于以后的新需求只需要添加新的脚本接口充当机制就可以了,我不打算再往这个玩意儿里加太多通用性的特性了,如果需求真的发展到了此山寨语言解决不了的时候我就直接把MY-BASIC或Lua什么的集成进来。我相信designer在经历一番渐进的把脚本理解成灵活的配置使用的阶段后会对写脚本这件事不那么排斥。

进入想说的正题。

对于一套新拿到手的脚本库,我大概想了一下阅读的线索。如果你想读脚本库希望下文能给你启发。

整体:

一、语法特性,语言的BNF表示。在深入了解机理之前先对要阅读的系统能实现哪些功能,不能实现哪些功能至少有个印象。

二、从脚本源代码到可运行的数据结构的解析过程分几遍,哪几遍。理一下大体的深入研究步骤,对一些脚本库可能会找到相关实现的书籍、网络资料或官方文档等,理清这一点相对容易;如果资料较少则大概浏览一下整个库的源码有哪些文件,文件里都说了些和什么相关的东西。

运行前:

一、词法分析。是否使用自动化工具生成了这部分模块。这部分相对容易。

二、语法分析,AST或等价数据结构。是否使用自动化工具生成了这部分模块。语法分析后的数据结构是什么。是否语法分析后的数据结构就是最终在运行环境里可执行的数据结构而不再经过下面三个步骤。

三、语义分析,中间、目标代码生成的流程和数据结构。表达式解析,函数调用相关处理,函数是否为第一类对象,对声明式语法的支持,是否支持JIT等。

四、代码优化。

五、调试信息。从脚本源码到目标数据结构是否有对应关系用于在目标数据结构运行时出现异常情况时能给出足够丰富的调试信息。

运行时:

一、语言内置对象在实现语言中的数据结构、类型表示、创建销毁策略。是否

struct {

type;

union;

}

样式的对象表示,还是。是否泛型、动态类型,销毁策略。

二、复杂类型。集合类型,结构体类型,类等。

三、目标代码运行环境。是否用了现成的语言后端运行环境库。有无虚拟机,如有是基于栈还是基于寄存器。

四、并发编程。

五、与宿主语言交互。脚本调用宿主函数,宿主调用脚本功能,脚本可重入挂起,数据结构转换,扩展库的实现方案。
锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛