spine 动画层 动态权重

 前奏.业务背景

这边想实现一个功能,项目中有 一只猫 猫的头会盯着逗猫棒移动。因为素材还没到所以这里使用了 spine 自带的猫头鹰。他的动画 刚好挺有针对性:(关联上篇)https://blog.****.net/nicepainkiller/article/details/144113214

一共有六组动画:

        idel  空闲动画全身都会动 多帧动画

        blink 眨眼睛动画 头不动 多帧动画

        其余几个动画只有有头会动 单帧动画 只有一帧

  •     blink  眼睛在中间的动画 会眨眼睛
  •     down 眼睛朝下看 单帧
  •     left     眼睛朝左看 单帧
  •     right   眼睛朝右看 单帧
  •     up      眼睛朝上看 单帧
  •     idel    空闲动画 全身动

 猫头鹰眼睛可以盯着 屏幕物体移动,实现效果如下 :

最初想的实现方式是:类似 Unity3D 有一个二位动画权重的东西。但是找遍 cocos creator  API 发现没找到,

那么只能纯手撸了:

        思路就是动态控制 动画层的权重来显示不同动画头上,头右,头下,头左)的播放权重。

实操1.逗猫棒位置计算

首先就确定一个屏幕可以拖动的元素,并且计算出一个区域,用来确定 向量 Vec2:

  1. 屏幕触点 转 屏幕坐标
  2. 根据屏幕坐标计算出 用来表示范围的  一个 向量
核心代码:
//获取 触点坐标位置
touchMove(event: EventTouch) {
    //更新 拖拽元素位置
    console.log('touchMove');
    this.potion.x = event.getLocationX();
    this.potion.y = event.getLocationY();
    //触点坐标转 屏幕坐标
    this.worldPostion = this.camera.screenToWorld(this.potion);
    //屏幕坐标转 局部坐标
    this.node.position = this.nodeParent.getComponent(UITransform).convertToNodeSpaceAR(this.worldPostion);
    //console.log("this.node.position:", this.node.position);
    //计算向量
    this.localPostion.x = clamp(this.node.position.x, -this.range, this.range) / this.range;
    this.localPostion.y = clamp(this.node.position.y, -this.range, this.range) / this.range;
    //console.log("this.localPostion:", this.localPostion);
    this.spinMerge1.updateAnimation(this.localPostion);
}
功能完整代码:
import { _decorator, Component, Node, EventTouch, Camera, Vec3, UITransform, Vec2, clamp, director, view } from 'cc';
import { SpinMerge1 } from './SpinMerge1';
const { ccclass, property } = _decorator;

@ccclass('TouchMove')
export class TouchMove extends Component {

    @property({ type: Node })
    private nodeParent: Node;

    @property({ type: Camera })
    private camera: Camera;

    //控制 Spine 动画的脚步
    @property({ type: SpinMerge1 })
    private spinMerge1: SpinMerge1;

    private potion: Vec3 = new Vec3();
    private worldPostion: Vec3 = new Vec3();
    private localPostion: Vec2 = new Vec2();
    private range: number;

    onLoad() {
        this.node.on(Node.EventType.TOUCH_START, this.touchStart, this);
        this.node.on(Node.EventType.TOUCH_MOVE, this.touchMove, this);
        this.node.on(Node.EventType.TOUCH_END, this.touchEnd, this)
        this.node.on(Node.EventType.TOUCH_CANCEL, this.touchCancel, this)
    }

    start() {
        this.range = view.getVisibleSize().width / 2;
    }

    //展示只有 在拖拽情况下才显示的 元素 equipmentFly
    touchStart(event: EventTouch) {
        //Log.trace('touchStart');
        console.log('touchStart');
    }

