变量与定义变量
# 变量与定义变量
这次,我们学习的内容非常的简单,你不用担心过于复杂。
# 变量
在编程中,变量是一个重要的因素。而 Python 里的变量可以存储各种值,如布尔值、整数值、字符串...(这些在之前存档文件那一章也有稍微提到过。)
这是上次的脚本:
label ch1_start:
$ persistent.playthrough = 0
$ persistent.anticheat = renpy.random.randint(1000, 0)
stop music fadeout 2.0
scene bg club_day with dissolve_scene_full
"今天是学园祭的第一天。"
show monika 2 at t42
m "好了,各位!我们开始准备吧!"
show sayori 4r at t43
s "耶!小饼干!"
show natsuki 2l at t41
n "要不也来尝下我的纸杯蛋糕?"
show yuri 3m at t44
y "...其实都可以了。"
menu:
"那么,我该先吃些什么呢?"
"纸杯蛋糕":
n "怎么样,是不是很好吃啊?"
"小饼干":
s "怎么样,是不是很好吃?"
menu:
"我该先和谁交流?"
"纱世里":
s "你好啊!在文学部感觉怎么样?"
"莫妮卡":
m "嗨,有什么事吗?"
"夏树":
n "哼,看我干什么?"
"优里":
y "你好..."
mc "总之,以后也要多多关照!"
让我们来增加一些新东西:
label ch1_start:
$ persistent.playthrough = 0
$ persistent.anticheat = renpy.random.randint(1000, 0)
$ delete_all_saves()
stop music fadeout 2.0
scene bg club_day with dissolve_scene_full
"今天是学园祭的第一天。"
show monika 2 at t42
m "好了,各位!我们开始准备吧!"
show sayori 4r at t43
s "耶!小饼干!"
show natsuki 2l at t41
n "要不也来尝下我的纸杯蛋糕?"
show yuri 3m at t44
y "...其实都可以了。"
$ n_aff = 0
$ s_aff = 0
menu:
"那么,我该先吃些什么呢?"
"纸杯蛋糕":
n "怎么样,是不是很好吃啊?"
$ n_aff += 1
$ s_aff -= 1
"小饼干":
s "怎么样,是不是很好吃?"
$ s_aff += 1
$ n_aff -= 1
menu:
"我该先和谁交流?"
"纱世里":
s "你好啊!在文学部感觉怎么样?"
"莫妮卡":
m "嗨,有什么事吗?"
"夏树":
n "哼,看我干什么?"
"优里":
y "你好..."
if s_aff >= 1:
s "诶嘿嘿~"
mc "总之,以后也要多多关照!"
if s_aff >= 1:
call ch1_exc_sayori
elif n_aff >= 1: # 这本来可以不用加,但是保险起见...
call ch1_exc_natsuki
return
label ch1_exc_sayori:
stop music fadeout 2.0
scene bg club_day with dissolve_scene_full
show sayori 1a at t11 zorder 2
s "[player]?"
mc "怎么了?"
$ sleep_time = renpy.random.randint(0, 4)
while sleep_time == 0:
$ sleep_time = renpy.random.randint(0, 4)
s "你已经睡了[sleep_time]个小时了!"
s "这里又不是午睡部!"
mc "好啦好啦,就让我睡一会。"
return
label ch1_exc_natsuki:
stop music fadeout 2.0
scene bg club_day with dissolve_scene_full
show natsuki 2c at t11 zorder 2
n "对了,[player]。"
n "你说过你喜欢漫画对吧?"
mc "是啊,怎么了?"
n 2l "我想你一定会喜欢这个!"
"夏树把我带到了橱柜旁。"
hide natsuki
play sound closet_open
scene bg closet
"橱柜里放满了漫画。"
mc "哇!"
show natsuki 4z at t11 zorder 2
n "怎么样?喜欢吧?"
return
在上面的脚本中 $ n_aff = 0
就代表着 n_aff 这个变量等于 0。
同样的,$ n_aff += 1
就代表着 n_aff 这个变量等于自身的数量 +1。 例如,如果 n_aff 这个变量现在等于 1,那么执行完 $ n_aff += 1
后,因为 1 + 1 = 2,所以这个变量就变成了 2。
这里的 n_aff
与 s_aff
就是变量。
运行脚本,如果 s_aff 大于或等于 1,就会触发 Sayori 支线; 否则如果 n_aff 大于或等于 1,就会触发 Natsuki 线。 你可能也会发现,在这两条线路中,Sayori 和 Natsuki 都会说出 MC 的名字。
扩展知识
这里的 [player] 会被引擎自动替换成 MC 的名字。
while
是 Python 中的一种循环,用法如下:
while <条件>: # 如果条件符合:
# 执行代码...
而在这里,Sayori 支线中的以下代码就利用了 while
:
$ sleep_time = renpy.random.randint(0, 4)
while sleep_time == 0:
$ sleep_time = renpy.random.randint(0, 4)
s "你已经睡了[sleep_time]个小时了!"
代表着如果 sleep_time
这个变量等于 0 就重新随机生成整数并赋值到 sleep_time
,如果它还是等于 0 就会继续循环,否则会继续运行下面的代码。
下面的对话就会调用刚刚定义的变量,使 Sayori 说出“你已经睡了2个小时了!”之类的话。
(Ren'Py 的官方文档有对 renpy.random.randint
这个函数的介绍,如果你有所了解,会知道刚刚其实不用这么麻烦,但毕竟刚好可以演示 while
。如果想要省去 while
语句,那么可以改为 $ sleep_time = renpy.random.randint(1, 4)
)
可见,如果想要在对话中说出变量值,只需要加上一个 []
并在里面写上变量名(当然也可以是任何有效的 Python 表达式)就可以了。
# 定义变量
在 Ren'Py 中,定义变量的方式有很多种,其表达的含义各不相同。在上文,你已经学习到了一种 —— 在 Python 语句中定义。接下来,我们将为你介绍其他定义方式。
# define
通常来说,使用 define
语句定义的量会被视作常量(不会改变的量)(当然你非要修改也不是不行)
define 语句将在游戏初始化时把一个对象赋值给常量。如:
define s_aff = 0
等同于:
init python:
s_aff = 0
define 语句还可以创造或使用一个命名存储区,如:
define aff.s_aff = 0
define 也支持三个运算符:=
、+=
、|=
=
用于定义,+=
用于添加元素或合并列表,|=
用于集合(set)合并,这里不过多介绍。
# default
default 语句给一个变量赋值,前提是该变量未定义。例如:
default n_aff = 0
如果变量 n_aff
在游戏启动时未定义,则该语句等于:
label start:
n_aff = 0
同样的,default 语句也可以创造或使用一个命名存储区。
# 优先级
试着猜测在以下代码运行之后,a 的值为多少。
a.rpy:
define a = 2
b.rpy:
define a = 1
c.rpy:
define a = 3
最终 a 的值为 3。这是因为 Ren'Py 在加载代码时,会按照 Unicode 先后顺序进行加载。将 a、b、c 转化为 Unicode 码,我们发现 a 的 Unicode 码为 0061,b 的 Unicode 码为 0062,c 的 Unicode 码为 0063。因为 0061 < 0062 < 0063,所以 a.rpy 被最先加载,其次是 b.rpy,最后为 c.rpy ,所以 a 的值为 3。
在这种情况下,若我们想要让 a.rpy 被最后加载该怎么办呢?此时优先级的重要性就体现出来了。
# 修改文件名方式(不推荐)
若要使一个文件内的所有代码在我们指定的优先级内加载,我们可以在其文件名前面加上一个整数,如:要使 a.rpy
最后加载,可以将其改为 01a.rpy
,其余文件在前面加上 00
。
但是这种方法有一个弊端 —— Ren'Py 的文件优先级也为 00
,若不小心覆盖 Ren'Py 自身代码,可能会导致游戏崩溃无法运行等。
# init offset 方式
init offset 语句能在所有初始化阶段运行的语句设置优先级偏移。init offset 语句中给定的偏移量对之后同一个语句块及其子语句块的所有语句均生效,如:
init offset = 2
define abc = 2
init offset = 5
define abc = 10
init offset = 0
此时运行后 abc 的值为 10。因为 define abc = 2
一行的优先级被设为 2,而 define abc = 10
的优先级被设为 5,5 > 2, 所以 define abc = 10
最后执行。
所以,若要使 a.rpy
最后加载,我们可以在 define 语句前加上 init offset 语句,如:
a.rpy:
init offset = 1
define a = 2
init offset = 0
b.rpy:
init offset = 0 # 可加可不加
define a = 1
c.rpy:
init offset = 0 # 可加可不加
define a = 3
此时虽然 0061 < 0062 < 0063,但因为有了 init offset 语句更改优先级,此时 0 = 0 < 1,所以 a.rpy 最后执行。
# [初始化语句] [优先级] [代码] 方式
在 init offset 语句,你已经知道了 init offset 可以对优先级进行更改。但如果在一个需要大量更改优先级的文件里,init offset 就显得不合适了。此时你就可以使用 [初始化语句] [优先级] [代码] 的方式更改优先级。
如:
define 0 a = 1
define 2 a = 2
define 1 a = 3
运行之后,a 的值为 2。因为我们在 define 语句后加了一个整数表示优先级,0 < 1 < 2,所以 define 2 a = 2
最后加载。
同样的,default 语句、init python 语句也可以这样使用,如:
default 0 a = 2
default 1 a = 1
init 0 python:
b = 3
init 1 python:
b = 6
因为 0 < 1,所以运行代码后,a 的值为 1,b 的值为 6。
所以,若要使 a.rpy
最后加载,我们可以在 define 语句后加上优先级,如:
a.rpy:
define 1 a = 2
b.rpy:
define 0 a = 1
c.rpy:
define 0 a = 3
此时虽然 0061 < 0062 < 0063,但因为在 define 语句后有了优先级,此时 0 = 0 < 1,所以 a.rpy 最后执行。
注意
我们建议您将优先级限制在 -999 ~ 999 之间。超过这个区间范围可能会导致覆盖 Ren'Py 代码,游戏无法正常运行。且除特殊代码,优先级原则上不应为负数。
扩展知识
当优先级为 0 时,可以不声明优先级,因为 Ren'Py 默认优先级就是 0。