找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 5492|回复: 0

[教程] 如何在RenPy中笨拙地实现一种功能齐全的QTE?

[复制链接]
发表于 2020-3-4 22:57:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 立笔犊 于 2020-3-4 23:09 编辑

QTE,即快速反应事件,就是玩到一定地方突然需要点点点或者按按按,超出时间没按完就会失败。
在视觉小说中添加QTE能增加紧张感,另外QTE在游戏中也算比较常见的设定。
那么如何在RenPy中实现QTE呢?
在英文论坛上好像已经有一些人实现过了,不过我没看。
首先要确定一下功能:
1、最好QTE可以同屏出现多个。2、最好QTE可以点击多次。
3、最好QTE可以延迟出现(比如以一定顺序先后出现)。
(4、最好QTE可以有一些条、滑块之类的装饰物)

其实如果单个、点击一次、立刻出现的QTE是非常好写的,就界面语法,按钮+计时器,判断返回值,几行就搞定了。
但是要实现以上这些功能就会比较麻烦。
我摸索了好久,摸索出了好几种实现方法(也摸索出了一堆RenPy界面语法与UI函数与类混杂时会发生的bug),最终得出了一个尽量简洁但仍显笨拙的实现方法,仅供参考,如果有更好更简洁的实现欢迎交流~~

演示视频:
演示视频.zip (62.46 KB, 下载次数: 34)


下面是一些讲解,因为实现得很笨拙,估计可能很难看懂。

一、首先定义一些图,比如按钮、滑块、槽之类的。
[RenPy] 纯文本查看 复制代码
##这几个图片是QTE测试的默认图片,放在image文件夹里
init -1 image qte_button:
    "button.png"
    pause 0.2
    "button2.png"
    pause 0.2
    repeat

init -1 image qte_bar:
    "left.png"

init -1 image qte_thumb:
    "thumb.png"

# 滑动块不带参的变换的示例
transform qte_thumb_trans:
    xpos 0
    linear 2.0 xpos 400

# 滑动块带参的变换的示例
transform qte_thumb_standard(delay_time, show_time):
    pause delay_time
    xpos 0
    linear show_time xpos 400


二、写一个QTE生成器的类,具体懒得解释了,其实不难
这个QTE类采用的是“先装配,再生成”的模式,一些set函数可以调整按钮、滑块、槽的位置等参数,add_qte函数用来按照配置生成一个QTE。其实这里的QTE就是一个imagebutton,会ui函数的朋友可以自己随便修改。
[RenPy] 纯文本查看 复制代码
init python:
    class QTE:
        #对象初始化时对各个参数赋值
        def __init__(self, qte_button=None, qte_bar=None , qte_thumb=None):
            #三个基础部件,按钮、时间条、滑动槽
            self.qte_button=qte_button
            self.qte_bar=qte_bar
            self.qte_thumb=qte_thumb

            self.qte_button_trans = None
            self.qte_bar_trans = None
            self.qte_thumb_trans = None

        def set_button(self, qte_button=None, trans=None):
            self.qte_button = qte_button
            self.qte_button_trans = trans

        def set_bar(self, qte_bar=None, trans=None):
            self.qte_bar = qte_bar
            self.qte_bar_trans = trans

        def set_thumb(self, qte_thumb=None, trans=None):
            self.qte_thumb = qte_thumb
            self.qte_thumb_trans = trans

        def add_qte(self, offset, sv, sv_value, sv_all=None, sv_all_value=None):
            action = [SetScreenVariable(sv,sv_value-1)]
            if sv_all != None:
                action.append(SetScreenVariable(sv_all, sv_all_value-1))

            ui.fixed()
            if self.qte_button != None:
                if self.qte_button_trans == None:
                    ui.imagebutton(idle=self.qte_button, offset=offset, action=action)
                else:
                    ui.imagebutton(idle=self.qte_button, offset=offset, action=action, at=self.qte_button_trans)

            if self.qte_bar != None:
                if self.qte_bar_trans == None:
                    ui.add(self.qte_bar, offset=offset)
                else:
                    ui.add(self.qte_bar, offset=offset, at=self.qte_bar_trans)

            if self.qte_thumb != None:
                if self.qte_thumb_trans == None:
                    ui.add(self.qte_thumb, offset=offset)
                else:
                    ui.add(self.qte_thumb, offset=offset, at=self.qte_thumb_trans)
            ui.close()


三、写几个QTE界面
每个QTE的点击次数对应一个界面变量,如qte1、qte2。
该界面中所有QTE的点击次数加起来设为qte_all。
在调用qte.add_qte传入参数:QTE的位置、界面变量名称、界面变量的值、总QTE次数变量名称、总QTE次数变量的值。
而如果是多按钮多点击延迟版的QTE其实就是定时器+条件判断,时间到了就显示,显示后再开始一个计时器。
其实理解了还是很容易,就是重复代码比较多,还是比较笨拙。
也没办法,RenPy限制还是太多了。
[RenPy] 纯文本查看 复制代码
screen QTE_sample_1():
    #首先需要创建QTE生成器的对象
    python:
        qte = QTE("qte_button", "qte_bar", "qte_thumb")
        qte.set_thumb("qte_thumb", qte_thumb_trans)

    default qte1=1
    default qte2=2
    default qte_all=6
    if qte1:
        $ qte.add_qte((0,0), "qte1", qte1, "qte_all", qte_all)

    if qte2:
        $ qte.add_qte((200,200), "qte2", qte2, "qte_all", qte_all)

    default qte3=3
    if qte3:
        $ qte.add_qte((400,400), "qte3", qte3, "qte_all", qte_all)

    #总体的计时器,时间到了就返回False,gg
    timer 2.0 action Return(False)

    #每过一段时间检测是否当前所有按钮已按下,全按了则返回True
    #如果与总体的计时器同时到了时间,目前看来这个 计时器更先判定,但不排除风险可能
    timer 0.5:
        if qte_all:
            action NullAction()
        else:
            action Return(True)
        repeat True

#这是多按钮多点击延迟版的QTE
screen QTE_sample_2():
    python:
        qte=QTE("qte_button", "qte_bar", "qte_thumb")

    default qte_all=5

    default qte1 = 0
    timer 1.0 action SetScreenVariable("qte1",2)
    if qte1:
        timer 2.0 action Return(False)
        $ qte.set_thumb("qte_thumb", qte_thumb_standard(1.0, 2.0))
        $ qte.add_qte((0,0), "qte1", qte1, "qte_all", qte_all)

    default qte2 = 0
    timer 2.0 action SetScreenVariable("qte2",3)
    if qte2:
        timer 2.0 action Return(False)
        $ qte.set_thumb("qte_thumb", qte_thumb_standard(2.0, 2.0))
        $ qte.add_qte((500,0), "qte2", qte2, "qte_all", qte_all)

    #每过一段时间检测是否当前所有按钮已按下,全按了则返回True
    timer 0.5:
        if qte_all:
            action NullAction()
        else:
            action Return(True)
        repeat True



四、在主流程中测试一下,根据界面返回值_return判断QTE是否成功。
[RenPy] 纯文本查看 复制代码
label start:

    "同一个屏幕有多个QTE、每个QTE可以点多次,所有QTE一开始都出现"
    call screen QTE_sample_1
    if _return == True:
        "龙没听龙活了"
    else:
        "龙听完龙死了"

    "同一个屏幕有多个QTE、每个QTE可以点多次,有的QTE过一会儿才出现"
    call screen QTE_sample_2
    if _return == True:
        "龙没听龙活了"
    else:
        "龙听完龙死了"


差不多就是这样。
其实我还尝试过用户自定义组件做QTE,理论上那样封装出来应该会更加简单。但是在如何判断鼠标点击到按钮上的时候遇到了问题。因为没有研读过renpy源码(还远没到直接看源码的水平)并且renpy也没有提供这样的基类或者直接用的事件(只提供了封装好了的button),所以并不清楚点击事件应该如何判断,尤其是如果有透明度的话更难。

这个还是给我之前那个朋友做的,不过没有用在《罗曼圣诞探案集》里了。


评分

参与人数 1干货 +1 收起 理由
BuErShen + 1 鼓励原创!

查看全部评分

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|RenPy中文空间 ( 苏ICP备17067825号|苏公网安备 32092302000068号 )

GMT+8, 2024-4-25 03:16 , Processed in 0.059542 second(s), 15 queries , File On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表