找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 775|回复: 7

[教程] PressedButton 挤压按钮

[复制链接]
发表于 2024-6-1 00:51:04 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 ZYKsslm 于 2024-8-15 23:29 编辑

PressedButton 挤压按钮


最近在论坛看见有人在问如何获取长按事件,索性自己花了点时间写了一个新的用户接口(确信)。


使用要求:
  • 将源码复制到项目的 game 目录中并保存为 rpy 脚本文件。
  • 或是直接将本帖附件保存到项目的 game 目录中。

提示:
  • 该接口尚通过初步测试,有任何问题请及时反馈

源码:
[RenPy] 纯文本查看 复制代码
python early:
    import pygame

    class PressedButton(renpy.display.behavior.Button):

        def __init__(self, *args, **kwargs):
            self.press_action = kwargs.pop("press_action", NullAction())
            self.release_action = kwargs.pop("release_action", NullAction())
            self.press_time = float(kwargs.pop("press_time", 0))
            self.stable_updater = kwargs.pop("stable_updater", [0])

            super().__init__(*args, **kwargs)

            self.updater = 0
            self.size = (0, 0)
            self.clock = 0
        
        def render(self, width, height, st, at):
            self.size = renpy.render(self.child, width, height, st, at).get_size()
            return super().render(width, height, st, at)
        
        def event(self, ev, x, y, st):
            if not ((0 <= x <= self.size[0]) and (0 <= y <= self.size[1])):
                return

            if ev.type == pygame.MOUSEBUTTONDOWN and ev.button == 1:
                self.clock = st
                self.updater = 0
                renpy.timeout(0)
            
            elif ev.type == pygame.MOUSEBUTTONUP and ev.button == 1:
                if self.clock:
                    self.clock = 0
                    self.updater = 0
                else:
                    renpy.run(self.release_action)
                    return
            
            if self.clock:
                if (elapsed_time := st - self.clock) >= self.press_time:
                    self.clock = 0
                    self.updater = self.press_time
                    renpy.run(self.press_action)
                else:
                    self.updater = elapsed_time
                    renpy.restart_interaction()
                    renpy.timeout(0)
                    
            return super().event(ev, x, y, st)

        def visit(self):
            return [self.child]

    renpy.register_sl_displayable("PressedButton", PressedButton, "pressed_button", 1
    ).add_property("press_action"
    ).add_property("release_action"
    ).add_property("press_time"
    ).add_property_group("button")

style pressed_button:
    is fixed


使用:
因为 PressedButton 继承自 renpy.display.behavior.Button ,所以使用方式与 Button 基本一致且拥有其所有的特性
但不同的是:

  • 需要改用 PressedButton 关键字。
  • 需要添加 press_action 、release_action(可选) 、press_time 三个新特性。
  • 应始终保持按钮内只有一个可视组件,若有多个请放入一个容器内。



错误示范:
[RenPy] 纯文本查看 复制代码
screen test:

    PressedButton:
        align (0.5, 0.5)

        press_action Notify("计时结束")
        release_action Notify("鼠标释放")
        press_time 5
        
        text "Hello" align (0.5, 0.5)
        text "World" align (0.5, 0.6)
    

label start:

    call screen test

    return



正确示范:
[RenPy] 纯文本查看 复制代码
screen test:

    PressedButton:
        align (0.5, 0.5)

        press_action Notify("计时结束")
        release_action Notify("鼠标释放")
        press_time 5
        
        vbox:
            spacing 10

            text "Hello"
            text "World"
    

label start:

    call screen test

    return



其他功能:
因为考虑到许多开发者有需要将长按与条联动的需求,所以 PressedButton 封装了一个简单的与条联动的功能,能够高效地满足不同的交互方式与部分小游戏的需求。
使用方式很简单,只需要将条值与 PressedButton 对象的 updater 属性绑定,就可以动态地在玩家长按按钮时更新条值。

[RenPy] 纯文本查看 复制代码
screen test:

    vbox:
        align (0.5, 0.5)
        spacing 20

        PressedButton:
            xalign 0.5
            as pressed_button
            press_action Notify("计时结束")
            release_action Notify("鼠标释放")
            press_time 10

            imagebutton:
                idle "#00ccff"
                hover "#0099ff"
                xalign 0.5
                xysize (100, 100)
                action NullAction()

        bar:
            xysize (500, 20)
            value FieldValue(pressed_button, "updater", pressed_button.press_time)
    

