大渣好,吾系Pio(就是右下角那只),Potion Maker,介系李没有Van过的船新版本,是萝莉控,就来游戏里点我(误
总算是把添加wifelive2d模型,解包提取texture,添加tips全套学会了(会用了),写一篇文章记录一下吧

前期准备

  • live2d模型和动作文件,使用插件的话一般插件都会提供,但都不太好看.
  • jQuery,可直接引入外链,也可以安装到本地,推荐引入外链,这个之后会说明.
  • 以下条目都是解包模型时使用的,如果不想使用换装功能可以直接跳过
    1. Visual Studio(不是vscode),并且安装了C++工作负载,用于编译运行AssetStudio
    2. AssetStudio,用于读取将解包后得到的assets文件
    3. FBXSDK,AssetStudio必要的依赖,由于官网下载速度过慢,可以直接下载我下载好的安装包
    4. UABE,用于解压缩

添加到网页上

开箱即用

由于dalao们已经制作好了各种引擎(包括hexo,typecho,wordpress,emlog)的插件,想要直接使用的小伙伴们可以直接去看看啦

手动添加

dalao们写的版本虽好,但是手动添加的话会更容易进行自定义.
下面以typecho为例,其它引擎类似

准备所需资源

  • 下载imjaddalao构建好的live2d.js
    将其放到你的博客的主题的目录下的你想要的位置(建议上传到你的cdn服务器上引外链使用)

  • 将模型文件放到你博客的主题的目录下的你想要的位置(同样建议上传到cdn引外链使用)
    如果没有模型,可以先使用这个,imjaddalao提供的.包含了Tia和Pio的初始三套服装.获取更多服装的方法请往下看

编写样式文件

以下代码保存为live2d.css,放到相应位置

.waifu {
    position: fixed;
    bottom: 0;
    left: 0;
    z-index: 1;
    font-size: 0;
    transition: all .3s ease-in-out;
    -webkit-transform: translateY(3px);
    transform: translateY(3px);
}
.waifu:hover {
    -webkit-transform: translateY(0);
    transform: translateY(0);
}
@media (max-width: 768px) {
    .waifu {
        display: none;
    }
}

修改header.php

在主题目录下的header.php中的合适位置引入刚才写的样式表.
如果是引外链使用直接引用你的外链即可
如果是放在本地(即主题目录下),要这样引用:

<link href="<?php $this->options->themeUrl('主题目录到live2d.css的相对路径') ?>" rel="stylesheet" type="text/css" />

然后在合适的地方创建画布(一般在body标签内)

<div class="waifu">
    <canvas id="live2d" width="280" height="250" class="live2d"></canvas>
</div>

footer.php中实例化live2d

在主题目录下的footer.php中的合适位置引用jQuery和live2d.js,并实例化live2d

<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="到live2d.js的路径" type="text/javascript"></script>
<script type="text/javascript">
    loadlive2d("live2d", "到模型的json文件的路径");
</script>

post.php中也要添加一份,否则直接从文章页面进入不会显示
如果是放在本地,引用方式需要和上面添加样式时一样

如果一切OK,刷新后萌萌哒的Pio就会出现在博客左下角啦

添加tips

以下已经是可选内容了
接下来我们让Pio会说话吧~

首先保存好需要的文件,注意js文件中有一处要更改

文本文件

以下文本保存为waifu-tips.json,放到相应位置

{
    "mouseover": [
        {
            "selector": ".container a[href^='http']",
            "text": ["要看看 <span style=\"color:#0099cc;\">{text}</span> 么?"]
        },
        {
            "selector": ".fui-home",
            "text": ["点击前往首页,想回到上一页可以使用浏览器的后退功能哦"]
        },
        {
            "selector": "#tor_show",
            "text": ["翻页比较麻烦吗,点击可以显示这篇文章的目录呢"]
        },
        {
            "selector": "#comment_go,.fui-chat",
            "text": ["想要去评论些什么吗?"]
        },
        {
            "selector": "#night_mode",
            "text": ["深夜时要爱护眼睛呀"]
        },
        {
            "selector": "#qrcode",
            "text": ["手机扫一下就能继续看,很方便呢"]
        },
        {
            "selector": ".comment_reply",
            "text": ["要吐槽些什么呢"]
        },
        {
            "selector": "#back-to-top",
            "text": ["回到开始的地方吧"]
        },
        {
            "selector": "#author",
            "text": ["该怎么称呼你呢"]
        },
        {
            "selector": "#mail",
            "text": ["留下你的邮箱,不然就是无头像人士了"]
        },
        {
            "selector": "#url",
            "text": ["你的家在哪里呢,好让我去参观参观"]
        },
        {
            "selector": "#textarea",
            "text": ["认真填写哦,垃圾评论是禁止事项"]
        },
        {
            "selector": ".OwO-logo",
            "text": ["要插入一个表情吗"]
        },
        {
            "selector": "#csubmit",
            "text": ["要提交了吗,首次评论需要审核,请耐心等待~"]
        },
        {
            "selector": ".ImageBox",
            "text": ["点击图片可以放大呢"]
        },
        {
            "selector": "input[name=s]",
            "text": ["找不到想看的内容?搜索看看吧"]
        },
        {
            "selector": ".previous",
            "text": ["去上一页看看吧"]
        },
        {
            "selector": ".next",
            "text": ["去下一页看看吧"]
        },
        {
            "selector": ".dropdown-toggle",
            "text": ["这里是菜单"]
        },
        {
            "selector": "c-player a.play-icon",
            "text": ["想要听点音乐吗"]
        },
        {
            "selector": "c-player div.time",
            "text": ["在这里可以调整<span style=\"color:#0099cc;\">播放进度</span>呢"]
        },
        {
            "selector": "c-player div.volume",
            "text": ["在这里可以调整<span style=\"color:#0099cc;\">音量</span>呢"]
        },
        {
            "selector": "c-player div.list-button",
            "text": ["<span style=\"color:#0099cc;\">播放列表</span>里都有什么呢"]
        },
        {
            "selector": "c-player div.lyric-button",
            "text": ["有<span style=\"color:#0099cc;\">歌词</span>的话就能跟着一起唱呢"]
        },
        {
            "selector": ".waifu #live2d",
            "text": ["干嘛呢你,快把手拿开", "鼠…鼠标放错地方了!"]
        }
    ],
    "click": [
        {
            "selector": ".waifu #live2d",
            "text": ["是…是不小心碰到了吧", "萝莉控是什么呀", "你看到我的小熊了吗", "再摸的话我可要报警了!⌇●﹏●⌇", "110吗,这里有个变态一直在摸我(ó﹏ò。)"]
        }
    ]
}

js文件

以下代码保存为waifu-tips.js.放到相应位置

function render(template, context) {

    var tokenReg = /(\\)?\{([^\{\}\\]+)(\\)?\}/g;

    return template.replace(tokenReg, function (word, slash1, token, slash2) {
        if (slash1 || slash2) {  
            return word.replace('\\', '');
        }

        var variables = token.replace(/\s/g, '').split('.');
        var currentObject = context;
        var i, length, variable;

        for (i = 0, length = variables.length; i < length; ++i) {
            variable = variables[i];
            currentObject = currentObject[variable];
            if (currentObject === undefined || currentObject === null) return '';
        }
        return currentObject;
    });
}
String.prototype.render = function (context) {
    return render(this, context);
};

var re = /x/;
console.log(re);
re.toString = function() {
    showMessage('哈哈,你打开了控制台,是想要看看我的秘密吗?', 5000);
    return '';
};

$(document).on('copy', function (){
    showMessage('你都复制了些什么呀,转载要记得加上出处哦', 5000);
});

$.ajax({
    cache: true,
    url: "到waifu-tips.json的位置",
    dataType: "json",
    success: function (result){
        $.each(result.mouseover, function (index, tips){
            $(document).on("mouseover", tips.selector, function (){
                var text = tips.text;
                if(Array.isArray(tips.text)) text = tips.text[Math.floor(Math.random() * tips.text.length + 1)-1];
                text = text.render({text: $(this).text()});
                showMessage(text, 3000);
            });
        });
        $.each(result.click, function (index, tips){
            $(document).on("click", tips.selector, function (){
                var text = tips.text;
                if(Array.isArray(tips.text)) text = tips.text[Math.floor(Math.random() * tips.text.length + 1)-1];
                text = text.render({text: $(this).text()});
                showMessage(text, 3000);
            });
        });
    }
});

(function (){
    var text;
    if(document.referrer !== ''){
        var referrer = document.createElement('a');
        referrer.href = document.referrer;
        text = 'Hello! 来自 <span style="color:#0099cc;">' + referrer.hostname + '</span> 的朋友';
        var domain = referrer.hostname.split('.')[1];
        if (domain == 'baidu') {
            text = 'Hello! 来自 百度搜索 的朋友<br>你是搜索 <span style="color:#0099cc;">' + referrer.search.split('&wd=')[1].split('&')[0] + '</span> 找到的我吗?';
        }else if (domain == 'so') {
            text = 'Hello! 来自 360搜索 的朋友<br>你是搜索 <span style="color:#0099cc;">' + referrer.search.split('&q=')[1].split('&')[0] + '</span> 找到的我吗?';
        }else if (domain == 'google') {
            text = 'Hello! 来自 谷歌搜索 的朋友<br>欢迎阅读<span style="color:#0099cc;">『' + document.title.split(' - ')[0] + '』</span>';
        }
    }else {
        if (window.location.href == 'https://imjad.cn/') { //如果是主页
            var now = (new Date()).getHours();
            if (now > 23 || now <= 5) {
                text = '你是夜猫子呀?这么晚还不睡觉,明天起的来嘛';
            } else if (now > 5 && now <= 7) {
                text = '早上好!一日之计在于晨,美好的一天就要开始了';
            } else if (now > 7 && now <= 11) {
                text = '上午好!工作顺利嘛,不要久坐,多起来走动走动哦!';
            } else if (now > 11 && now <= 14) {
                text = '中午了,工作了一个上午,现在是午餐时间!';
            } else if (now > 14 && now <= 17) {
                text = '午后很容易犯困呢,今天的运动目标完成了吗?';
            } else if (now > 17 && now <= 19) {
                text = '傍晚了!窗外夕阳的景色很美丽呢,最美不过夕阳红~';
            } else if (now > 19 && now <= 21) {
                text = '晚上好,今天过得怎么样?';
            } else if (now > 21 && now <= 23) {
                text = '已经这么晚了呀,早点休息吧,晚安~';
            } else {
                text = '嗨~ 快来逗我玩吧!';
            }
        }else {
            text = '欢迎阅读<span style="color:#0099cc;">『' + document.title.split(' - ')[0] + '』</span>';
        }
    }
    showMessage(text, 6000);
})();

window.setInterval(showHitokoto,30000);

function showHitokoto(){
    $.getJSON('https://api.imjad.cn/hitokoto/?cat=&charset=utf-8&length=28&encode=json',function(result){
        showMessage(result.hitokoto, 5000);
    });
}

function showMessage(text, timeout){
    if(Array.isArray(text)) text = text[Math.floor(Math.random() * text.length + 1)-1];
    console.log(text);
    $('.waifu-tips').stop();
    $('.waifu-tips').html(text).fadeTo(200, 1);
    if (timeout === null) timeout = 5000;
    hideMessage(timeout);
}
function hideMessage(timeout){
    $('.waifu-tips').stop().css('opacity',1);
    if (timeout === null) timeout = 5000;
    $('.waifu-tips').delay(timeout).fadeTo(200, 0);
}

注意上面的代码中有一处要更改为waifu-tips.json的路径的,但由于js文件中不好使用php的语法,我建议是把waifu-tips.json上传到cdn~
代码中有引用imjad的api,再次%

添加样式

在刚才写的live2d.css中添加tips对话框的样式:

.waifu-tips {
    opacity: 0;
    width: 250px;
    height: 70px;
    margin: -20px 20px;
    padding: 5px 10px;
    border: 1px solid rgba(224, 186, 140, 0.62);
    border-radius: 12px;
    background-color: rgba(236, 217, 188, 0.5);
    box-shadow: 0 3px 15px 2px rgba(191, 158, 118, 0.2);
    font-size: 12px;
    text-overflow: ellipsis;
    overflow: hidden;
    position: absolute;
    animation-delay: 5s;
    animation-duration: 50s;
    animation-iteration-count: infinite;
    animation-name: shake;
    animation-timing-function: ease-in-out;
}
.waifu #live2d{
    position: relative;
}

