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() ࿱…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...


