游戏剧本
返回总目录
第十章 游戏剧情(Game Plot)
在大部分的RPG中,故事剧情是非常重要的。例如某些播放某些过场动画,人物台词等文字叙述的显示。这些可以推动整个游戏流程。
在Unity商店中,也有一些剧情类的插件。你可以单独使用它或单独使用我们编写的,也可以配合一起使用。
文章目录
- 第十章 游戏剧情(Game Plot)
- 一 剧本规则 (Rule of Scenario)
- 1 剧本说明(Scenario Description)
- 2 命令的选择(Selection of commands)
- 3 命令(Commands)
一 剧本规则 (Rule of Scenario)
在游戏中可以使用“剧本”(或称“故事大纲”),制作好它并使用程序执行,可以让故事发展下去,或产生事件。
1 剧本说明(Scenario Description)
能够用程序解释的剧本在格式方面有着严格的规定,而且还存在 条件分支语句(例如游戏中剧情选项) ,这跟电影(电视剧)故事大纲(或剧本)有着非常大的差距。它更倾向于“程序语言”。
想撰写游戏专用的剧本,应该先有一个“游戏专用的剧本语言”。用它来写出含有可被执行命令的“剧本”。这听起来更接近于解释型语言(例如Python,Lua等),我们称它为脚本(script)。 它不仅可以使用现有的语言,也可以自创语言,而“如何执行它们”才是我们需要做的。
关于编译型语言与解释型语言
百度百科-编译型语言
百度百科-解释型语言
例如,假设可执行命令text
表示显示对话,map
表示进入地图,if
表示条件判断语句,goto
表示跳转到剧本的位置,那么:
-
使用
xml
格式:<?xml version="1.0" encoding="utf-8"?> <GameScript name="myScript"> <contents> <TextCommand code="text" position="0" value="你是谁"/> <TextCommand code="text" position="1" value="我是主角"/> <MapCommand code="map" name="map0" resultVar="map0result"/> <IfCommand code="if" var="map0" op="==" value="0" next="goto" flag="lose"/> </contents> </GameScript>
-
使用
txt
格式:text 0 你是谁; text 1 我是主角; map map0 map0result; // 进入地图map0 if map0result == 0 goto lose; // 如果 map0result == 0,失败了,去lose
上面的例子中,表示了两个人对话后进入关卡地图的例子。
这个例子之中,在text
中有几个变量:
-
code
表示命令关键字,类似C#语言中的int
和string
; -
position
表示文本显示的位置,例如屏幕上边,左边,右边或下边(当然你也可以增加参数使用坐标x
和y
); -
value
表示要显示的文本。
同样的,在map
和if
中:
-
code
表示命令关键字; -
name
表示地图名称; -
resultVar
表示地图是否胜利的标识符名称; -
var
,op
,value
表示条件判断语句; -
next
表示下一条命令关键字; -
flag
表示goto
语句跳转的剧本标识。
就是用类似这种的剧本去推动故事。剧本是用“命令”的形式把必要的功能加到故事中,例如配合故事情节显示菜单选项,切换背景,播放过场动画等。当游戏进行到该命令的部分时,就要执行相应命令。
而语言方面,不限于使用xml
和txt
的格式,也可以使用任意一种解释型语言。这也就是之前说的, 不限于使用哪种格式,而重要的是“如何执行它们(如何解释它们)”。
而且要记住,在制作这门语言时, 最重要的是制定规则。
2 命令的选择(Selection of Commands)
在指定规则时,我们首先要考虑的就是命令(游戏主要要执行的命令),也就是说我们的剧本有什么样的功能。
在初期,我们考虑的可能不是那么全面,不过不要紧,在之后可以添加。
-
首先,是一些基础的功能:
名称(Name) 常用代码(Code) 说明(Description) 命令分隔符 ;
,\n
,<eoc>
(end of command)分割语句 注释 //
,;
,#
注释掉后面的内容 剧情标识符 #
,*
,$
可用于跳转剧情 变量 var
,int
生成一个整形变量 计算 calc
计算变量的值 条件 if
用于变量判断 跳转 goto
用于跳转剧情到标识符 切换 exec
,load script
切换脚本 -
其次,是一些在大部分J-AVG或RPG游戏中都有的功能:
名称(Name) 常用代码(Code) 说明(Description) 文本 text
用于显示对话或文本 菜单 menu
用于显示菜单或选项 图像相关 load image
,show image
等图像,CG,动画,特效等操作 音乐相关 music
,sound
等用于控制音乐,音效 暂停剧情 pause
,sleep
等用于剧本的暂停(等待玩家其它操作后激活)或指定暂停时间延迟后继续剧本 -
最后,其它一些功能,例如进入哪张地图,移动物体(例如摄像机)等。
这些功能都不是必须的,因为这些都是为我们的游戏服务的,具体要用到哪些主要还是看我们的游戏需求。
为了更加了解它的运行机制,我们采用txt
编写它,从零到有的创建一门“专属游戏语言”。
我们规定命令格式:
keycode [param0 [param1 [param2 ...]]]; // code commenting
-
先写出代码关键字:
code
; -
然后以空格
" "
作为分隔符写上参数:param0 params1 ...
; -
每个命令以“
;
”分隔符区分; -
最后是注释
//
,其后可以接注释内容。
我们创建的语言,并不要求每一行都是一条命令,而是以;
表示一条命令。如果你对行号非常的关注,更建议每一行一条命令,并且以换行符\n
表示一条命令。
3 命令(Commands)
我们找一些典型的命令,来看它们的写法。
-
命令分隔符
;
与注释//
这个很好理解,与一些程序语言相同:
我是命令 我是参数; // 我是注释
也可以与Python相同:
我是命令 我是参数 # 我是注释,在这里没有`;`,且一行是一个命令
-
创建变量
var
这个也很好理解,就是生成一个整形变量。
var a = 1; var b = 2; var c = -1;
要注意的是,这里不能写成
var a=1;
(下同),这是由格式化方法决定的,我在C#中读取字符串格式化中使用了[" ", "\t", "\n"]
分割参数。如果你需要这种“紧贴式”写法,你需要按单个字符读取并格式化。为什么只用整形变量?
我们这个不是一个复杂的编程语言,只是为了专门写剧本。
一个整形变量就可以了,可以替代
bool
(0和1);也可以进行条件判断。而其它类型变量,比如字符串,浮点数等几乎用不到。
-
计算变量
calc
计算在这里,我们规定只使用基本的四则运算,也就是没有括号,运算不能超过两个数字。这足够我们使用了。
var num0 = 1; var num1 = 20; calc num0 += 10; calc num0 = num0 * num1;
注意:这里同样不能写成
calc num0+=10;
,理由同var
。当然,如果你觉得不够,可以更改解释器支持更复杂或更多数字的运算,使用逆波兰表达式(Reverse Polish Notation)是比较不错的,几乎所有的二元运算都可以用它解决。
// 如果使用逆波兰表达式,那么多数情况只需要一个运算表达式参数 // 注意这里只有一个keycode和一个参数(运算表达式),并不是按单个字符读取。 calc num0=num1*(num2+20)/5; // keycode RPN;
-
剧情标识符
#
剧情标识符的作用是标记剧本位置,根据变量跳转剧情时使用。
例如(这里使用
#
,如果你使用Python形式,可以使用*
或$
):#标识符1 #标识符2
-
条件判断
if
与跳转剧情goto
我们这里规定
if
语句后接goto
语句,可以做条件判断,然后跳转到标签。if
语句判断暂时包含:[==, !=, >, >=, <, <=]
。例如:
var option = 0; // 建立变量 // 影响option数值的剧情 if option == 1 goto #分支剧情1; if option >= 2 goto #分支剧情2; // 相当于 else if goto #分支剧情else; // 相当于 else goto #条件结束; #分支剧情1; // option == 1 // 标识符1分支剧本 goto #条件结束; #分支剧情2; // option >= 2 // 标识符2分支剧本 goto #条件结束; #分支剧情else; // option < 1 //else标识符分支剧本 goto #条件结束; #条件结束; // 之后剧本
这看起来并不是特别难以理解,在C#中的代码对应为:
public static Class IfGoto { public static void ExecuteIfGoto() { int option = 0; // 省略影响option数值的剧情 if (option == 1) 分支剧情1(); else if (option >= 2) 分支剧情2(); else 分支剧情else(); // 条件结束后的剧情 } private static void 分支剧情1(){} private static void 分支剧情2(){} private static void 分支剧情else(){} }
就像上一个例子中展示的,
goto
语句也可以单独使用:goto #标识符2 #标识符1; // 标识符1与标识符2之间的语句不执行 #标识符2; // 这里的语句执行
-
切换剧本
exec
将正在执行的剧本停止,并执行另一个剧本。
例如,当前执行剧本为
script1
,需要在中途执行另一个剧本script2
:// 当前剧本为script1 exec script2; // 这将暂停script1,并执行script2
-
显示文本
text
在显示文本时有多种方式,根据你的游戏自定义。
两个例子:
-
固定文本UI,传入位置与文本:
text Top // 顶部位置,`Top`在C#中,用枚举会比较好,比如 WindowDir.Top 文本行0 文本行1 等等...;
-
传入坐标与文本参数:
text 200 200 100 100 // 文本窗口:X坐标200,Y坐标200,宽度100,高度100 文本行0 文本行1 等等...;
注意1:关于是否使用
"
或'
把文本括起来,这取决于你在C#中编写的格式化方法或解释器方法。注意2:我们的游戏文本都存储在一个
txt
文件中,所以参数应该会用数字id
,并不会像例子中使用字符串。 -
-
菜单选项
menu
菜单选项是非常常见的,比如大部分J-AVG跳出选项,或者RPG对话中给出选项。
菜单选项常与
if
和goto
连用:// `menuOption`是记录选择的哪个选项的变量名, // 在C#中,应在每次打开菜单时重置为不在选项中的默认值 // 选项如果从0开始,默认值最好为-1 // 选项如果从1开始,默认值最好为0 // `Vertical` 表示垂直的选项, // 在C#中,最好也用枚举来表示 // Horizontal, Vertical, Grid // 当然,有没有它也取决于你的解释器 menu menuOption Vertical 选项文本1 选项文本2 ...选项文本n; if menuOption == 1 goto #menuOption1; if menuOption == 2 goto #menuOption2; goto #menuOptionEnd; #menuOption1; // 选择1的剧本 goto #menuOptionEnd; #menuOption2: // 选择2的剧本 goto #menuOptionEnd; #menuOptionEnd; // 结束
在这些例子中,脚本的格式与应用已经比较全面,不再举例其它命令。
其它命令与上面所述的内容大同小异。
最重要的还是你的解释器如何格式化文本与如何规定参数。
等到编写时,再按需添加其它命令。
相关阅读
Description 一个高为n的连分数定义为 。 给出2个数,一个用p/q的方式表达,另一个用高度为n的连分数来表示,请你判断他们是否相等。
ER图(实体-联系图Entity Relationship Diagram)
https://blog.csdn.net/k3108001263/article/details/89578515
作为程序员,往往思想比较单一,一直以理工科的思维来思考这个世界。有时候要跳槽程序这个圈子,让自己的身心做个旅行。前段日子,请假出
Windows7下游戏全屏 发烧友设置最简法 核心提示:Windows系统的注册表是一个管理功能强大的配置表单,在这里,用户可以尝试到去用很简
A5创业网(公众号:iadmin5)12月6日报道,本月初,一种新型的勒索病毒在国内爆发,该病毒采用“供应链感染”方式进行传播,通过论坛