spine 动画层 动态权重
前奏.业务背景
这边想实现一个功能,项目中有 一只猫 猫的头会盯着逗猫棒移动。因为素材还没到所以这里使用了 spine 自带的猫头鹰。他的动画 刚好挺有针对性:(关联上篇)
https://blog.csdn.net/nicepainkiller/article/details/144113214
一共有六组动画:
idel 空闲动画全身都会动 多帧动画,
blink 眨眼睛动画 头不动 多帧动画
其余几个动画只有有头会动 单帧动画 只有一帧
- blink 眼睛在中间的动画 会眨眼睛
- down 眼睛朝下看 单帧
- left 眼睛朝左看 单帧
- right 眼睛朝右看 单帧
- up 眼睛朝上看 单帧
- idel 空闲动画 全身动
猫头鹰眼睛可以盯着 屏幕物体移动,实现效果如下 :
最初想的实现方式是:类似 Unity3D 有一个二位动画权重的东西。但是找遍 cocos creator API 发现没找到,
那么只能纯手撸了:
思路就是动态控制 动画层的权重,来显示不同动画(头上,头右,头下,头左)的播放权重。
实操1.逗猫棒位置计算
首先就确定一个屏幕可以拖动的元素,并且计算出一个区域,用来确定 向量 Vec2:
- 屏幕触点 转 屏幕坐标
- 根据屏幕坐标计算出 用来表示范围的 一个 向量
核心代码:
//获取 触点坐标位置 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;}//展示只有 在拖拽情况下才显示的 元素 equipmentFlytouchStart(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;}}
工程下载
相关文章:
spine 动画层 动态权重
前奏.业务背景 这边想实现一个功能,项目中有 一只猫 猫的头会盯着逗猫棒移动。因为素材还没到所以这里使用了 spine 自带的猫头鹰。他的动画 刚好挺有针对性:(关联上篇)https://blog.csdn.net/nicepainkiller/article/details/144…...
《Python基础》之Python中可以转换成json数据类型的数据
目录 一、JSON简介 JSON有两种基本结构 1、对象(Object) 2、数组(Array) 二、将数据装换成json数据类型方法 三、在Python中,以下数据类型可以直接转换为JSON数据类型 1、字典(Dictionary)…...
在oracle下载jdk显示400 Bad Request Request Header Or Cookie Too Large
下载JDK17,官网地址:【https://www.oracle.com/cn/java/technologies/downloads/#jdk17-windows】 问题: 出现 400 Bad Request: Request Header Or Cookie Too Large 错误,通常是由于浏览器存储的 Cookies 或请求头过大所导致的…...
MongoDB注入攻击测试与防御技术深度解析
MongoDB注入攻击测试与防御技术深度解析 随着NoSQL数据库的兴起,MongoDB作为其中的佼佼者,因其灵活的数据模型和强大的查询能力,受到了众多开发者的青睐。然而,与任何技术一样,MongoDB也面临着安全威胁,其…...
【Java基础入门篇】前言
Java基础入门篇 本系列内容主要针对Java基础知识,总共包含四大部分内容: 变量、数据类型和运算符控制语句和递归算法面向对象和JVM底层分析数组和排序 学习需要具备: IDEA编译器 JDK1.8版本 写在前面 在Java入门的最开始,我们需…...
Oracle 建表的存储过程
建表的存储过程 下面是建表的存储过程,用途:通过不同的表,根据不同过滤条件,得到某个字段,例如neid,然后创建一个新表T,表T的表名为拼接XXXX_XXX_neid,表T的字段自行添加 xxx&…...
【Debug】hexo-github令牌认证 Support for password authentication was removed
title: 【Debug】hexo-github令牌认证 date: 2024-07-19 14:40:54 categories: bug解决日记 description: “Support for password authentication was removed on August 13, 2021.” cover: https://pic.imgdb.cn/item/669b38ebd9c307b7e9f3e5e0.jpg 第一章 第一篇博客记录一…...
torch.is_floating_point(input)
torch.is_floating_point(input) input: 输入张量 如果输入的数据类型是 浮点数据类型 ,则返回 True。否则返回False。 浮点数据类型:torch.float64、torch.float32、torch.float16 、 torch.bfloat16 import torch# 创建一个浮点数张量 float_tensor torch.te…...
【分布式】分布式事务
目录 1、事务的发展 2、本地事务 (1)如何保障原子性和持久性? (2)如何保障隔离性? 2、全局事务 (1)XA事务的两段式提交 (2)XA事务的三段式提交…...
Spring Data 简介
Spring Data 是一个用于简化数据库访问的框架,它是 Spring 生态系统中的重要组成部分。以下是详细介绍: 一、背景和目的 在开发应用程序时,数据访问层的实现往往是比较复杂和繁琐的。开发人员需要编写大量的代码来实现诸如数据库连接、查询…...
【娱乐项目】基于批处理脚本与JavaScript渲染视频列表的Web页面
Demo介绍 一个简单的视频播放器应用,其中包含了视频列表和一个视频播放区域。用户可以通过点击视频列表中的项来选择并播放相应的视频,播放器会自动播放每个视频并在播放完毕后切换到下一个视频。本项目旨在通过自动化脚本和动态网页渲染,帮助…...
[MySQL]流程控制语句
流程控制语句需要借助存储过程才有效。关于存储过程,我会在后续的文章详述,本篇文章只是阐述流程控制语句。因此,大家只需要注意存储过程中相应的流程控制语句即可。 如果文中阐述不全或不对的,多多交流。 参考笔记三,…...
Flink在Linux系统上的安装与入门
一、Flink的引入 这几年大数据的飞速发展,出现了很多热门的开源社区,其中著名的有Hadoop、Storm,以及后来的Spark,他们都有着各自专注的应用场景。Spark 掀开了内存计算的先河,也以内存为赌注,赢得了内存计…...
微信小程序Webview与H5通信
背景 近期有个微信小程序需要用到web-view嵌套H5的场景,该应用场景需要小程序中频繁传递数据到H5进行渲染,且需要保证页面不刷新。 由于微信小程序与H5之间的通信限制比较大,显然无法满足于我的业务场景 探索 由于微信小程序与webview的环境是…...
Debezium Engine监听binlog实现缓存更新与业务解耦
飞书文档 解决缓存与数据源数据不一致的方案有很多, 各有优缺点; 1.0、旁路缓存策略, 直接同步更新 读取流程: 查询缓存。如果缓存命中,则直接返回结果。如果缓存未命中,则查询数据库。将数据库查询到的数据写入缓存,并设置一个…...
docker搭建socks5代理
准备工作 VPS安全组/策略放行相应端口如启用了防火墙,放行相应端口 实际操作 我们选用“历史悠久”的Dante socks5 代理服务器,轻量、稳定。Github也有对dante进行进一步精简的镜像,更为适宜。github项目地址如下: https://gi…...
scanf函数和printf函数的格式化输入输出
#include<stdio.h> int main() {int a;double b;char c;scanf("a%d,b%lf:c%c",&a,&b,&c); //float型输入时使用%f占位,double型使用%lf占位;输出时二者相同都是%f即可。if(a>0)printf("a%-10d,b%20.3lf,c%c",a…...
Day31 贪心算法 part05
56. 合并区间 本题也是重叠区间问题,如果昨天三道都吸收的话,本题就容易理解了。 代码随想录 class Solution {public int[][] merge(int[][] intervals) {Arrays.sort(intervals, (a,b) -> Integer.compare(a[0], b[0]));List<int[]> result …...
uniapp连接mqtt频繁断开原因和解决方法
mqtt参考文档:MQTT.js 入门教程 | EMQ、MQTT.js 入门教程 - EMQX - 博客园 uniapp引用MQTT频繁断开的问题可能由于以下几个原因导致: 网络不稳定:频繁断开可能是由于网络不稳定导致的,可以尝试优化网络连接。 心跳机制问题&…...
【数据结构-队列】力扣641. 设计循环双端队列
设计实现双端队列。 实现 MyCircularDeque 类: MyCircularDeque(int k) :构造函数,双端队列最大为 k 。 boolean insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true ,否则返回 false 。 boolean insertLast() ࿱…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
【多线程初阶】单例模式 指令重排序问题
文章目录 1.单例模式1)饿汉模式2)懒汉模式①.单线程版本②.多线程版本 2.分析单例模式里的线程安全问题1)饿汉模式2)懒汉模式懒汉模式是如何出现线程安全问题的 3.解决问题进一步优化加锁导致的执行效率优化预防内存可见性问题 4.解决指令重排序问题 1.单例模式 单例模式确保某…...


