朋友有个需求关于金币滚动效果,网上也有很多教程;但多不太符合他的需求,所有利用空余时间帮他做了一个通用组件。
效果图如下:
1、按照次数和速度进行,对应的滚动效果。
2、缓动效果可以根据自己的情况进行修改。
项目地址:https://gitee.com/songhuiyuan/utility.git
一、节点视图如下:
二、思路
- 减少控制参数,越少越好,这里有三种
1、初始值
2、控制参数(滚动次数和滚动速度)
3、目标值 - 滚动次数
1、次数小于等于0的时候,只从初始值滚动到目标值(缓动值可以自己去跳这个)
2、次数大于0的时候,分为加速阶段,匀速阶段、减速阶段;我们滚动的次数是控制匀速阶段的。(根据加速阶段最后两帧的位置计算出速度,匀速就按照这个速度进行滚动)。当然可以自动去改动一下达到自己的次数的效果。 - Rolling接口
1、initValue初始值
2、setParam设置控制参数
3、rollToValue滚动函数调用
关于Test.ts中的代码仅仅测试用。没什么意义。
三、代码如下:
Rolling.ts
const { ccclass, property } = cc._decorator;
@ccclass
export default class Rolling extends cc.Component {
/**当前数字 */
private m_curNum: number = 0;
/**字体高度 */
private m_fontHeight: number = 0;
/**开始位置 */
private m_startPoint: cc.Vec2 = cc.v2(0, 0);
/**单个个数 */
private m_singleNum: number = 0;
/**双个个数 */å
private m_doubleNum: number = 0;
private m_isRollIng: boolean = false;
/**轮训次数 */
private m_rollCounts: number = 0;
/**滚动速度 */
private m_rollSpeed: number = 300;
private roolNode: cc.Node = null;
onLoad() {
this.roolNode = this.node;
}
start() {
this.roolNode.x = this.m_startPoint.x;
this.roolNode.y = this.m_startPoint.y;
this.m_singleNum = this.roolNode.childrenCount / 2;
this.m_doubleNum = this.roolNode.childrenCount;
this.m_fontHeight = this.roolNode.height / this.roolNode.childrenCount;
}
public initValue(num: number) {
this.m_curNum = num;
this.roolNode.y = num * this.m_fontHeight;
}
public setParam(rollCount: number, rollSpeed: number) {
this.m_rollCounts = rollCount;
this.m_rollSpeed = rollSpeed;
}
public async rollToValue(num: number) {
let tempNum: number = num;
if (this.m_isRollIng) { return };
if (tempNum < 0 || tempNum > this.m_singleNum) { return };
this.m_isRollIng = true;
if (num < this.m_curNum) {
num += 10;
}
//到目标值长度和单次轮训长度
let distance1: number = (num - this.m_curNum) * this.m_fontHeight;
let distance2: number = this.m_singleNum * this.m_fontHeight;
let time: number;
if (this.m_rollCounts > 0) {
time = await this.rollAccelerateAction(distance2) as number;
time = await this.rollUniformityAction(distance2, time) as number;
time = await this.rollDecelerateAction(distance1, num, tempNum) as number;
this.m_isRollIng = false;
console.log('-----执行完毕----');
}
else {
if (tempNum == this.m_curNum) { return };
time = distance1 / this.m_rollSpeed;
cc.tween(this.roolNode)
.by(time, { position: new cc.Vec3(0, distance1, 0) }, { easing: 'quartInOut' })
.call(() => {
this.initValue(tempNum);
this.m_isRollIng = false;
})
.start();
}
}
/**加速阶段 */
private rollAccelerateAction(distance: number) {
let array: number[] = [];
let time: number = distance / this.m_rollSpeed;
return new Promise((resolve, reject) => {
cc.tween(this.roolNode)
.by(time, { position: new cc.Vec3(0, distance, 0), }, {
easing: 'quartIn',
onUpdate: (target: cc.Vec3, ratio: number) => {
array.push(target.y);
}
})
.call(() => {
this.initValue(this.m_curNum);
let value = array[array.length - 1] - array[array.length - 2];
let speed = value / (1 / array.length);
resolve(distance / speed);
})
.start();
});
}
/**匀速阶段 */
private rollUniformityAction(distance: number, time: number) {
let count: number = 0;
return new Promise((resolve, reject) => {
cc.tween(this.roolNode)
.by(time, { position: new cc.Vec3(0, distance, 0), })
.call(() => {
this.initValue(this.m_curNum);
count++;
}).union().repeat(this.m_rollCounts)
.call(() => {
resolve(null);
console.log(count);
})
.start();
});
}
/**减速阶段 */
private rollDecelerateAction(distance: number, num: number, tempNum: number) {
let time: number = distance / this.m_rollSpeed;
return new Promise((resolve, reject) => {
cc.tween(this.roolNode)
.by(time, { position: new cc.Vec3(0, distance, 0) }, {
easing: 'quartOut'
})
.call(() => {
this.initValue(tempNum);
resolve(null);
})
.start();
});
}
}
Test.ts//测试代码
@ccclass
export default class NewClass extends cc.Component {
private rollScrs: Rolling[] = null;
start () {
let newNode = cc.find('New Node', this.node);
if(newNode) {
this.rollScrs = newNode.getComponentsInChildren(Rolling) || [];
}
}
callBack() {
this.scheduleOnce(() => {
this.rollScrs[0] && this.rollScrs[0].initValue(0);
this.rollScrs[0] && this.rollScrs[0].setParam(0,380);
this.rollScrs[0] && this.rollScrs[0].rollToValue(6);
this.rollScrs[1] && this.rollScrs[1].initValue(2);
this.rollScrs[1] && this.rollScrs[1].setParam(0,380);
this.rollScrs[1] && this.rollScrs[1].rollToValue(0);
this.rollScrs[2] && this.rollScrs[2].initValue(0);
this.rollScrs[2] && this.rollScrs[2].setParam(2,380);
this.rollScrs[2] && this.rollScrs[2].rollToValue(6);
this.rollScrs[3] && this.rollScrs[3].initValue(2);
this.rollScrs[3] && this.rollScrs[3].setParam(2,380);
this.rollScrs[3] && this.rollScrs[3].rollToValue(0);
}, 2)
}
// update (dt) {}
}