label start:
    
    call screen test

    return

演示

演示

00AdvancedButton.rpy

2.21 KB, 阅读权限: 10, 下载次数: 6, 下载积分: 活力 100

评分

参与人数 3活力 +600 干货 +9 收起 理由
blackpineapple + 300 + 3 感谢分享!
被诅咒的章鱼 + 300 + 3 感谢分享!
烈林凤 + 3 感谢分享!

查看全部评分

本帖被以下淘专辑推荐:

发表于 2024-6-5 11:46:49 | 显示全部楼层
在帖主和Feniks老师的基础上做了长按显示弧形环转一圈的效果:

                               
登录/注册后可看大图


Feniks老师相关工具的地址:https://feniksdev.itch.io/
实际使用的是CircularBar相关的代码,这个是收费的dlc,因此可能不太方便直接分享orz
原理是利用CircularBar,参考2号范例制作,然后将CircularBar嵌套在PressedButton内使用:
[RenPy] 纯文本查看 复制代码
        PressedButton:
            as pressed_button
            textbutton "测试"
            circular_bar:
                offset(-9,-9)
                value FieldValue(pressed_button, "updater", pressed_button.press_time-0.1)
            style 'T2'
            press_action Notify("计时结束")
            release_action Notify("鼠标释放")
            press_time 3.0
            action Notify('点击效果')



另外,定义circular_bar的style时,必须要定义fore_bar 和 aft_bar,但由于旋转之前我们应该是不显示fore_bar的,目前我的解决方法是:
[RenPy] 纯文本查看 复制代码
style circular_bar:
    fore_bar Transform('gui/bar/round_bar.png', alpha=.0)
    aft_bar Transform('gui/bar/round_bar.png', matrixcolor=TintMatrix(Col[gui.color][2]))
    focus_mask True
    xysize (140, 140)


透明度0.0也算一种不显示

注意,press_time 参数必须要是float格式,不然没法自然转动
另一方面,原本的button代码也需要调整,找到event中的:
[RenPy] 纯文本查看 复制代码
self.updater = round(elapsed_time)


这个代码是将updater的数据固定为int,因此点击后无法丝滑转动,建议调整为2位小数:
[RenPy] 纯文本查看 复制代码
self.updater = round(elapsed_time,2)



就能实现丝滑转动了!



点评

感谢反馈!  发表于 2024-6-5 22:55
回复 支持 3 抱歉 0

使用道具 举报

发表于 2024-6-3 09:38:34 | 显示全部楼层
这个封装的按钮真是棒,完美继承了原生按钮的各种显示状态。

有个小建议,把 press_time 细分为两个时长,分别对应首次长按的等待时间和后续反复执行 press_action 的间隔时间。
回复 支持 抱歉

使用道具 举报

 楼主| 发表于 2024-6-3 22:23:50 | 显示全部楼层
被诅咒的章鱼 发表于 2024-6-3 09:38
这个封装的按钮真是棒,完美继承了原生按钮的各种显示状态。

有个小建议,把 press_time 细分为两个时长, ...

什么意思呢,没理解,能举个例子么
回复 支持 抱歉

使用道具 举报

发表于 2024-6-4 09:01:34 | 显示全部楼层
ZYKsslm 发表于 2024-6-3 22:23
什么意思呢,没理解,能举个例子么

没事,忽略吧……
回复 支持 抱歉

使用道具 举报

发表于 2024-6-4 10:25:56 | 显示全部楼层
ZYKsslm 发表于 2024-6-3 22:23
什么意思呢,没理解,能举个例子么

应该指的是按钮CD一类的东西吧,长按执行完之后要等多久才能进行下一次长按(猜的)
回复 支持 抱歉

使用道具 举报

发表于 2024-6-4 20:26:27 | 显示全部楼层
卧草!!!谢谢!!!!!!!!!!!!!!!!!
天哪这真是太棒了!!!!!!!谢谢谢谢!!!!!!等下去试试……!!!!!!!!!!!
回复 支持 抱歉

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-4 01:25 , Processed in 0.119429 second(s), 32 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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