@keyframes shake {
    2% {
        transform: translate(0.5px, -1.5px) rotate(-0.5deg);
    }

    4% {
        transform: translate(0.5px, 1.5px) rotate(1.5deg);
    }

    6% {
        transform: translate(1.5px, 1.5px) rotate(1.5deg);
    }

    8% {
        transform: translate(2.5px, 1.5px) rotate(0.5deg);
    }

    10% {
        transform: translate(0.5px, 2.5px) rotate(0.5deg);
    }

    12% {
        transform: translate(1.5px, 1.5px) rotate(0.5deg);
    }

    14% {
        transform: translate(0.5px, 0.5px) rotate(0.5deg);
    }

    16% {
        transform: translate(-1.5px, -0.5px) rotate(1.5deg);
    }

    18% {
        transform: translate(0.5px, 0.5px) rotate(1.5deg);
    }

    20% {
        transform: translate(2.5px, 2.5px) rotate(1.5deg);
    }

    22% {
        transform: translate(0.5px, -1.5px) rotate(1.5deg);
    }

    24% {
        transform: translate(-1.5px, 1.5px) rotate(-0.5deg);
    }

    26% {
        transform: translate(1.5px, 0.5px) rotate(1.5deg);
    }

    28% {
        transform: translate(-0.5px, -0.5px) rotate(-0.5deg);
    }

    30% {
        transform: translate(1.5px, -0.5px) rotate(-0.5deg);
    }

    32% {
        transform: translate(2.5px, -1.5px) rotate(1.5deg);
    }

    34% {
        transform: translate(2.5px, 2.5px) rotate(-0.5deg);
    }

    36% {
        transform: translate(0.5px, -1.5px) rotate(0.5deg);
    }

    38% {
        transform: translate(2.5px, -0.5px) rotate(-0.5deg);
    }

    40% {
        transform: translate(-0.5px, 2.5px) rotate(0.5deg);
    }

    42% {
        transform: translate(-1.5px, 2.5px) rotate(0.5deg);
    }

    44% {
        transform: translate(-1.5px, 1.5px) rotate(0.5deg);
    }

    46% {
        transform: translate(1.5px, -0.5px) rotate(-0.5deg);
    }

    48% {
        transform: translate(2.5px, -0.5px) rotate(0.5deg);
    }

    50% {
        transform: translate(-1.5px, 1.5px) rotate(0.5deg);
    }

    52% {
        transform: translate(-0.5px, 1.5px) rotate(0.5deg);
    }

    54% {
        transform: translate(-1.5px, 1.5px) rotate(0.5deg);
    }

    56% {
        transform: translate(0.5px, 2.5px) rotate(1.5deg);
    }

    58% {
        transform: translate(2.5px, 2.5px) rotate(0.5deg);
    }

    60% {
        transform: translate(2.5px, -1.5px) rotate(1.5deg);
    }

    62% {
        transform: translate(-1.5px, 0.5px) rotate(1.5deg);
    }

    64% {
        transform: translate(-1.5px, 1.5px) rotate(1.5deg);
    }

    66% {
        transform: translate(0.5px, 2.5px) rotate(1.5deg);
    }

    68% {
        transform: translate(2.5px, -1.5px) rotate(1.5deg);
    }

    70% {
        transform: translate(2.5px, 2.5px) rotate(0.5deg);
    }

    72% {
        transform: translate(-0.5px, -1.5px) rotate(1.5deg);
    }

    74% {
        transform: translate(-1.5px, 2.5px) rotate(1.5deg);
    }

    76% {
        transform: translate(-1.5px, 2.5px) rotate(1.5deg);
    }

    78% {
        transform: translate(-1.5px, 2.5px) rotate(0.5deg);
    }

    80% {
        transform: translate(-1.5px, 0.5px) rotate(-0.5deg);
    }

    82% {
        transform: translate(-1.5px, 0.5px) rotate(-0.5deg);
    }

    84% {
        transform: translate(-0.5px, 0.5px) rotate(1.5deg);
    }

    86% {
        transform: translate(2.5px, 1.5px) rotate(0.5deg);
    }

    88% {
        transform: translate(-1.5px, 0.5px) rotate(1.5deg);
    }

    90% {
        transform: translate(-1.5px, -0.5px) rotate(-0.5deg);
    }

    92% {
        transform: translate(-1.5px, -1.5px) rotate(1.5deg);
    }

    94% {
        transform: translate(0.5px, 0.5px) rotate(-0.5deg);
    }

    96% {
        transform: translate(2.5px, -0.5px) rotate(-0.5deg);
    }

    98% {
        transform: translate(-1.5px, -1.5px) rotate(-0.5deg);
    }

    0%, 100% {
        transform: translate(0, 0) rotate(0);
    }
}

