
引言
哈喽大家好,我是亿元程序员,一位有着8年游戏行业经验的主程。
不知道大家还记不记得笔者之前出过的拼图系列:
- 图片拼图
- 图片拼图Mask版
- 图片拼图Shader版
- 3D拼模型
- 3D方块拼图
居然有这么多,以至于小伙伴都看不下去了:
本来笔者已经暗暗发誓不再插手拼图游戏,但是前阵子又有小伙伴一起探讨拼视频游戏如何实现:

既然如此,我只好出手完成拼图游戏的最后一块碎片了!
言归正传,本期带大家一起来实战看看,在Cocos游戏开发中,如何提取视频纹理,完成拼图游戏,并且支持原生!
本文实战完整源码可在文末获取,小伙伴们自行前往,有体验链接。
显示视频有哪些方法?
既然我们要实现视频拼图游戏,那么我们第一步就是要在游戏中能够把视频显示出来。
相信小伙伴们都比较苦恼,那在Cocos游戏中显示视频的方法有哪些?
我列举一下我知道的:
1.VideoPlayer组件
VideoPlayer是一种视频播放组件,可通过该组件播放本地和远程视频。
这是官方提供的一个跨平台的视频播放组件,老粉应该还记得,笔者一战成名的就是利用VideoPlayer组件模仿《完蛋,我被美女包围了!》。
但是这个组件年久失修,多多少少有些问题,例如无法获取视频数据,原生层级问题等等。
2.视频转图片
正如笔者和小伙伴探讨的,有一个笨方法就是可以先把视频逐帧转成图片,然后在游戏里面再逐帧切换,形成视频效果。
这样能行吗? 笔者想了一天没头绪,我亲自去试了下这个方案,实测还真可以:
首先笔者去安装了FFmpeg,然后通过命令行将视频拆分成图片:
将视频拆分得到:
然后把图片都加载好,在update中逐帧替换:
确实可以实现效果:
这样有个好处就是支持跨平台,无论是网页、原生、小游戏都可以,只需要一套代码就能够顺利完成。
但是也有一些缺点,首先包体会增大,将视频拆分之后,大小受品质、fps和宽度影响,图片总大小会比原视频大很多:

其次就是图片一般来说会比较多,本地加载/网络加载次数会增多:
最终让我放弃这种方案的是,它在原生安卓环境会莫名其妙地加速,百思不得其姐,最终放弃。
3.通过原生方法
通过原生方法的意思就是,利用原生提供的接口或者组件,间接地帮助我们在Cocos游戏中实现。
首先是web环境,我们直接可以利用document接口拿到视频,然后通过视频拿到视频贴图:
一套流程行云流水,效果也很好,非常流畅:
但是事情并没有那么简单,原生安卓环境没有这玩意,直接就失效了。
万般无奈之下,笔者继续去寻找安卓原生的方案,庆幸找到了官方技术支持的仓库有示例工程:
不过,最后更新时间已经是3 years ago了,版本是3.7.3:

直接用,在3.8.7肯定是不行的,不过没关系,咱们动手能力强,魔改一个3.8.7的版本:

其实最主要也是在原生利用了ffmpeg提供的库,将视频解码,拿到视频帧,后续完成拼图游戏,下面详细讲讲:
-
启动时注册 JSB:首先在引擎启动时,调用
register_all_video_experiment,把原生类注册到TS环境。

-
真正挂到gfx.Video:这里obj可以理解为一个全局对象,确保先有一个
gfx对象,然后调用js_register_video_Video。

-
注册Video类和方法:就是把方法实现好暴露出去,方便
Ts调用。
-
TS创建时实际new的是C++对象:代码里的对象直接
new就可以,现实可不行。

在了解原生的流程之后,我们看下在Ts这边如何使用。
-
先声明原生类长什么样:首先是类型声明,原生暴露的
gfx.Video有这些方法,和原生定义的一致。

-
获取原生注册的对象:判断原生类是否存在。
-
创建原生Video对象:

-
监听原生事件和调用原生方法:

其实上面的所有操作的目的就是为了将视频帧上传到Texture2D,我们只要拿到了,后续全部都是原来拼图游戏的流程了:
下面就是安卓原生的最终效果,视频播放速度也正常了:

其他细节
1.核心流程
本文核心是如何通过原生解码视频,提取纹理,显示到Sprite上,拼图游戏玩法可以直接沿用,小伙伴们可以看下源码,或者翻看旧的文章。
2.实战过程
实战全程均由笔者和AI搭子真实完成,通过官方提供的例子进行魔改,如有不对还请指出。
3.组件整合
完整组件已经包含在源码里面,小伙伴们只需要将native文件夹拷贝到项目根目录:

以及VideoTexturePlayer脚本拷贝到项目调用对应方法即可完成对视频贴图的提取:
最终效果
拼图完成之后,我们就可以看到美术妹子啦!下课!

结语
本文实战完整源码已集成到亿元Cocos小游戏实战合集2.0,内含体验链接,已经拥有的小伙伴可以直接更新。
那么问题来了,还有什么东西可以拼的吗?















