在Spine中翻转骨骼动画播放 AS3 与 Cocos2dx

之前一直在用 cocos2dx 的 cocosStudio 自带的骨骼动画
但是为了由于Spine支持网格动画,于是手头的项目都转到支持Spine的骨骼的说。

最近想做一个动画倒播的功能,在之前的 cocosStudio 中,可以通过 API, gotoAndStop(frame) 来实现倒播
到了 Spine 里,貌似就没有这个功能啦

嘛~研究了一下,貌似改起来难度不高。。 自己的本本没装各种编程软件。。。(游戏本嘛) 只有Flash Profession CC, 于是就拿 AS3版本来改改先啦。

话说Spine也是蛮搞的,C++ 版本要合并 Spine C 和 Spine cocos2dx. 而 Flash版本要合并 Spine flash 和 Spine Starling. 而且还没有完整API,丰富的范例(就2个。。还没体现所有功能)

就拿AS3的版本举例好了,最后说下C++中对应的关系就行了

在Spine 中,每个动作都是一个 TrackEntry, 里面存了时间轴的一些基础数据
因此我加入了几个翻转的属性
like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TrackEntry {
    public var next:TrackEntry;
    internal var previous:TrackEntry;
    public var animation:Animation;
    public var loop:Boolean;
    public var delay:Number, time:Number = 0, lastTime:Number = -1, endTime:Number, timeScale:Number = 1;

//新增翻转开始
    public var reverseDeltaTime : Number = 0, reverseTime : Number = 0, reverseLastTime : Number = 0;
    public var reverse : Boolean;
//新增翻转结束

    internal var mixTime:Number, mixDuration:Number, mix:Number = 1;
    public var onStart:Function, onEnd:Function, onComplete:Function, onEvent:Function;
   
    public function toString () : String {
        return animation == null ? "<none>" : animation.name;
    }
}

有了这些属性后,就可以在 AnimationState 中修改 Update 和 apply 2个函数就行了

修改后的 Update 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public function update (delta:Number) : void {
        delta *= timeScale;
        for (var i:int = 0; i < _tracks.length; i++) {
            var current:TrackEntry = _tracks[i];
            if (!current) continue;
           
            if(current.reverse){
                if(0 >= current.reverseDeltaTime){
                    current.reverseDeltaTime = current.time <= 0 ? current.endTime : current.time;
                    current.lastTime = current.endTime;
                }
               
                current.reverseDeltaTime -= delta * current.timeScale ;
                current.reverseTime += delta * current.timeScale;
                current.time = current.reverseDeltaTime;
            }else{
                current.time += delta * current.timeScale ;
            }

            if (current.previous) {
                var previousDelta:Number = delta * current.previous.timeScale;
                current.previous.time += previousDelta;
                current.mixTime += previousDelta;
            }

            var next:TrackEntry = current.next;
            if (next) {
                next.time = current.lastTime - next.delay;
                if (next.time >= 0) setCurrent(i, next);
            } else {
                // End non-looping animation when it reaches its end time and there is no next entry.
                if(current.reverse){
                    if (!current.loop && current.reverseLastTime >= current.endTime) clearTrack(i);
                }else{
                    if (!current.loop && current.lastTime >= current.endTime) clearTrack(i);
                }
            }
        }
    }

修改后的apply如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    public function apply (skeleton:Skeleton) : void {
        for (var i:int = 0; i < _tracks.length; i++) {
            var current:TrackEntry = _tracks[i];
            if (!current) continue;
           
            _events.length = 0;
           
            var time:Number = current.time;
            var lastTime:Number = current.lastTime;
            var endTime:Number = current.endTime;
            var loop:Boolean = current.loop;
            if (!loop && time > endTime) time = endTime;
           
            var previous:TrackEntry = current.previous;
            if (!previous) {
                if (current.mix == 1)
                    current.animation.apply(skeleton, current.lastTime, time, loop, _events);
                else
                    current.animation.mix(skeleton, current.lastTime, time, loop, _events, current.mix);
            } else {
                var previousTime:Number = previous.time;
                if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
                previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null);
               
                var alpha:Number = current.mixTime / current.mixDuration * current.mix;
                if (alpha >= 1) {
                    alpha = 1;
                    current.previous = null;
                }
                current.animation.mix(skeleton, current.lastTime, time, loop, _events, alpha);
            }
           
            for each (var event:Event in _events) {
                if (current.onEvent != null) current.onEvent(i, event);
                onEvent.invoke(i, event);
            }

            // Check if completed the animation or a loop iteration.
            if(reverse){
                lastTime = current.reverseLastTime;
                time = current.reverseTime;
            }
            if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) {
                var count:int = (int)(time / endTime);
                if (current.onComplete != null) current.onComplete(i, count);
                onComplete.invoke(i, count);
            }
           
            current.lastTime = time;
            current.reverseLastTime = time;
        }
    }

C++的对应关系是
TrackEntry 在C++中 结构体在 AnimationState.h 中
AnimationState.as 在 C++中 为 AnimationState.c

=。= 最近越来越没耐心写博客了,看来真的老了。。。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.