找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 8104|回复: 0

[转载] Ren'Py引擎从入门到放弃(16)——GUI定制化之快捷菜单

[复制链接]
发表于 2021-2-7 20:00:21 | 显示全部楼层 |阅读模式

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

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

×
Ren'Py引擎从入门到放弃(16)——GUI定制化之快捷菜单

世上无难事,只要肯放弃。

这是入门介绍的第十六篇,主要内容是GUI定制化,这次内容是非常简单的快捷菜单(quick_menu)。

再次感谢cexo同学提供的方案和素材。


第一个问题:快捷菜单有什么特点?

答:一般来说GAL或者VN都会设计一个快捷菜单,作为一些常用操作的入口。例如cexo的原案中,包含了6个功能入口(按钮),分别是:Skip(跳过)、Autoplay(自动播放)、Save(存档)、Load(读档)、Log(查看对话记录)和System(配置选项)。比项目默认生成的快捷菜单功能少一些,挺好的~

快捷菜单的特点是“快捷”(等于没说),所以通常会始终显示在画面上,界面的zorder值需要大一些,确保引擎最后绘制,避免被其他界面覆盖的情况。当然,也可以设定一块区域,仅在鼠标移动到这块区域时显示快捷菜单,本篇会实现这个效果。


第二个问题:怎么搞?

:这个界面只有一堆按钮,按钮的行为(action)都是Ren'Py内置的,只需要改改按钮的样子和布局就行了。

还是先来看看项目默认的 quick_menu 界面是怎么写的:
[RenPy] 纯文本查看 复制代码
# PC端快捷菜单界面,移动端界面在另一个variant "touch"中
screen quick_menu():

    ## 确保该菜单出现在其他界面之上,
    zorder 100

    if quick_menu:

        hbox:
            style_prefix "quick"

            xalign 0.5
            yalign 1.0

            textbutton _("回退") action Rollback()
            textbutton _("历史") action ShowMenu('history')
            textbutton _("快进") action Skip() alternate Skip(fast=True, confirm=True)
            textbutton _("自动") action Preference("auto-forward", "toggle")
            textbutton _("保存") action ShowMenu('save')
            textbutton _("快存") action QuickSave()
            textbutton _("快读") action QuickLoad()
            textbutton _("设置") action ShowMenu('preferences')


## 此语句确保只要玩家没有明确隐藏界面,就会在游戏中显示“quick_menu”界面。
init python:
    config.overlay_screens.append("quick_menu")

default quick_menu = True

先解释下最后一句,quick_menu是个布尔值,不是screen名称。默认值设置为True的话,在screen quickmenu()定义的if语句里才会执行绘制各个按钮的代码。在某些不希望显示快捷菜单的场景时,可以设置该布尔值为False实现。例如,希望开场剧情不允许跳过、也不允许存档,就可以在script.rpy中写一行:
[RenPy] 纯文本查看 复制代码
$ quick_menu = False

过了这段剧情,允许存档时再将这个值改为True:
[RenPy] 纯文本查看 复制代码
$ quick_menu = True

(同时注意,需要禁用或删除键盘Esc键和鼠标右键调出游戏内菜单的功能,防止玩家绕道存档。)

quick_menu界面的其他部分都简单明了,我们只需要根据UI素材把按钮替换,并略微调整布局即可。

按钮的图片在这里会多次复用,所以在之前创建的button_config.rpy文件中创建一个配置项:
[RenPy] 纯文本查看 复制代码
define gui.button_defaut_image = "gui/button/button_default.png"

图片还是复用之前的黑白图:

黑白图

黑白图


先把 Skip 和 Auto 按钮加上:
[RenPy] 纯文本查看 复制代码
screen quick_menu():

    ## 确保该菜单出现在其他界面之上,除了confirm界面
    zorder 100

    if quick_menu:

        hbox:

            # 改为显示在画面上方
            xalign 0.5
            yalign 0.0

            # skip
            button:
                background im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_bg_fill_color, gui.button_bg_stroke_color) * im.matrix.opacity(gui.button_bg_alpha), xalign=0.5, yalign = 0.5)
                add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_skip_hover_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5) at button_fadeinout
                foreground Text("SKIP", xalign=0.5, yalign = 0.5, size = 15)
                action Skip() alternate Skip(fast=True, confirm=True)
            # autoplay
            button:
                background im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_bg_fill_color, gui.button_bg_stroke_color) * im.matrix.opacity(gui.button_bg_alpha), xalign=0.5, yalign = 0.5)
                add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_auto_hover_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5) at button_fadeinout
                foreground Text("AUTO", xalign=0.5, yalign = 0.5, size = 15)
                action Preference("auto-forward", "toggle")

auto.gif

此时,我们会遇到需求层面的两个小问题。

第一个需求问题是,skip和auto按钮在被选中状态后需要显示不同于idle和hover状态的第三种颜色。办法是用 if-else 语句添加不同图像:
[RenPy] 纯文本查看 复制代码
            # skip
            button:
                background im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_bg_fill_color, gui.button_bg_stroke_color) * im.matrix.opacity(gui.button_bg_alpha), xalign=0.5, yalign = 0.5)
                if (renpy.is_skipping() == True):
                    add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_skip_selected_idle_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5)
                else:
                    add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_skip_hover_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5) at button_fadeinout
                foreground Text("SKIP", xalign=0.5, yalign = 0.5, size = 15)
                action Skip() alternate Skip(fast=True, confirm=True)
            # autoplay
            button:
                background im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_bg_fill_color, gui.button_bg_stroke_color) * im.matrix.opacity(gui.button_bg_alpha), xalign=0.5, yalign = 0.5)
                if (preferences.afm_enable == True):
                    add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_auto_selected_idle_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5)
                else:
                    add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_auto_hover_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5) at button_fadeinout
                foreground Text("AUTO", xalign=0.5, yalign = 0.5, size = 15)
                action Preference("auto-forward", "toggle")