    //获取 触点坐标位置
    touchMove(event: EventTouch) {
        //更新 拖拽元素位置
        console.log('touchMove');
        this.potion.x = event.getLocationX();
        this.potion.y = event.getLocationY();
        //触点坐标转 屏幕坐标
        this.worldPostion = this.camera.screenToWorld(this.potion);
        //屏幕坐标转 局部坐标
        this.node.position = this.nodeParent.getComponent(UITransform).convertToNodeSpaceAR(this.worldPostion);
        //console.log("this.node.position:", this.node.position);
        //计算向量
        this.localPostion.x = clamp(this.node.position.x, -this.range, this.range) / this.range;
        this.localPostion.y = clamp(this.node.position.y, -this.range, this.range) / this.range;
        //console.log("this.localPostion:", this.localPostion);
        this.spinMerge1.updateAnimation(this.localPostion);
    }

    //结束拖拽 隐藏拖拽元素
    touchCancel(event: EventTouch) {
        console.log('touchCancel');
        this.node.position = new Vec3();
        this.spinMerge1.resetAnimation();

    }
    //结束拖拽
    touchEnd(event: EventTouch) {
        console.log('touchEnd');
        this.node.position = new Vec3();
        this.spinMerge1.resetAnimation();
    }

}


实操2.猫头鹰盯着逗猫棒

猫头随着物体移动的核心就是

      通过动画层混合 分别控制 头上,头右,头下,头左 动画权重,做到动态控制展示的权重。

 

核心代码:
public updateAnimation(vec2: Vec2) {
    //console.log('updateAnimation:', vec2);
    this.ver2Normal.x = Math.abs(vec2.x);
    this.ver2Normal.y = Math.abs(vec2.y);
    //右上
    if (vec2.x > 0 && vec2.y > 0) {
        this.trackleft.alpha = 0.0;
        this.trackdown.alpha = 0.0;

        this.trackright.alpha = this.ver2Normal.x;
        this.trackUp.alpha = clamp(this.ver2Normal.y, 0, 1 - this.ver2Normal.x);
        //右下
    } else if (vec2.x > 0 && vec2.y < 0) {
        this.trackUp.alpha = 0;
        this.trackleft.alpha = 0;

        this.trackright.alpha = this.ver2Normal.x;
        this.trackdown.alpha = clamp(this.ver2Normal.y, 0, 1 - this.ver2Normal.x);

        //左下
    } else if (vec2.x < 0 && vec2.y < 0) {
        this.trackUp.alpha = 0;
        this.trackright.alpha = 0;

        this.trackleft.alpha = this.ver2Normal.x;
        this.trackdown.alpha = clamp(this.ver2Normal.y, 0, 1 - this.ver2Normal.x);


        //左上
    } else if (vec2.x < 0 && vec2.y > 0) {
        this.trackright.alpha = 0;
        this.trackdown.alpha = 0;

        this.trackleft.alpha = this.ver2Normal.x;
        this.trackUp.alpha = clamp(this.ver2Normal.y, 0, 1 - this.ver2Normal.x);
    } else {
        this.trackUp.alpha = 0;
        this.trackright.alpha = 0;
        this.trackdown.alpha = 0;
        this.trackleft.alpha = 0;
    }

}
完整代码:
import { _decorator, Component, Node, sp, Button, Vec2, clamp } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('SpinMerge1')
export class SpinMerge1 extends Component {

    @property({ type: sp.Skeleton })
    private spinAnimation: sp.Skeleton;
    private trackUp: sp.spine.TrackEntry;
    private trackright: sp.spine.TrackEntry;
    private trackdown: sp.spine.TrackEntry;
    private trackleft: sp.spine.TrackEntry;

    private ver2Normal: Vec2 = new Vec2();

    start() {
        this.spinAnimation.setAnimation(0, 'idle', true);

        //猫头鹰的动画名 left right 反了
        //所以我们这里的顺序是: 上 -> 右 -> 下 -> 左 
        this.trackUp = this.spinAnimation.setAnimation(1, 'up', true);
        this.trackright = this.spinAnimation.setAnimation(4, 'left', true);
        this.trackdown = this.spinAnimation.setAnimation(3, 'down', true);
        this.trackleft = this.spinAnimation.setAnimation(2, 'right', true);
        //眨眼睛动画
        this.spinAnimation.addAnimation(5, 'blink', true, 2);

        this.trackUp.alpha = 0;
        this.trackright.alpha = 0;
        this.trackdown.alpha = 0;
        this.trackleft.alpha = 0;
    }

