怎么实现类似单机游戏里的剧情,人物会移动,对话,玩家选择,剧情不同走向,最最好当然是能用一个类似配置文件来实现
我记得雾霾侠的直播里面有做过这种功能,你可以去翻一下雾霾侠的视频录播。
有本书《visual c++角色扮演游戏程序设计》里面就完成了这样的功能,你可以搜一下。还有一本书也值得看《游戏脚本高级编程》
半天了,我觉得还是有必要给你讲一下这本书里实现方法,我去年也问这个问题的时候,找了半天没人给我解决,最后我看了这本书,再到英文网站找到解决方案。可能大家觉得简单,就懒得说明了,但是讲道理,对新手来说,还是很难的。也不能叫难,新手不知道怎么做到代码最优化,数据结构不知道如何配置、读取、使用。
播放剧情,像游戏的开始logo播放,到游戏里的剧情,再到战斗场景的剧情,用纯代码写,能写出来,如果剧情太多,太繁琐,你用纯代码写是很费劲的,如果你只有一个剧情,你可以直接硬写进程序里,比如一个updat函数,然后里面有各种if else,然后就是各种flag条件,这是初级的想法。高级点的,就是类似于写bat脚本,逐行执行。
《visual c++角色扮演游戏程序设计》这本书里使用了“基于命令的脚本”(这个词其实是《游戏脚本高级编程》这本书里的)。基于命令的脚本,就是“指令+参数”的形式。如下:
GetNPC npc01
ShowFace "生气"
MoveTo 200,400
Text "你今天去了那里?"
WaitForSeconds 2s
GetNPC npc02
ShowFace "不安"
MoveTo 600,400
Text "我哪里也没去啊!"
接着,你要设计一类比如ScirptAction来执行这个脚本,如ScriptAction->runPlot(thisPlot)接着你要为每一个命令设计一个成员函数:
GetNPCFunc(para);
ShowFace(para);
MoveTo(para1,para2);
......
接着就是读取一行脚本,然后判断指令,调用对应的函数,然后第二行,如此循环。你可以想象到这得用到多少if else或者switch case!尤其是当你的指令函数相当多时,这就得用到“表驱动”“数据驱动”这样的东西,你的代码才好看。
在C++中,你要创建一个map,然后把“字符串”和“成员函数”对应存储进入这个map,这里用到了“成员函数指针”,如下所示:
typedef void (ScriptAction::*cmd_t)(Lexer&);
typedef std::pair<std::string,cmd_t> CmdTab;
typedef std::map<std::string, cmd_t> CmdMap;
ScriptAction::ScriptAction()
{
cmd_table.insert(CmdTab("GetNPC",&ScriptAction::GetNPCCmd));
cmd_table.insert(CmdTab("Text",&ScriptAction::TextCmd));
cmd_table.insert(CmdTab("MoveTo",&ScriptAction::MoveToCmd));
}
void ScriptAction::parserString(const char* str)
{
Lexer lexer(str);
cmd_t cmd =parseCommand(lexer);
(this->*cmd)(lexer);//这句话就是调用指令函数
}
javascript里就方便多了,每一个类都是一个对象嘛,比如:
var methods = {
GetNPC : function(string){....},
Text : function(string){.....},
MoveTo : function (string) {.....},
.......
}
cmd = parasCommand(string).c_str;
methods[cmd](string);
这个例子可能不太完美,当伪代码看了。
接着你可能会遇到一个问题,我如果设计一个“基于命令的脚本”,有点多此一举了,还要再设计一个脚本解析器进行语法分析词法分析。对于creator的js来说,js本身就是脚本,为何不把上述脚本安key-value的形式在js文件里存储。就是这样:
[
{"cmd": "GetNPC", "para" : "role01"},
{"cmd": "Text", "para" : "你在说什么呀?"},
........
]
或者你也可以这样,但是这样做,你得稍微写点解析的东西:
[
"GetNPC#role01",
"Text#你在说什么呀?",
....
]
但是如上配置js剧情,是个体力活,你要是有excel或者creator一些插件,然后设计一套键值格式给你策划用。
如上,这就是《visual c++角色扮演游戏程序设计》这本书里的解决方案。你要设计一个“基于命令的脚本规则”,你要设计一个ScriptAction类来逐行运行脚本,最重要的,就是创建一个表,保存指令对应的成员函数,以方便调用。《游戏脚本高级编程》在第三章里有讲述“基于命令的脚本”,这本书后面的结构化脚本,其实就是实现了类似cocos2d-js脚本绑定的东西,那是另外一回事了。
以上并没有说一些指令数据结构、指令完成后回调函数等,你要自己完成。
当然,也有终极解决方案,是为你的每一条命令设计一个类(以上的例子是为每一个指令设计一个函数),unity3d上有一个文字交互游戏的解决方案,是开源的,你可以学习一下Fungus(若有疏漏和错误的地方,请指正,谢谢)