🧨大过年的,给熊孩子整一本妙趣横生的游戏书吧

3,482 阅读5分钟

PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛

前言

开始前先看看效果吧 项目宣传视频

买年货、包饺子、剪窗花、贴春联、穿新衣、放烟花、看春晚、逛庙会...

极具仪式感的过年习俗里

藏着人们最温暖的春节记忆

如今的年味似乎越来越淡了

我们想设计一本有关传统中国年的互动绘本

让小朋友足不出户也能感受传统中国年的魅力

找回年味十足的春节记忆。

立项

项目立项后,在书店里翻了一堆跟春节有关的绘本和资料,从中提炼了一些最具代表性的传统春节元素。在这过程也发现了不少好书,其中最受影响是是一本由知名童书出版社“乐乐趣”出版的立体书 - 《欢乐中国年》

image.png 这本书大量的精巧的互动元素设计,给了我们许多启发,我们是不是也能在手机上做一本可以玩的书?并且充分利用智能设备的优势,实现一些实体书由于制作工艺限制无法实现的互动体验?

执行

整个项目的流程大致可以分为:

故事脚本 -> 场景/人物设定 -> 分镜 -> 美术 -> 音乐/音效制作 -> 旁白/人物配音 -> 场景动画/人物骨骼动画/特效 -> 程序功能开发

由于篇幅有限,本文主要挑选技术方面具有代表性的几个场景实现方案提供解决思路

项目使用Cocos Creator2.4.0开发

功能开发

场景一:大扫除

1642755602662902.gif 在大扫除场景中,除了常规的点触操作,希望能挖掘更多趣味的交互方式,小朋友可以通过涂抹的方式把窗户擦干净,实现原理:

image.png

  1. 在窗户上叠加一层污渍图层
  2. 在污渍节点的父节点添加Mask组件(污渍图层将受父节点遮罩影响显示内容),并勾选inverted(反向选项,显示遮罩图形以外的内容) image.png
  3. 重写Mask的graphic绘制自定义遮罩图形
start () {
    this._graphics = this.mask._graphics  // 获取mask组件的画布对象
    this.node.on('touchmove', (e) => {
        let point = e.getLocation()
        this.clearMask(point) // 根据手指触摸点绘制遮罩图形
    })
}
clearMask (point: cc.Vec2) {
    // 重新绘制Mask图形,作为污渍遮罩
    this._graphics.moveTo(prevPos.x, prevPos.y)
    this._graphics.lineTo(pos.x, pos.y)
    this._graphics.lineWidth = 40
    this._graphics.stroke()
}

在这一幕中还设计了一个彩蛋,我把福字藏在屏风后面,点击屏风就需要一个折叠屏风的效果:

1642755602662902 2.gif

实际上这个折叠屏风的伪3D效果只需要做个简单的缩放动画:

image.png

cc.tween(this._byobu)
    .to(1, { scaleX:: 0.65 }, { easing: 'elasticOut' })
    .start()

场景二:帖年红

nianhong (online-video-cutter.com) (2).gif

实现方案:

  1. 春联、窗花:拖拽吸附
  2. 窗户:遮罩
  3. 开门:shader uv动画(比较复杂,不展开)
  4. 横批:Graphics(Canvas的基础绘图方式,lineTo stroke)

场景三:备年菜

444.gif

实现方案

  1. 蒸包子:拖拽+碰撞检测,蒸熟后的烟雾:粒子特效(粒子特效在粒子软件中调好效果参数生成plist直接给cocos使用即可)

  2. 磨豆腐:旋转手势,液体效果由一张图片Y轴缩放实现,水桶用三层图片叠加 image.png

  3. 添柴火:做一个火焰粒子,每添加一个柴火,增加粒子发射数量,模拟火越烧越旺的效果

image.png

let fire = this.node.getComponent(cc.ParticleSystem)
fire.startSize += 10  // 增加粒子发射初始大小
fire.endSize += 5   // 增加粒子结束大小
fire.life += 0.2  //增加粒子生命时间

场景四:年夜饭

上菜.gif

实现原理:拖拽 + 碰撞避让

场景五:放烟花

放烟花.gif

主要介绍一下引线动画的实现原理

  1. 在PS中根据引线图形绘制路径数据,得到SVG路径数据
  2. 给引线父节点添加Mask组件,用于裁剪引线
  3. 自定义遮罩图形,并设置为反向遮罩
  4. 用Tween或GSAP从引线末端沿着SVG路径数据绘制圆形进行遮罩涂抹,达到引线慢慢燃尽的效果: image.png
ignate () {
    const sparkProxy = {
        x: this._sparkNode.x,
        y: this._sparkNode.y,
        rotation: -this._sparkNode.angle
    }

    const svgPath = "M567.5,553.5c-1.13-0.22-2.92-0.42-5..." // 引线SVG
    GSAP.to(sparkProxy, {
        motionPath: {
            path: svgPath,
            autoRotate: true
        },
        duration: 5,
        ease: "none",
        onUpdate: () => {
            // 让火苗随着引线燃尽的末端运动
            this._sparkNode.x = sparkProxy.x - 508  
            this._sparkNode.y = sparkProxy.y - 392
            this._sparkNode.angle = sparkProxy.rotation
            // 自定义绘制引线遮罩图形,绘制的区域使引线不可见
            this.clearMask(cc.v2(sparkProxy.x, sparkProxy.y)))
        }
    })
}
clearMask(pos: cc.Vec2) {
    const graphics = this.mask._graphics
    graphics.circle(pos.x, pos.y, 5)
    graphics.fillColor = cc.color(0, 0, 0, 255)
    graphics.fill()
}

场景六:穿新衣

穿新衣.gif

实现方案:拖拽吸附(同场景四)

场景七:舞龙舞狮

乌龙.gif 在这一幕场景中,小朋友可以自由控制舞龙队表演,每一个传统乐器演奏出来的音效都需要跟人物骨骼动画节奏对应上,可以在骨骼动画软件DragonBones中的时间轴里,在对应的动作帧emit事件,在Cocos捕获对应事件进行卡点音效播放

我的影片11.gif

let dragonDisplay = this.xxx.getComponent(dragonbones.ArmatureDisplay)
dragonDisplay.on('dragonBones.EventObject.SOUND_EVENT', () => {
    // 监听骨骼动画的帧事件,当动画播放到对应卡点位置时,播放音效
    cc.audioEngine.playEffect(this.audioYoho)
})

最后

以上就是这次的技术分享,刚好春节活动想到之前做过的这个项目挺契合主题,这是去年创业做的项目了,许多实现细节记得不太清楚了,感兴趣的小伙伴可以微信交流

在线体验地址

欢乐中国年H5版 - 白熊互动绘本

我们的应用也上架了APP STORE/和安卓各大应用商店哦~

搜索:白熊互动绘本 下载原生应用获得最佳体验

image.png

家里有小朋友的可以玩一下,边玩游戏边学知识,找到绘本中的8个福字彩蛋,100%获得现金红包(打个小广告)

好了,卷铺盖,回家过年