    onBtnTop() {
        this.trackUp.alpha = 1;
        this.trackright.alpha = 0;
        this.trackdown.alpha = 0;
        this.trackleft.alpha = 0;
    }
    onBtnRight() {
        this.trackUp.alpha = 0;
        this.trackright.alpha = 1;
        this.trackdown.alpha = 0;
        this.trackleft.alpha = 0;
    }
    onBtnBottom() {
        this.trackUp.alpha = 0;
        this.trackright.alpha = 0;
        this.trackdown.alpha = 1;
        this.trackleft.alpha = 0;
    }
    onBtnleft() {
        this.trackUp.alpha = 0;
        this.trackright.alpha = 0;
        this.trackdown.alpha = 0;
        this.trackleft.alpha = 1;
    }

    onBtnRightTop() {
        this.trackleft.alpha = 0.0;
        this.trackdown.alpha = 0.0;

        this.trackright.alpha = 0.5;
        this.trackUp.alpha = 0.5;
    }

    onBtnRightBottom() {
        this.trackUp.alpha = 0;
        this.trackleft.alpha = 0;

        this.trackright.alpha = 0.5;
        this.trackdown.alpha = 0.5;
    }

    onBtnleftBottom() {
        this.trackUp.alpha = 0;
        this.trackright.alpha = 0;

        this.trackleft.alpha = 0.5;
        this.trackdown.alpha = 0.5;
    }

    onBtnleftTop() {
        this.trackdown.alpha = 0;
        this.trackright.alpha = 0;

        this.trackleft.alpha = 0.5;
        this.trackUp.alpha = 0.5;
    }


    public updateAnimation(vec2: Vec2) {
        //console.log('updateAnimation:', vec2);
        this.ver2Normal.x = Math.abs(vec2.x);
        this.ver2Normal.y = Math.abs(vec2.y);
        //右上
        if (vec2.x > 0 && vec2.y > 0) {
            this.trackleft.alpha = 0.0;
            this.trackdown.alpha = 0.0;

            this.trackright.alpha = this.ver2Normal.x;
            this.trackUp.alpha = clamp(this.ver2Normal.y, 0, 1 - this.ver2Normal.x);
            //右下
        } else if (vec2.x > 0 && vec2.y < 0) {
            this.trackUp.alpha = 0;
            this.trackleft.alpha = 0;

            this.trackright.alpha = this.ver2Normal.x;
            this.trackdown.alpha = clamp(this.ver2Normal.y, 0, 1 - this.ver2Normal.x);

            //左下
        } else if (vec2.x < 0 && vec2.y < 0) {
            this.trackUp.alpha = 0;
            this.trackright.alpha = 0;

            this.trackleft.alpha = this.ver2Normal.x;
            this.trackdown.alpha = clamp(this.ver2Normal.y, 0, 1 - this.ver2Normal.x);


            //左上
        } else if (vec2.x < 0 && vec2.y > 0) {
            this.trackright.alpha = 0;
            this.trackdown.alpha = 0;

            this.trackleft.alpha = this.ver2Normal.x;
            this.trackUp.alpha = clamp(this.ver2Normal.y, 0, 1 - this.ver2Normal.x);
        } else {
            this.trackUp.alpha = 0;
            this.trackright.alpha = 0;
            this.trackdown.alpha = 0;
            this.trackleft.alpha = 0;
        }

    }

    public resetAnimation() {
        this.trackUp.alpha = 0;
        this.trackright.alpha = 0;
        this.trackdown.alpha = 0;
        this.trackleft.alpha = 0;

    }

}


工程下载

上一篇:基于Linux操作系统的DNS服务器实验


下一篇:网络原理(一)—— http