type
status
date
slug
summary
tags
category
icon
password
效果预览
可以先思考一下,如何使用代码实现上面的效果呢?
实现思路
开始之前,还是要从一个故事讲起,在一个遥远的未来世界,有一个独特的机器人,它的名字叫做小白,小白不像传统的机器人那样呆板,而是由流畅的曲线和精巧的结构构成。它的头部,特别引人注目。开始的时候,它的头部只是一个简单的贝塞尔曲线构成的轮廓,仿佛是一幅未完成的艺术品。
然而,随着时间的推移,小白的头部逐渐丰富起来。它学会了表情和情感,曲线逐渐变得更加细腻,仿佛一个真正的人类头部。小白的眼睛是最吸引人的地方,它们不仅能够传达情感,还能够扫描和分析周围的环境…
哈哈,言归正传,要实现上面的效果,其实是以下的技术实现思路:
- 四段三次贝塞尔曲线
在 使用四段三次 Bézier 曲线拟合圆 这篇博客里面,介绍了通过四段三次贝塞尔曲线去绘制一个圆,不止是圆,定义四段三次贝塞尔曲线能形成很多的形状。
- 形状组合和表情设计
定义一个表示形状的数据结构,其中包含四段贝塞尔曲线的描述,将多个形状组合成一个表情。通过组合不同的形状来设计表情,每个形状代表表情的一部分,例如眼睛、嘴巴、脸部等,然后在画布上绘制这些部分。
- 动作设计
定义一个机器人的数据结构,头部加入表情,机器人的其它部分和表情共同组成一个动作。
- 动作串联
将多个动作串联实现动画效果。可以通过在时间上连续绘制不同的动作,设计一个动画系统,根据时间轴逐步绘制不同的动作,从而实现机器人的动画效果。
在 Android 开发中,可以利用 Canvas 绘图功能、动画框架等来实现这种复杂的图形效果。从一段贝塞尔曲线开始,到最终的动画效果,这将是一个奇妙的旅程。
四段三次贝塞尔曲线组成基础形状
首先,通过四段三次贝塞尔曲线组成一系列形状做为基础,如下图所示:
因为需要形状的大小可以自由变化,定义了以下函数来获取一段三次贝塞尔曲线
定义一个数据结构描述四段贝塞尔曲线
定义一个
CurveShapeView
来负责绘制形状下图演示从一个形状切换到另一个形状,并基于进度控制切换状态。
因为要做状态保存,定义一个 VisualInfo 类,其中 DrawInfo 用来控制绘制(作用于 View#onDraw()),ViewPropertyInfo 用于控制 View 本身属性(供 Android 属性动画调度)
形状组合
有了形状,就可动手把他们组合成表情了
这里我定义了一个 EmoteInfo 类,其中包含面部、左右眼、嘴巴等形状
同样定义一个
FaceView
用来绘制表情下图演示从一个表情切换到另一个表情,并基于进度控制切换表情,由于基于属性,可以在任何时间切换时获取当前属性,从而是切换时画面自然过渡。
其实到这一步,就可以通过变换表情来执行动画了,但总感觉少了点什么,所以下面底部加了个小影子
动作设计
定义一个 PoseInfo 类,代表一个动作,主要包含表情、底部的影子、头部的属性控制等
同样定义一个 RobotView 负责展示和执行动作
动作串联
在 RobotView 定义了动画执行控制器,其实就是一个属性动画
考虑到机器人外部执行动画的同时,做表情变化(比如演示中上下摆动的同时做表情变换),在 FaceView 里面同样定义了动画执行控制器。
至此,按照开始时的思路已一一实现。
做这个小机器人有什么用呢
除了拿来写博客,它还有别的用处吗?
- 可以设计一系列表情,做矢量图形使用。
- 人脸验证的时候,提示张嘴、闭眼,可以用表情动画做对应的提示。
- 多设计几组动作,结合 ChatGpt Api 做一个聊天机器人应该也挺有意思的吧。
相关资料
后记:本来以为做这个东西只需要一两天,谁知道最终实现花费了一个完整周日和周一到周三的下班时间,看起来简单,真正做的过程中还是充满了各种挑战,坚持到写完博客真的是心力憔悴。
这份代码虽然还有很多不足的地方(对象频繁创建,整个代码结构可以使用设计模式做规整,捏和图形像是徒手磨螺丝,机器人整体动画实现方式不合理),再休息一段时间之后再来优化吧。或许做减法,只到表情那块刚刚好。
另外,通过这个作品感受到了 kotlin 的简洁性,如果用 java,今天应该还完不成。