官方入门教程无法用cc.tween实现左右移动的问题

版本2.3.3。刚入门研究CCC,跟着官方教程做了一遍那个入门小游戏(小怪物摘星星)。原教程里是用Action控制怪物跳跃,然后在update()里控制左右平移。

新版CCC在运行时提示Action即将被废弃,推荐使用tween来做缓动动画,于是用tween重写了缓动部分 (TypeScript代码):

cc.tween(this.node)
        .repeatForever(
            cc.tween()
                .by(this.jumpDuration, { position: cc.v2(0, this.jumpHeight) }, { easing: 'cubicOut' })
                .by(this.jumpDuration, { position: cc.v2(0, -this.jumpHeight) }, { easing: 'cubicIn' })
                .call(() => this.playJumpSound())
        )
        .start();

但是在运行时发现update()函数里更新node.x的代码不能正常工作:

update(dt: number) {
    // ...
    // 上面是计算 this.xSpeed 的代码
    this.node.x += this.xSpeed * dt;
}

打印this.node.x发现 x 的值没有正常累加,感觉是 tween 的位移计算重置了 this.node.x 的值?打印出来的值大概是这样( x1 = 本帧修改前的this.node.x,v = xSpeed * dt,x2 = x1 + v ):

...
x1: 0,  v: 6.667600000000676,  x2: 6.667600000000676
x1: 0,  v: 6.653600000000005,  x2: 6.653600000000005
x1: 0,  v: 6.687199999999575,  x2: 6.687199999999575
...

请问有大佬知道为什么会这样吗?用tween的时候如何正确更新node的位置?

tween只修改Y值试试看
你修改的是position,肯定会把x也修改的

把那个接口替换成这个:

runJumpAction () { 
        // 跳跃上升
        var jumpUp = cc.tween()
            .by(this.jumpDuration, {y: this.jumpHeight}, {easing: "cubicOut"})
        // 下落
        var jumpDown = cc.tween()
            .by(this.jumpDuration, {y: -this.jumpHeight}, {easing: "cubicInt"})
        
        // 形变
        var squash = cc.tween()
            .to(this.squashDuration, {scaleX: 1, scaleY: 0.6}, {easing: "smooth"})
        
        var stretch = cc.tween()
            .to(this.squashDuration, {scaleX: 1, scaleY: 1.2}, {easing: "smooth"})

        var scaleBack = cc.tween()
            .to(this.squashDuration, {scaleX: 1, scaleY: 1}, {easing: "smooth"})

        cc.tween(this.node)
            // 不断重复,而且每次完成落地动作后调用回调来播放声音
            .repeatForever(
                cc.tween()
                    .sequence(squash, stretch, jumpUp, scaleBack, jumpDown)
                    // 添加一个回调函数,用于在动作结束时调用我们定义的其他方法
                    .call(this.playJumpSound, this)
            )
            .start()
    }

相应的修改一下代码里面的调用方式。

1赞

谢谢大佬,我看api文档还以为第二个参数只接受position、scale等几个固定的属性值:joy:

谢谢您给出的详尽代码示例!

不客气:slightly_smiling:

我起先也是以为只有文档示例那几个固定属性,后来自己写上scaleX\scaleY做拉伸动画,就没多想一步,官方文档里说的是——可以对任意对象的任意属性进行缓动
groupIndex: 0 group: "default" x: 0 y: 142.06288952702533 rotation: -0 angle: 0 rotationX: 0 rotationY: 0 scale: 1 scaleX: 1.0161903824420007 scaleY: 1.1930796659030305 skewX: 0 skewY: 0 opacity: 255 color: Color anchorX: 0.5 anchorY: 0 width: 78 height: 67 zIndex: 0
诸如此类!

十分感谢,我也遇到了这个问题.
后面被迫使用动作系统来解决,但是没有单个动作执行完的回调,还是tween方便.:grin: