找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 7700|回复: 1

[经验] 小白也能学会的眨眼和说话(非常简单好用)

[复制链接]
发表于 2021-3-29 03:45:25 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 雪团子 于 2021-3-29 16:41 编辑

大家好,这里是研究了一下午眨眼+说话的雪团子,代码什么的是照搬英文版官方的,想分享一些自己总结的经验和容易失误的点。这里是代码来源。

https://www.renpy.org/wiki/renpy/doc/cookbook/Blink_And_Lip_Flap

也参考了这位的文章。
https://pastebin.com/mPepv6nT
首先,建立一个新的文件,ATOM的话是,点击file,new file 即可,记得保存的时候后缀要 .rpy ,这样就会自动变成rpy格式了。
然后把这段代码原封不动的放进去,保存,完成第一步。
[RenPy] 纯文本查看 复制代码
init python:

    # This is set to the name of the character that is speaking, or
    # None if no character is currently speaking.
    speaking = None

    # This returns speaking if the character is speaking, and done if the
    # character is not.
    def while_speaking(name, speak_d, done_d, st, at):
        if speaking == name:
            return speak_d, .1
        else:
            return done_d, None

    # Curried form of the above.
    curried_while_speaking = renpy.curry(while_speaking)

    # Displays speaking when the named character is speaking, and done otherwise.
    def WhileSpeaking(name, speaking_d, done_d=Null()):
        return DynamicDisplayable(curried_while_speaking(name, speaking_d, done_d))

    # This callback maintains the speaking variable.
    def speaker_callback(name, event, **kwargs):
        global speaking

        if event == "show":
            speaking = name
        elif event == "slow_done":
            speaking = None
        elif event == "end":
            speaking = None

    # Curried form of the same.
    speaker = renpy.curry(speaker_callback)

然后我们进入script.rpy,复制以下代码开始修改。
需要注意的点。
我试过官方的define,但renpy不给运行,所以我试了其他人写的phyton格式,完美的运行了。
下面需要放进script的完整代码,里面需要注意的点都有解释,请务必认真阅读。
[RenPy] 纯文本查看 复制代码
init:
    
#callback=speaker是这次重点,名字要和image的名字相同。
    $ nvzhu = Character("我",image="nvzhu", callback=speaker("nvzhu"))
# side是我写的头像,去掉side就是普通的立绘了。还有上面那段的image="nvzhu"也是用来描述头像的,如果定义的是普通的立绘,请都删除。
    image side nvzhu normal = Composite(
        (450,450),# 这个是图片的大小,分辨率px多少填多少,是宽x高。
        (0, 0), "nvzhubase.png",# 下面的这些(0,0)是定位,第一个是底图,也就是没眼睛没嘴巴的立绘,我是吧脸+眉毛放在一起的。
        (0, 0), "nvzhu eyes normal",#比如眼睛部分,你可能需要手动定位在底图也就是base上面,可以看一看链接的例子便于理解。
        #但如果在导入之前就已经定位好了,且图和底图的大小一致,也就是说不需要移动,设定为 0 和 0 就好。
        (0, 0), WhileSpeaking("nvzhu", "nvzhu mouth normal", "nvzhumouthclosed.png"),
        )
        #可以看出来以上有些是单个图片(带png后缀的)有些是一个图片组,下面我们就来定义这些图片组。
#眨眼的部分。
    image nvzhu eyes normal:
        #png 都是图片,替换成自己的图片资源就好,我分了睁眼,半睁眼以及闭眼三种。
        "nvzhueyeopen.png"#这是睁眼部分的图,以下的choice 是增加随机性的要点。
        choice:
            1#数字是秒,也就是说,会随机每多少多少眨眼,看起来比较自然,数字都可更改。
        choice:
            2
        choice:
            3
        choice:
            4
        #半睁眼
        "nvzhueyeclosing.png"
        .1#同样也是速度。
        #闭眼
        "nvzhueyeclosed.png"
        .25
        repeat
#嘴巴说话部分。
    image nvzhu mouth normal:
        #两个张嘴说话的形态,或者也可以设定成一张一闭。
        "nvzhumouthopen2.png"
        .2
        "nvzhumouthopen.png"
        .2
        repeat

# 现在这里展示的是,如果已经定义了一个图像组,比如眨眼,是不用重新定义的。
    image side nvzhu sad = Composite(
        (450,450),
        (0, 0), "nvzhubasesad.png",#这里是伤心的底图,主要是眉毛的变化
        (0, 0), "nvzhu eyes normal",#像这里,直接取用之前的图像组。
        (0, 0), WhileSpeaking("nvzhu", "nvzhu mouth sad", "nvzhumouthsadclosed.png"),
        )
#不过如果嘴巴要变成伤心的嘴巴都话,也还是要定义的。
    image nvzhu mouth sad:#复制粘贴改名字,改显示的图像。
        "nvzhumouthsadopen.png"
        .2
        "nvzhumouthsadopen1.png"
        .2
        repeat
#这里展现的是如果要添加无动态立绘,需要注意缩进。
image side nvzhu blackface = "images/nvzhublackface.png"




要准备到图片。
1.基础,base,概念就是除了眼睛嘴巴以外的脸和身体的部位,会动的部件分开。
2.眼睛的睁眼和闭眼至少两种形态的图。
3.嘴巴的张开和闭着。
接下来放一段 label,主要展示如何正确的show,展示。
[RenPy] 纯文本查看 复制代码
label start:

    scene bg room
#如果是立绘就。
    show nvzhu normal #重点是后缀 normal。
    
    nvzhu normal "您已创建一个新的 Ren'Py 游戏。"#重点是后缀 normal。
    nvzhu blackface "您已创建一个新的 Ren'Py 游戏。"#无动态图也可以很正常的展示。
    nvzhu sad "当您完善了故事、图片和音乐之后,您就可以向全世界发布了!"

以上能做到较为自然的眨眼和文字滚动时嘴巴动,不滚动时初始状态。
注意一些png的后缀,比如mouthclosed 就是嘴巴闭着的状态,替换成同样的嘴巴闭着的状态即可。感谢被诅咒的章鱼的指正和补充。
改了一下代码,变成 composite了。


评分

参与人数 2活力 +100 干货 +2 收起 理由
龙氏 + 100 + 1 楼主辛苦了!
被诅咒的章鱼 + 1 感谢分享!

查看全部评分

发表于 2021-3-29 14:37:06 | 显示全部楼层
帮楼主补充几句……

整个方案的设计思路有两个关键点:

1. 角色的回调函数(Character Callbacks)。
按照文档的说明,定义Character时的入参可以有一个callback函数,用来处理say语句的相关事件。有些类似其他编程语言中的“委托”。
这里使用的回调函数“speaker()”核心功能只有一个,在角色对象调用say时,如果收到事件“show”,则将角色名称“name”赋值给全局变量“speaking”(就是最上层代码中初始化为None的变量)。
因为角色回调函数默认只能有一个固定位置入参“event”,所以使用renpy.curry()函数做了“柯里化”。
renpy.curry()函数仅仅在文档里作为预留名称出现,实际用法……也只有Tom本人写了样例才可能知道了……

2. 动态可视组件(DynamicDisplayable)。
定义角色图像时使用LiveComposite方法将角色底图、眼睛和嘴合成并显示。
其中底图是静态的,眼睛是两帧动画穿插显示。
嘴的图像有两种状态,“WhileSpeaking”函数会检查第一个入参是否与全局变量“speaking”的值一致,显示静态的图像或者两帧动画,返回结果是一个动态可视组件。
(顺便一说,LiveComposite方法已经废弃,后续版本用LiveComposite可能会报错,7.3以后的版本应该使用Composite方法)
回复 支持 2 抱歉 0

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-4 01:29 , Processed in 0.111764 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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