游戏脚本系统的原型
来源: BlogBus 原始链接: http://gamedev.blogbus.com:80/logs/2005/11/1564148.html 存档链接: https://web.archive.org/web/20060224003545id_/http://gamedev.blogbus.com:80/logs/2005/11/1564148.html
一周游戏开发 专注于游戏开发,提供优秀的游戏开发杂志,做最好的参考 << 游戏引擎设计 | 首页 | 3D渲染的基本原理 >> 2005-11-04 游戏脚本系统的原型 TAG: 脚本 通过玩魔兽世界,或者学习OGRE以及其他比如3D Game Stdio等工具,不难让我们发现脚本系统对游戏开发以及开发的模式产生了深远的影响,脚本系统在不改变源程序的基础上,能够建立各种各样的粒子系统,能够配置渲染引擎中的各种材质,动画和各种资源信息,同时能够为游戏中的人工智能系统建立各种行为模式,这些不仅增强了游戏系统结构的灵活性,同时也提高了游戏开发的速度,在以后业余的时间里,我将为大家介绍脚本系统在游戏中的运用,以下是一个简单的脚本系统,为大家把脚本系统加入到游戏中有个全面的认识: //首先定义操作类型 enum opcode { op_talk, op_end }; //操作类 class Instruction { public: Instruction(opcode code) : _code(code) {} opcode Code() const { return _code; } private: opcode _code; //char* _data; //当然也可以为操作类型添加不同的数据 }; //接下来是一个简单的脚本类,用来装载各种操作 class Script { public: Script(const std::vector & instrList) : _instrList(instrList) {} const Instruction* InstrPtr() const { return &_instrList[0]; } private: std::vector _instrList; }; //当我们有了脚本类以后,需要有一个虚拟的机器来执行脚本,而这通常是游戏所必须要做的 class VirtualMachine { public: VirtualMachine() : _scriptPtr(0), _instrPtr(0), _instr(0), _scriptCount(0) {} // 执行方法 inline void Execute(size_t scriptId); size_t Load(const Script& script) { return AddScript(script); }// 装载脚本 private: typedef const Script* ScriptRef; typedef const Instruction* InstrRef; private: size_t AddScript(const Script& script) // add script to list and retrieve id {_scriptList.push_back(script); return _scriptCount++;} void SelectScript(size_t index) {assert(index < _scriptCount); _scriptPtr = &_scriptList[index]; _instrPtr = _scriptPtr->InstrPtr();} private: // data members std::vector }; //执行脚本的类 // rudimentary virtual machine with methods inlined for convenience class VirtualMachine { public: VirtualMachine() : _scriptPtr(0), _instrPtr(0), _instr(0), _scriptCount(0) {} // a very basic interface inline void Execute(size_t scriptId); size_t Load(const Script& script) { return AddScript(script); } private: // useful abstractions // pointers used as non-modifying dynamic references typedef const Script* ScriptRef; typedef const Instruction* InstrRef; private: // utilities size_t AddScript(const Script& script) // add script to list and retrieve id {_scriptList.push_back(script); return _scriptCount++;} void SelectScript(size_t index) // set current script by id {assert(index < _scriptCount); // make sure the id is valid _scriptPtr = &_scriptList[index]; _instrPtr = _scriptPtr->InstrPtr();} private: // data members std::vector }; //执行脚本的类 class VirtualMachine { public: VirtualMachine() : _scriptPtr(0), _instrPtr(0), _instr(0), _scriptCount(0) {} //基本的执行函数,解析脚本 inline void Execute(size_t scriptId); size_t Load(const Script& script) { return AddScript(script); } private: // useful abstractions // pointers used as non-modifying dynamic references typedef const Script* ScriptRef; typedef const Instruction* InstrRef; private: // utilities size_t AddScript(const Script& script) // add script to list and retrieve id {_scriptList.push_back(script); return _scriptCount++;} void SelectScript(size_t index) // set current script by id {assert(index < _scriptCount); // make sure the id is valid _scriptPtr = &_scriptList[index]; _instrPtr = _scriptPtr->InstrPtr();} private: // data members std::vector _scriptList; ScriptRef _scriptPtr; // current script InstrRef _instrPtr; // root instruction InstrRef _instr; // current instruction size_t _scriptCount; // track the loaded scripts }; //脚本解析的具体实现 void VirtualMachine::Execute(size_t scriptId) { SelectScript(scriptId); // select our _instrPtr by script ID _instr = _instrPtr; // set our iterator to the beginning while (_instr) { switch(_instr->Code()) { case op_talk: std::cout << "I am talking." << std::endl; ++_instr; // iterate break; case op_end: _instr = 0; // discontinue the loop break; } } } 以下是脚本系统执行的一个简单实现,通过建立脚本,装载脚本和执行脚本,我们不难了解到游戏脚本系统通常是我们遵守游戏脚本的语法编写游戏脚本,然后通过游戏引擎装载,解析来达到不改变源程序的情况下,能够配置游戏和改变游戏的各个方面。 int _tmain(int argc, _TCHAR* argv[]) { VirtualMachine vm; // build the script vector InstrList; InstrList.push_back(Instruction(op_talk)); // talk twice InstrList.push_back(Instruction(op_talk)); InstrList.push_back(Instruction(op_end)); // then end Script script(InstrList); // load the script and save the id size_t scriptID = vm.Load(script); // execute the script by its id vm.Execute(scriptID); return 0; } 源程序 ■ body1001 @ 15:24:00 [ 引用_0 ] [ 编辑 ] ▲ Top ■ 评论 ■ Add 发表评论 用户名: Email: 地址: © 2002-2005, Some rights reserved: www.blogbus.com