马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 枝树 于 2026-4-3 12:55 编辑
前言
这个教程面向刚接触 Ren'Py、想在视觉小说里加入答题 / 考试玩法的创作者。
最终实现的核心功能: - 随机抽题(不重复)+ 选项随机打乱顺序
- 单题限时倒计时,超时自动触发惩罚机制
- 全流程数据记录(正确率、超时次数、剧情专属数值)
- 答题结果直接对接后续剧情分支 / 多结局
[目录]
- 模块 1:全局变量初始化
- 模块 2:倒计时屏幕 + 超时惩罚机制
- 模块 3:考试入口(正式 / 模拟双模式)
- 模块 4:题目循环核心逻辑
- 模块 5:题库编写 + 随机选项实现
- 模块 6:结局分支对接
模块 1:全局变量初始化
第一步先把所有要用到的变量定义好,放在任意.rpy文件的最顶部即可,作用是全程记录玩家的答题数据。
[RenPy] 纯文本查看 复制代码 default answer_time = 15 # 单题限时(秒)
default remain_time = 15 # 单题剩余时间
default sum_time = 0 # 答题总耗时
# 答题数据统计
default correct = 0 # 答对题数
default zhonger = 0 # 恶搞选项计数(可替换成任意剧情数值)
default evil = 0 # 超时题数(惩罚计数)
default trueend = 0 # 真结局触发数值
# 题库相关
default current_q_list = [] # 存放本轮随机抽取的题目编号
default show_q_index = 1 # 给玩家展示的当前题号
# 结局解锁(persistent为永久存档,重启游戏也不会重置)
default persistent.choose_ed1 = False
default persistent.choose_ed2 = False
# 引入随机数库(抽题、打乱选项必须)
init python:
import random
模块 2:倒计时屏幕 + 超时惩罚机制
用 Ren'Py 的 Screen 功能做一个常驻的倒计时显示,同时处理超时逻辑,最后 3 秒会变红警告,时间到自动跳惩罚。
[RenPy] 纯文本查看 复制代码 # ========== 2. 倒计时屏幕 ==========
screen show_timer():
zorder 100 # 把图层拉到最高,避免被背景/立绘挡住(解决倒计时不显示的bug)
# 倒计时显示:剩余3秒变红警告
if remain_time <= 3:
text "⚠️ 剩余:[remain_time] 秒 ⚠️" xalign 0.9 yalign 0.1 size 24 color "#ff0000" bold True
else:
text "剩余时间:[remain_time] 秒" xalign 0.9 yalign 0.1 size 22 color "#ffffff" bold True
# 每秒自动减1,时间到跳超时惩罚
timer 1.0 repeat True:
action If(
remain_time > 0,
SetVariable("remain_time", remain_time - 1),
Jump("timeout_penalty")
)
# ========== 超时惩罚处理 ==========
label timeout_penalty:
hide screen show_timer # 关闭倒计时
$ evil += 1 # 超时计数+1
$ show_q_index += 1 # 题号+1,跳过本题
$ sum_time += 15 # 耗时计入总时长
jump exam_loop # 直接回到循环,进入下一题
模块 3:考试入口(正式 / 模拟双模式)
这里做了两个模式,新手可以先测试模拟模式,逻辑更简单;正式模式可以对接剧情和结局。
[RenPy] 纯文本查看 复制代码 # ========== 3. 正式考试入口 ==========
label exam:
play music "roar of water dargon.mp3" # 替换成你的考试BGM
"""欢迎来到【最终测试】!
每题限时15秒!
顺带一提,超时的坏宝宝会有惩罚哦~"""
# 每次进入考试,重置所有数据
$ correct = 0
$ sum_time = 0
$ evil = 0
$ zhonger = 0
$ show_q_index = 1
# 随机抽题:从1-30号题库里,随机抽9道不重复的题
$ current_q_list = random.sample(range(1, 31), 9)
jump exam_loop # 进入答题循环
# ========== 模拟考试入口(无惩罚、无剧情,纯练习) ==========
label examsimulate:
"欢迎来到【模拟测试】!"
$ show_q_index = 1
# 随机抽题:从1-30号题库里,随机抽5道不重复的题
$ current_q_list = random.sample(range(1, 31), 5)
jump exam_loopsimulate # 进入模拟答题循环
模块 4:题目循环核心逻辑
这是整个系统的心脏,负责自动出题、重置计时、调用题目、统计数据,实现一套题自动连续考完。
[RenPy] 纯文本查看 复制代码 # ========== 4. 正式考试循环逻辑 ==========
label exam_loop:
show class # 替换成你的考试背景
# 检查是否还有题目:没题了就结束考试
if not current_q_list:
hide screen show_timer
jump After_Exam
# 从抽好的题目列表里,取出一道题
$ rand_num = current_q_list.pop()
"==========【第 [show_q_index] 题】=========="
# 重置本题倒计时,显示计时器
$ remain_time = 15
show screen show_timer
# 调用对应题号的题目(自动匹配q1、q2...q30)
call expression "q" + str(rand_num)
# 答完题后,统计耗时和题号
$ sum_time += (15 - remain_time)
$ show_q_index += 1
jump exam_loop # 回到循环,进入下一题
# ========== 模拟考试循环逻辑(简化版) ==========
label exam_loopsimulate:
show class # 替换成你的考试背景
# 检查是否还有题目
if not current_q_list:
hide screen show_timer
jump After_Examsimulate
# 取出题目
$ rand_num = current_q_list.pop()
"==========【第 [show_q_index] 题】=========="
# 调用题目
call expression "q" + str(rand_num)
# 题号+1
$ show_q_index += 1
jump exam_loopsimulate
模块 5:题库编写 + 随机选项实现
一个题目对应一个label,用列表实现选项随机打乱,同时可以给每个选项设置不同的数值,对接剧情。
[RenPy] 纯文本查看 复制代码 # ========== 5. 题库示例 ==========
# 第1题
label q1:
# 选项格式:("选项文本", 正确得分, 剧情数值)
$ q_data = [
("发达的运动器官", 0, 0),
("能光合的器官", 0, 0),
("防失水结构", 1, 0), # 正确选项,得分+1
("河神契约", 0, 1) # 恶搞选项,剧情值+1
]
$ random.shuffle(q_data) # 随机打乱选项顺序
# 出题菜单
menu:
"水生生物成功登陆演化的关键结构是什么?"
"[q_data[0][0]]":
$ correct += q_data[0][1]
$ zhonger += q_data[0][2]
"[q_data[1][0]]":
$ correct += q_data[1][1]
$ zhonger += q_data[1][2]
"[q_data[2][0]]":
$ correct += q_data[2][1]
$ zhonger += q_data[2][2]
"[q_data[3][0]]":
$ correct += q_data[3][1]
$ zhonger += q_data[3][2]
# 答完题隐藏倒计时,返回循环
hide screen show_timer
return
# 第2题、第3题...以此类推,复制上面的模板改内容即可
label q2:
# 你的题目内容
return
模块 6:结局分支对接
考完试后,用之前统计的correct、evil、zhonger等数值,做不同的剧情分支和结局。
[RenPy] 纯文本查看 复制代码 # ========== 6. 正式考试结算画面 ==========
label After_Exam:
stop music
hide class
"考试结束!"
"..."
# 分支1:超时过多,触发坏结局
if evil > 5:
call evilend
# 分支2:触发真结局
elif trueend !=0 or zhonger >=7:
"你的答题表现,触发了隐藏剧情!"
# 你的真结局剧情
call gameend
$ persistent.choose_ed1 = True
# 分支3:普通结局,按正确率分剧情
else:
if correct >= 7:
"考得不错!顺利通关!"
# 你的好结局剧情
elif correct >= 5:
"发挥一般,勉强通关~"
# 你的普通结局剧情
else:
"正确率太低,触发了洪水结局!"
# 你的坏结局剧情
$ persistent.choose_ed2 = True
return
# ========== 模拟考试结算 ==========
label After_Examsimulate:
hide class
"测试结束!"
"正确题数:[correct] / 5"
if correct >= 4:
"太棒了!学霸!"
elif correct >= 2:
"还不错,继续努力!"
else:
"小子,继续加油啊"
return
|