修改header.php

在刚才创建画布的容器里再添加一个waifu-tips,变成以下这样:

<div class="waifu">
    <div class="waifu-tips"></div>
    <canvas id="live2d" width="280" height="250" class="live2d"></canvas>
</div>

修改footer.php

在jQuery外链的后面引用waifu-tips.js:

<script async src="waifu-tips.js的路径"></script>

由于并不是很重要的内容,所以使用了非阻塞加载来保证访问速度
不要忘了post.php中也要添加一份

完成后刷新一下,Pio就会说话啦~
到此,live2d模型部署到网页的部分已经全部完成

获取更多模型

本节将介绍如何通过解包获取Pio的更多服装

药水制造师

Pio的衣服并不会存在本地,除非你使用过.也就是说,你只有玩药水制造师并解锁服装来获得新的服装(强行安利嘿嘿嘿
提供存档是不可能提供的,这辈子都不可能提供的.只有疯狂安利,给Pio续一秒才能维持得了生活这样子.
氪金也是OK的哟~我会考虑把我老婆Pio借你摸一下的(滑稽
国内玩家可以通过QooApp,或是TapTap下载.

解压缩模型文件

获得的服装保存在Android/data/com.sinsiroad.potionmaker/files/UnityCache/Shared目录下以40位hash命名的文件夹里.
每个文件夹里都有一个文件名叫__data的文件,这就是我们需要的
将文件传到电脑上
使用UABE(前面提到的)unpack文件:
启动UABE,依次点击File->Open,选择相应的__data文件,这时候UABE会提醒你是否要解压缩,选择确定后将文件命名保存即可.

利用AssetStudio解包

首先确认你电脑上安装了VS,并从GitHub上拷贝了AssetStudio项目.
在项目根目录有一个解决方案文件AssetStudio.sln,直接双击即可使用VS打开它.
但直接开始编译运行会报错,这是因为这个项目使用的FBX版本是2015版本的,但是我没找到2015版本的FBXSDK(也许是我星际),于是我使用了2019版本的FBXSDK,但是项目已经默认FBX的版本是2015了,并不能检测到2019版的.
所以我们需要手动更改
首先点到解决方案的AssetStudioFBX项目,然后点上方工具栏中的视图->属性页
然后在属性页中找到这两个地方,把箭头所指的一项改成你本地的相应目录

然后打开AssetStudioFBX-x86项目的属性页,按如上方法再操作一遍

然后直接开始调试运行
UPD: 我瞎了抱歉,原来有release版
接着用AssetStudio打开之前保存的asset文件,也就是通过UABE得到的文件
如果你把这些文件都放在一个目录里了,还可以直接Load Folder
文件类型为Texture2D的文件即为我们需要的模型
还有几张是活动的宣传画,注意鉴别

选中这些文件,右键->Export selected assets,保存文件
然后你就获得了Pio的新服装!
要使用这些服装,只需更改Pio的model.json文件中的textures一项即可

给Pio加上换装功能

有了新衣服后,就可以给Pio加上换装功能啦
但由于我太菜了(我是群里最弱的玩家.jpg),不太理解live2d.js的原理以及不知道php或js有关json文件的更多操作,只能使用最笨的方法进行换装了
也就是写多个Pio的配置文件,在加载时随机加载一个配置文件
我们就以这套Healer-Costume为例
首先确认这套服装已经上传到正确的目录,和之前的服装一起
新建一个名为Pio_Healer-Costume.json的配置文件,将它和之前的配置文件放到一起
textures一项的值改为Healer-Costume
比如之前是

"textures":[
        "textures/default-costume.png"
    ],

改为

"textures":[
        "textures/Healer-Costume.png"
    ],

然后写一个live2d_changeClothes.php,在里面写上随机取一套服装的逻辑

<?php  
    $clothes    = array("default-costume",
                        "Healer-Costume"
);
    $randomNum  = rand(0,count($clothes) - 1);
    $modelUrl   = "\"http://documents.elatis.cn/live2d_models/Pio/Pio_".$clothes[$randomNum].".json\"";
    echo $modelUrl;
?>

之前的配置文件也记得要改名
要是之后获得了新服装,只需要在数组中加上即可
最后在footer.phppost.php中修改一下之前添加的代码,引用这个php文件即可

<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script async src="到waifu-tips.js的路径"></script>
<script src="到live2d.js的路径" type="text/javascript"></script>
<script type="text/javascript">
    loadlive2d("live2d", <?php require_once "到live2d_changeClothes.php的路径" ?>);
</script>

刷新网站即可让Pio随机换装!
这样(low版)随机换装也实现了.
到此,关于在博客上添加一个看板娘的相关教程也结束了

感谢阅读!

参考资料

https://imjad.cn/archives/lab/add-dynamic-poster-girl-with-live2d-to-your-blog-02

标签: none

添加新评论