两个if语句中的判断条件是Ren'Py内置的函数和变量,分别表示“skip状态中”和“自动前进状态”,详见官方说明文档。

第二个需求问题是,skip按钮遇到没有看到过的(unseen)内容时,默认是不可用状态(insensitive)。默认的文本按钮会在这种状态下显示为灰色,并且不接收和处理hover、idle等事件。因为在没有可skip的内容状态下,hover不会显示高亮颜色,也可以认为此按钮是不可用状态,不处理也没问题。较真的同学如果一定要在按钮insensitive状态下显示不同的色彩,可以把按钮改为imagebutton类型,每个按钮都设为frame子组件(解决background透明度问题),给imagebutton设置单独的insensitive图片。这里我就偷懒不弄了……

修改后效果如图:
修改后效果.gif

继续把其他4个按钮也加上去:
[RenPy] 纯文本查看 复制代码
            button:
                background im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_bg_fill_color, gui.button_bg_stroke_color) * im.matrix.opacity(gui.button_bg_alpha), xalign=0.5, yalign = 0.5)
                add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_save_hover_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5) at button_fadeinout
                foreground Text("SAVE", xalign=0.5, yalign = 0.5, size = 15)
                action ShowMenu("save")
            button:
                background im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_bg_fill_color, gui.button_bg_stroke_color) * im.matrix.opacity(gui.button_bg_alpha), xalign=0.5, yalign = 0.5)
                add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_load_hover_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5) at button_fadeinout
                foreground Text("LOAD", xalign=0.5, yalign = 0.5, size = 15)
                action ShowMenu("load")
            button:
                background im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_bg_fill_color, gui.button_bg_stroke_color) * im.matrix.opacity(gui.button_bg_alpha), xalign=0.5, yalign = 0.5)
                add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_log_hover_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5) at button_fadeinout
                foreground Text("LOG", xalign=0.5, yalign = 0.5, size = 15)
                action ShowMenu("history")
            button:
                background im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_bg_fill_color, gui.button_bg_stroke_color) * im.matrix.opacity(gui.button_bg_alpha), xalign=0.5, yalign = 0.5)
                add im.MatrixColor(gui.button_default_image, im.matrix.colorize(gui.button_system_hover_color, gui.button_default_stroke_color), xalign=0.5, yalign = 0.5) at button_fadeinout
                foreground Text("SYSTEM", xalign=0.5, yalign = 0.5, size = 15)
                action ShowMenu("preferences")

齐活……
项目默认的界面.gif

除了skip和auto,其他按钮会使用ShowMenu动作调用其他界面,那些界面的定制化是后面几篇的内容。目前点击它们会出现项目默认的界面。


第三个问题:说好的“鼠标移动到某块区域时显示快捷菜单”呢?

答:突然想起来cexo提供的素材里还有一张快捷菜单的背景图。不过原案设计菜单按钮是在屏幕下面的,我需要先把图处理一下,命名为 quick_menu_bg.png……以及写一个显示和隐藏的transform:
[RenPy] 纯文本查看 复制代码
transform quick_button_base_fade:
    alpha 0.0
    on show:
        linear 0.5 alpha 1.0
    on hide:
        linear 0.5 alpha 0.0

hbox也写一个transform,效果是显示时从画面上方移入,消失时从画面上方移出:
[RenPy] 纯文本查看 复制代码
transform quick_menu_buttons_transform:
    #背景图高度36,所以比36稍微多几个像素值
    yoffset -40
    on show:
        linear 0.5 yoffset 0
    on hide:
        linear 0.5 yoffset -40

整个quick_menu界面的开头和结尾修改为:
[RenPy] 纯文本查看 复制代码
screen quick_menu():

    zorder 100

    if quick_menu:
    
        add "gui/quick_menu_bg.png" at quick_button_base_fade


        hbox:
            xalign 0.5
            yalign 0.0

            # 按钮定义略
            # 按钮定义略

            at quick_menu_buttons_transform

界面的动画已经基本完成,接着需要指定一块mousearea来检测鼠标位置并放在一个新的screen中:
[RenPy] 纯文本查看 复制代码
screen quick_menu_show_area():
    # 在quick_menu上层,保证比quick_menu更早获取鼠标位置
    zorder 101
    
    mousearea:
        area (0, 0, 1.0, 100)
        hovered Show("quick_menu")
        unhovered Hide("quick_menu")

最后一步,把原来固定显示quick_menu的那句python改成固定显示quick_menu_show_area:
[RenPy] 纯文本查看 复制代码
init python:
    config.overlay_screens.append("quick_menu_show_area")

完成效果:
快捷菜单效果
Ren_Py引擎从入门到放弃_16_——GUI定制化之快捷菜单-完成效果.gif

总结一下,主要工作是在换图片……

整体来说还是挺简单的……吧?

预告部分:下一篇可能是存档/读档,也可能是历史记录界面。等我看看哪个容易先做哪个……
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-4-26 09:37 , Processed in 0.061166 second(s), 14 queries , File On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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