在微信小游戏中实现语音互动

之前在unity里尝试用过语音控制,当时的想法是实时控制游戏角色的移动与攻击,这在通过在线api解析语义的方式下体验一般,不过也想到在实时性要求不那么高的互动场景应该可以用起来。这里就在微信小游戏中尝试一下。

语音交互自然需要一个对象,像我这种手残人士最适合的设计当然就是卡通的小动物了。经过多次修改,在iPad上完成了形象设计(有点丑,有点歪,大家不要见怪):

在微信小游戏中实现语音互动_第1张图片

设计好形象之后就可以设计动画了。一帧一帧的画出连贯的动作。因为偷懒,所以一个动画也就几帧,准备了下面几个动画:

  1. 眨眼。1帧,空闲状态的时候播放,避免什么都不做的时候画面看起来太死板。
  2. 挠头。2帧,录音结束发给服务器等待服务器结果的时候播放,使得能在话音刚落时就给出反应。
  3. 微笑。1帧,对它说“笑一个”的时候播放。
  4. 举牌子。3帧,狗狗不会说话,要通过写字的方式和玩家交流。

接下来就可以参考飞机示例,完成游戏的代码部分。

首先新建一个class InterAction,在constructor中进行各种初始化,主要是加载一些图片资源,注册事件等:

constructor(c, returnTitle) {
    ctx = c
    this.returnTitle = returnTitle

    this.bg = wx.createImage()
    this.bg.src = 'images/bg2.png'

    this.recordBtn = wx.createImage()
    this.recordBtn.src = 'images/record.png'
    this.recordBtnDown = wx.createImage()
    this.recordBtnDown.src = 'images/recorddown.png'
    this.btn = this.recordBtn

    this.dog = new Dog()

    this.idleFrameCount = 0

    this.result = ''

    this.recorderManager = wx.getRecorderManager()

    this.recorderManager.onStop(this.onRecordEnd.bind(this))

    this.restart()
  }

  restart() {
    this._touchStartHandler = this.touchStartHandler.bind(this)
    wx.onTouchStart(this._touchStartHandler)

    this._touchEndHandler = this.touchEndHandler.bind(this)
    wx.onTouchEnd(this._touchEndHandler)

    requestAnimationFrame(this.loop.bind(this))
  }

之后,可以看到主线程结构和飞机的基本一样:

loop() {
    this.update()

    this.render()

    requestAnimationFrame(this.loop.bind(this))
  }

在update和按钮、录音的回调函数中更新状态,在render中显示当前帧的内容。

录音结束后,调用happycxz提供的接口进行语音解析:

onRecordEnd(res) {
   // 向服务器发送录音文件
   let url = 'https://api.happycxz.com/wxapp/mp32asr'
   this.dog.playAnimation('thinking', 0, true)
   this.idleFrameCount = 0
   this.processFileUploadForAsr(url, res.tempFilePath)
 }

 processFileUploadForAsr(url, filePath) {
    wx.uploadFile({
      url: url,
      filePath: filePath,
      name: 'file',
      formData: { 'appKey': appkey, 'appSecret': appsecret, 'userId': UTIL.getUserUnique()},
      header: {'content-type': 'multipart/form-data'},
      success: function(res) {
        let nliResult = this.getNliFromResult(res.data)
        let stt = this.getSttFromResult(res.data)

        let result = ''
        if (nliResult != undefined && nliResult.length != 0) {
          result = nliResult[0].desc_obj.result
        } else {
          result = '出了点问题'
        }
        this.handleResult(result)
      }.bind(this),
      fail: function (res) {
        wx.showModal({
          title: '提示',
          content: "网络请求失败,请确保网络是否正常",
          showCancel: false,
          success: function (res) {
          }
        })
      }.bind(this)
    })
  }

处理返回结果:

handleResult(res) {
    if (res.length > 6) {
      res = res.substr(0, 6)
    }
    this.result = res
    if (this.result == '微笑') {
      this.dog.playAnimation('smile', 0, true, 60)
      this.idleFrameCount = 0
    } else if (this.result == 'exit') {
      wx.offTouchStart(this._touchStartHandler)
      wx.offTouchEnd(this._touchEndHandler)
      this.returnTitle()
    } else {
      this.dog.playAnimation('answer', 
                              0, 
                              false, 
                              240, 
                              function () {
                                ctx.fillStyle = "#ffffff"
                                ctx.font = "15px Arial"

                                ctx.fillText(
                                  this.result,
                                  constants.screenWidth * 17 / 32,
                                  constants.screenHeight * 15 / 32
                                )}.bind(this), 
                              2)
      this.idleFrameCount = 0
    }
  }

Dog是继承自我扩展之后的Animation类,主要的改动有两个,一个是支持多个动画,另一个是在playAnimation时增加了多个参数,可以控制动画循环的方式,并可以指定在特定的帧显示时调用的回调函数。具体的代码可以看文末的代码包,这里就不多说了。

最后来看看测试效果。

在微信小游戏中实现语音互动_第2张图片

按下录音键,说话,松开后会做挠头动作(有点难看),等待一段时间会举起牌子显示结果。目前只在olami平台配置了闲聊、24点和算术功能。为了适应牌子大小,结果做了截断处理。下面是几个测试例子:

笑一个/笑一笑:会做出笑脸
再见/拜拜:会返回标题界面
其他:会通过牌子上显示文字信息

另外,代码中还包含了一个跳跃的小游戏,通过在主界面点击开始可以进入。如果进一步开发,可以把小游戏的分数做为奖励,在互动界面购置一些装饰品之类的,应该会增加不少游戏的趣味性。

附:

此项目源码地址:https://gitee.com/stdioh_cn/jumpingdog

你可能感兴趣的:(技术问题)