本帖最后由 被诅咒的章鱼 于 2023-12-20 14:27 编辑
这不算是个bug,而是Ren'Py的feature(嘴硬)!
我加了几行打印日志并调试过,任何鼠标点击都是可以进入到 add "fire" 那行的。但在鼠标坐标不变的情况下,Ren'Py此时认为 "fire" 已经在界面上了,并且所有transform的特性都完全一样,唯一性检查 Displayable._unique() 之后认为不需要再重新绘制一次,就什么也不做了。所以用楼主思路是没有办法解决的……
----------------------------------------------------------------------------------------------------------------
扯了些有的没的,解决方案是去掉 add "fire" ,直接捕获鼠标点击事件并显示一个可视组件。
[RenPy] 纯文本查看 复制代码 init python:
def display_clickFX():
x, y = renpy.get_mouse_pos()
renpy.show("fire", at_list=[mouse_pos_trans(x, y)], layer='aboveall')
transform mouse_pos_trans(x, y):
#这两个偏移量建议也改成参数
xpos x-48
ypos y-53
screen mouse_effect:
key "mousedown_1" action Function(display_clickFX)
注意,renpy.show 中指定显示图层为“aboveall”,是为了保证该动画尽可能显示在其他图层上面,而不是被遮挡。(不使用“overlay”的原因是,mouse_effect 界面已经显示在overlay固定显示,renpy.show无法在同层的action中显示其他内容,很傻逼。)另外,需要在options.rpy中增加该图层:
[RenPy] 纯文本查看 复制代码 define config.layers = ['master', 'background', 'middle', 'forward', 'transient', 'screens', 'overlay', 'aboveall']
此外,之前的 config.overlay_screens 不能在菜单界面中生效,需要更强力的:
[RenPy] 纯文本查看 复制代码 define config.always_shown_screens = ['mouse_effect']
----------------------------------------------------------------------------------------------------------------
最后再扩展一下,简单说明一下满足楼主需求的通用设计方案:
楼主的核心需求是鼠标点击之后在画面上“显示”一个图像(序列帧)。图像(序列帧)是预先定义好的,唯一的变量只有鼠标坐标。我们可以在捕获鼠标点击事件时很容易地得到鼠标坐标。
接着就要设置一个始终显示的“图层”来“显示”之前定义的图像(序列帧)。该“图层”需要始终在其他所有图层上面,并且不影响其他图层的鼠标点击事件。这个“图层”具体的实现有多种方式,可以是layer、screen、component等等,不同的引擎有不同的方案。
此时有个关键问题在“显示”的定义和实现方法上。我们可以在图层上预先添加一个图像(序列帧),然后根据鼠标点击事件修改该图像(序列帧)的位置,也就是楼主的方案。可行,但不够好。另一种通用方案是,在捕获鼠标点击事件后,在对应坐标实时增加一个图像(序列帧)。也就是说,鼠标点了很多次之后,图层上会同时存在很多个图像(序列帧)。此时鼠标多次点击后可以在画面上看到多个动画,并且每一个都能完整播放。这会带来另一个问题,随着图像越来越多,占用内存越来越多,应用越来越卡……应对这个新问题时,我们可以在图像(序列帧)显示完毕后销毁(调用析构函数)。这种方法在大多数时候都够用,但在鼠标点击这种频发事件中新建对象和销毁对象都是会占用不少资源,可能会带来卡顿。更好的通用方案为“资源池”。“资源池”可以是任意容器,容器内的元素类型为图像(序列帧)对应的类。每次需要显示图像(序列帧)时都从“资源池”申请,如果资源池内有“空闲”的元素则从资源池弹出和“激活”该元素并移动到鼠标位置开始播放,如果资源池内没有“空闲”元素则重新生成一个对应类型元素并移动到鼠标位置开始播放。每个元素——图像(序列帧)需要在播放完毕后通过回调函数将自身重新加入到资源池。
由于我对Ren'Py不熟,所以不清楚怎样具体实现以上方案。楼主有空可以实现一下……
|