一、简介
继《OpenHarmony有氧拳击设备端的开发》后,本次为大家带来酷炫的运用端开发。如下视频,开发者伴随着音乐,律动出拳后,那开发板屡次播映“挨揍”作用,这究竟是怎样一回事?让咱们一探背后原理。
这款拳击游戏开端时会播映音乐,然后以随机速度下落“击拳方块”。当小哥哥在击拳区域内挥拳时,游戏会判断方块的方位,依据不同方位确定播映一般击中或完美击中的动画作用。
二、动画
游戏中一共运用两种动画:特点动画和Lottie动画,分别完成下落和击中的作用。“击拳方块”下落作用是运用特点动画进行修正偏移量来完成。游戏一起设置守时器,守时获取挥拳状况和“击拳方块”的所处方位,用于判断当时挥拳是否得分。若得分则依据击中区间来播映不同作用的Lottie动画。
三、“下落”动画
1、特点动画介绍
从上图能够看到,游戏中“击拳方块”是自上而下匀速移动。这种简单操控通用特点进行动画改变的动画,便很合适运用特点动画来完成。特点动画是指组件的通用特点发生改变时,会依据开端状况和通用特点改变后的状况作为动画关键帧,在指守时刻内完成突变作用。换言之咱们只需要确定设置好组件在动画结束时的组件特点,然后调用animateTo(value: AnimationOptions, event: ()=> void),即可创立特点动画。
AnimationOptions目标说明
● 特点
●接口
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)
// .....
}
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()
}
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{
// 未抵达区域
}
}
四、击中动画
像前文说到的“下落”动画合适运用特点动画,那么当咱们需要完成更杂乱,如上图的动画作用时,该怎么来完成呢?
Lottie介绍
Lottie是一款能够为运用程序增加动画的开源组件,它能够解析AE(After Effects)导出的json文件,让杂乱的动画资源轻松运转在运用程序中。如图所示,动画文件经过AE的bodymovin插件将动画转换成通用的json格局描述文件后,运用开发者只需运用Lottie解析json文件,就能将动画绘制出来。
Lottie优点:
-
只需运用Lottie解析json文件就能完成动画的加载,基本上完成了0代码开发;
-
运用开发者能够经过修正json文件的参数,将动画运转到不同的运用程序中,完成动画的一次规划多端运用;
-
运用开发者可从网络如lottiefiles.com/ 直接下载json文件,实时更新动画资源;
-
Lottie根据canvas画布进行根底的2D渲染,让动画流通度更高;
-
Lottie能够将UX规划师给出的杂乱动画作用100%复原到运用程序中 ;
-
Lottie提供了丰富的API,让开发者能轻松操控动画,大大提高了开发功率。
怎么运用Lottie?
- 导入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
- 创立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…