DDLC 中的 meta 机制分析 [2]
1 整体逻辑
点击新游戏,首先会触发 screen.rpy 中的 navigation:
# 输入名字后进入游戏textbutton _("New Game") action If(persistent.playername, true=Start(), false=Show(screen="name_input", message="Please enter your name", ok_action=Function(FinishEnterName)))ddlc 的核心脚本是 scripts.rpy, 进入一周目,执行 scripts.rpy 的 start:
2 章节实现
2.1 ch0
2.1.1 日常
script-ch0.rpy 中定义了 label ch0_main:
Sayori 刚出场的名字是 ???:

登场后名字改变,加载立绘:

部分人物立绘是通过 l, r 以及面部表情组合得到的:



label ch0_main: ... # 切换到下一个场景 scene bg class_day ... # 后续切场景,人物立绘逻辑相似,return 后进入写诗环节 ... "I'll just need to make the most of my circumstances, and I'm sure good fortune will find me." "And I guess that starts with writing a poem tonight..." return2.1.2 写诗
写诗的脚本定义在 script-poemgame.rpy 中,先来看它初始化做了什么:
scripts.rpy 调用 call poem,执行 label poem 中的语句:

2.2 ch1
首先走 Natsuki 线普通结局,改变 chapter 的值后 call ch1_main:
2.2.1 读诗前
label ch1_main: scene bg club_day with dissolve_scene_half play music t2 show monika 5 zorder 2 at t11 m "Hi again, [player]!" ... "I can't help but notice her intense expression, like she was waiting for this chance." "Meanwhile, Natsuki is rummaging around in the closet."
# 根据上一次写诗的结果调用角色剧情,eval(poemwinner[0][0] + "_appeal") 取出该角色获胜的次数,这里是 natsuki_exclusive_1 $ nextscene = poemwinner[0] + "_exclusive_" + str(eval(poemwinner[0][0] + "_appeal")) # call nextscene call expression nextsceneNatsuki 线第一个剧情定义在 script-exclusives-natsuki.rpy 中:

label natsuki_exclusive_1: scene bg club_day with wipeleft_scene n "Ugh...!" ... # 返回到 ch1_main 中,ch1_main 对话结束后再 return 到 start 中的 poemresponse_start return进入读诗环节,定义在 script-poemresponses.rpy 中:
2.2.2 读诗的反应
以 Sayori 为例, call poemresponse_sayori,Yuri 和 Natsuki 逻辑类似
label ch1_s_med: s "..." s 2x "This is a good poem, [player]!" s "Are you sure it's your first time?" mc "Of course..." mc "It's not that good." mc "Am I the kind of guy who would be writing poems in his spare time?" s 2q "Ehehe, I guess you're right~" s 1q "But that's why it impressed me!" s 1d "Well, to be honest..." s "I was afraid that you wouldn't do it seriously..." s "Or that you wouldn't write one at all." jump ch1_s_shared跳到 ch1_s_shared:
label ch1_s_shared: s 1a "I'm really happy just that you wrote one." s "It just reminds me of how you're really a part of the club now~" "(Not to mention the fact that I'm standing in front of you in the clubroom...?)" ... return执行结束后回到 poemresponse_sayori 中执行 ch1_s_end:
label ch1_s_end: # 展示诗 call showpoem (poem_s1) mc "Sayori..." mc "This is just a guess, but..." ... return角色的诗定义在 poems.rpy 中:
Monika 虽然也有 poemopinion,但是逻辑稍有不同:
2.2.3 end
全部角色读完之后 return 到 script.py 然后 call ch1_end:
进入第二次写诗,这里仍然选择 Natsuki,开启下一个章节
2.3 ch2
label ch2_main: scene bg club_day with dissolve_scene_half play music t2 ...
# 进入 natsuki_exclusive_2 $ nextscene = poemwinner[1] + "_exclusive_" + str(eval(poemwinner[1][0] + "_appeal")) call expression nextscenelabel natsuki_exclusive_2:...label natsuki_exclusive_2_ch3: "I pull the first volume of Parfait Girls out from my bag." ... # definitions.rpy 中定义了 default persistent.clear = [False, False, False, False, False, False, False, False, False, False] # 记录解锁了哪个 cg $ persistent.clear[1] = True $ renpy.save_persistent() scene n_cg2_bg show n_cg2_basecall poemresponse_start 的逻辑与之前类似,略过
进入 ch2_end:

label ch2_end_natsuki: mc "Walking home with Natsuki, huh..." "Why does the thought of that make my heart pound...?" mc "I mean..." mc "I think I would be afraid of what she'd do to me if I turned her down..." s 1x "Isn't she so cute and fun to be around?" # 跳转到 end_shared jump ch2_end_shared
label ch2_end_shared: mc "That has nothing to do with what I just said!" s 4s "Ahaha! You admitted it!" ... return进入第三次写诗,选择 Natsuki,开启下一个章节
2.4 ch3
选择给 Sayori 读诗:
选择给 Yuri 读诗:
label ch3_y_bad: if y_poemappeal[0] < 0 and y_poemappeal[1] < 0: label ch3_y_bad12_shared: y 4b "..." "Yuri doesn't look too enthusiastic about spending time with me..." "I guess if she changes her mind, she'll come to me." "But I should leave her be for now." # 跳过读诗 $ skip_poem = True return选择给 Natsuki 读诗:
return 到 ch3_end:
# 进入 natsuki endlabel ch3_end_natsuki: # 设定 ch4_scene 的值 $ ch4_scene = "natsuki" mc "Well, baking sounds like it could be fun..." mc "And you guys made it sound like a lot of work, so it could probably use two people."
... # 向上 return 到 ch3_end 继续执行 returnlabel ch3_end: scene bg residential_day with wipeleft_scene $ ch4_name = ch4_scene.capitalize() "I can't believe this!" "[ch4_name] is going to be coming to my house on Sunday...?" # 只有 sayori 结局这里才为 True if help_sayori: ... else: "My anxiety shoots through the roof."... # 向上 return,开启 ch4 return2.5 ch4
2.6 ch5


return 到 script.rpy 后进入 endgame:
label endgame(pause_length=4.0): $ quick_menu = False stop music fadeout 2.0 scene black # 显示 "gui/end.png" show end with dissolve_scene_full pause pause_length $ quick_menu = True # 向上返回到 start,再 return 回主界面 return