一、简介

继《OpenHarmony有氧拳击设备端的开发》后,本次为大家带来酷炫的运用端开发。如下视频,开发者伴随着音乐,律动出拳后,那开发板屡次播映“挨揍”作用,这究竟是怎样一回事?让咱们一探背后原理。

这款拳击游戏开端时会播映音乐,然后以随机速度下落“击拳方块”。当小哥哥在击拳区域内挥拳时,游戏会判断方块的方位,依据不同方位确定播映一般击中或完美击中的动画作用。

OpenHarmony有氧拳击之应用端开发

二、动画

游戏中一共运用两种动画:特点动画和Lottie动画,分别完成下落和击中的作用。“击拳方块”下落作用是运用特点动画进行修正偏移量来完成。游戏一起设置守时器,守时获取挥拳状况和“击拳方块”的所处方位,用于判断当时挥拳是否得分。若得分则依据击中区间来播映不同作用的Lottie动画。

三、“下落”动画

1、特点动画介绍

从上图能够看到,游戏中“击拳方块”是自上而下匀速移动。这种简单操控通用特点进行动画改变的动画,便很合适运用特点动画来完成。特点动画是指组件的通用特点发生改变时,会依据开端状况和通用特点改变后的状况作为动画关键帧,在指守时刻内完成突变作用。换言之咱们只需要确定设置好组件在动画结束时的组件特点,然后调用animateTo(value: AnimationOptions, event: ()=> void),即可创立特点动画。

AnimationOptions目标说明

● 特点

OpenHarmony有氧拳击之应用端开发

●接口

OpenHarmony有氧拳击之应用端开发

2、动画完成

编写“击拳方块”UI组件,并将组件的相对布局偏移量offset特点,绑定到@state leftY1变量中,那么经过修正leftY1的值即可完成修正组件所在方位。

@State leftY1: string = '50%'
    @Builder LeftBoxing(offsetY: string) {
        Image($r('app.media.icon_boxing_left'))
            .width(144)
            .height(110)
            .offset({ x: "-30%", y: offsetY })
            .touchable(true)
    }
    build() {
        Stack() {
            // .....
             // 左侧
            this.LeftBoxing(this.leftY1)
            // .....
    }

OpenHarmony有氧拳击之应用端开发

3、创立动画

调用animateTo显式动画来播映动画完成单个“击拳方块”自上而下地移动,再经过设置delay参数完成4个“击拳方块”按次序分别移动。

    async leftAnimate(){
        // 设置图标下滑动画
        // 动画持续时刻
        let leftDuration = this.getRandomDuration()
        this.leftDuration = leftDuration
        // 推迟时长
        let leftDelay = leftDuration / (this.boxingCount - 1)
        // 设置开端时刻
        let now = new Date
        this.animateLeftTimestamp = now.getTime()
        // 左侧animateTo动画
        animateTo({ duration: leftDuration, curve: Curve.Linear,delay:0 * leftDelay ,iterations: 1 }, () => {
            this.leftY1 = "50%"
        })
        animateTo({ duration: leftDuration, curve: Curve.Linear,delay:1 * leftDelay, iterations: 1 }, () => {
            this.leftY2 = "50%"
        })
        animateTo({ duration: leftDuration, curve: Curve.Linear,delay:2 * leftDelay, iterations: 1 }, () => {
            this.leftY3 = "50%"
        })
        animateTo({ duration: leftDuration, curve: Curve.Linear,delay:3 * leftDelay, iterations: 1 }, () => {
            this.leftY4 = "50%"
        })
        let totalTime = leftDuration + 3 * leftDelay
        await this.sleep(totalTime)
        this.resetAnimate(true)
        this.leftAnimate()
    }

OpenHarmony有氧拳击之应用端开发

4、设置击中区域监听

设置守时器守时查询当时是否挥拳,若检测到挥拳再经过计算当时动画运转时刻来判断“击拳方块”方位,从而履行击中或完美击中的逻辑,以下为监听逻辑。

    setScoreListen(){
        this.intervalNumber = setInterval(async()=>{
            let res = await BoxingGameNAPI.recvMsg();
            if(res?.message.length > 0){
                if(res.message.includes('left') && !this.leftAnimateLock){
                    // 检测到左手挥拳
                    this.judgeLeft()
                }
            }
        },200)
    }
    judgeLeft(){
        let nowTime = new Date().getTime()
        // 首次抵达目标顶部时刻
        let firstTime = this.animateLeftTimestamp + (this.percentToPoint(this.targetOffsetY)+this.percentToPoint('50%') - this.percentToPoint('10%')) * this.leftDuration
        // 结束时刻
        let endTime = this.animateLeftTimestamp + this.leftDuration * 2
        if(nowTime > firstTime - 200 && nowTime < endTime){
            // 得分时刻边界
            let leftDelay =  this.leftDuration /(this.boxingCount -1 )
            let handleTime = (nowTime - firstTime) % leftDelay
            let judgeTime = this.leftDuration /6
            CommonLog.info(TAG,`leftDelay:${leftDelay},handleTime:${handleTime},judgeTime:${judgeTime}`)
            // 完美击中
            if (judgeTime/4 < handleTime && handleTime  < (judgeTime *(3/4))) {
            }else if(handleTime < judgeTime){
               // 一般击中
            }else{
                // 不得分
            }
        }else{
            // 未抵达区域
        }
    }

四、击中动画

OpenHarmony有氧拳击之应用端开发

像前文说到的“下落”动画合适运用特点动画,那么当咱们需要完成更杂乱,如上图的动画作用时,该怎么来完成呢?

Lottie介绍

Lottie是一款能够为运用程序增加动画的开源组件,它能够解析AE(After Effects)导出的json文件,让杂乱的动画资源轻松运转在运用程序中。如图所示,动画文件经过AE的bodymovin插件将动画转换成通用的json格局描述文件后,运用开发者只需运用Lottie解析json文件,就能将动画绘制出来。

Lottie优点:

  1. 只需运用Lottie解析json文件就能完成动画的加载,基本上完成了0代码开发;

  2. 运用开发者能够经过修正json文件的参数,将动画运转到不同的运用程序中,完成动画的一次规划多端运用;

  3. 运用开发者可从网络如lottiefiles.com/ 直接下载json文件,实时更新动画资源;

  4. Lottie根据canvas画布进行根底的2D渲染,让动画流通度更高;

  5. Lottie能够将UX规划师给出的杂乱动画作用100%复原到运用程序中 ;

  6. Lottie提供了丰富的API,让开发者能轻松操控动画,大大提高了开发功率。

怎么运用Lottie?

  1. 导入Lottie

在Terminal窗口运用npm install @ohos/lottieETS命令下载Lottie,并在页面中导入@ohos/lottieETS,如下:

importlottiefrom'@ohos/lottieETS'

放置动画资源

将After Effects导出的json动画资源文件保存到项目common/lottie途径中,详细途径如下:entry/src/main/ets/MainAbility/common/lottie/animation.json

OpenHarmony有氧拳击之应用端开发

  1. 创立Lottie动画

Lottie根据canvas画布进行根底的2D渲染,创立canvas画布后设置相关播映参数即可创立并播映Lottie动画,Lottie更多信息可参阅Lottie接口。

创立canvas画布:

    @Builder TargetArea(controller:CanvasRenderingContext2D,lottieName:string) {
        Stack() {
            Canvas(controller)
                .aspectRatio(1)
                .width(300)
                .offset({ y:  this.targetOffsetY })
                .onAppear(() => {
                })
            Animator('__lottie_ets') // declare Animator('__lottie_ets') when use lottie
        }.height('100%').width(220)
    }

设置Lottie动画参数:

setLottie(controller:CanvasRenderingContext2D,lottieName:string,animatePath:string){
        lottie.loadAnimation({
            container: controller,
            renderer: 'canvas',
            loop: false,
            autoplay: false,
            name: lottieName,
            path: animatePath,
        })
        lottie.setSpeed(1,lottieName)
    }

在“下落”动画击拳监听中参加播映不同作用的Lottie动画逻辑:

    judgeLeft(){
       ......
        if(nowTime > firstTime - 200 && nowTime < endTime){
           ......
            // 完美击中
            if (judgeTime/4 < handleTime && handleTime  < (judgeTime *(3/4))) {
                lottie.destroy('animate_left')
                this.setLottie(this.controllerLeft,'animate_left',this.animatePerfectPath)
                lottie.play('animate_left') // 播映完美击中动画
                // 等动画履行完成后才能进入下一次挥拳断定
                this.leftAnimateLock = true
                setTimeout(()=>{
                    lottie.stop()
                    lottie.destroy('animate_left')
                    this.leftAnimateLock = false
                },this.lottieDuration)
            }else if(handleTime < judgeTime){
                // 击中
                lottie.destroy('animate_left')
                this.setLottie(this.controllerLeft,'animate_left',this.animateJustPath)
                lottie.play('animate_left')// 播映击中动画
                this.leftAnimateLock = true
                setTimeout(()=>{
                    lottie.stop()
                    lottie.destroy('animate_left')
                    this.leftAnimateLock = false
                },this.lottieDuration)
            }
        }
    }

五、总结

本文首要叙述了拳击互动游戏中,怎么运用特点动画完成简单特点改变的动画作用,如游戏中“击拳方块”自上往下移动;运用Lottie组件完成杂乱艳丽的动画作用,如游戏中的击拳作用。

本样例是OpenHarmony常识系统工作组(相关链接在文章末尾)为广阔开发者共享的样例。常识系统工作组结合日常生活,给开发者规划了各种场景的Demo样例,如智能家居场景、影音文娱场景、运动健康场景等。欢迎广阔开发者一起参加OpenHarmony的开发,更加完善样例,彼此学习,彼此进步。

六、参阅链接

本样例代码下载链接

growing.openharmony.cn/mainPlay/de…

特点动画

docs.openharmony.cn/pages/v3.2B…

docs.openharmony.cn/pages/v3.2B…

Lottie

docs.openharmony.cn/pages/v3.2B…

mp.weixin.qq.com/s/2adu8dNI9…

OpenHarmony常识系统共建开发仓

gitee.com/openharmony…

OpenHarmony学习途径

growing.openharmony.cn/mainPlay/le…

小熊派BearPi-HM Nano开发板学习途径

growing.openharmony.cn/mainPlay/le…

gitee.com/bearpi/bear…

润和DAYU200(RK3568)开发板介绍

growing.openharmony.cn/mainPlay/le…

OpenHarmony有氧拳击之设备端开发

mp.weixin.qq.com/s/qVEFKid2g…