Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smooth Motion Streak movement #9693

Merged
merged 1 commit into from Mar 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions cocos2d/core/components/CCMotionStreak.js
Expand Up @@ -61,6 +61,7 @@ var MotionStreak = cc.Class({

ctor () {
this._points = [];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我是不太能理解渲染数据挂在组件上的行为。
谁使用,就应该谁持有。

this._lastWPos = new cc.Vec2();
},

properties: {
Expand Down Expand Up @@ -247,6 +248,8 @@ var MotionStreak = cc.Class({
reset () {
this._points.length = 0;
this._assembler && this._assembler._renderData.clear();
this._lastWPos.x = 0;
this._lastWPos.y = 0;
if (CC_EDITOR) {
cc.engine.repaintInEditMode();
}
Expand Down
109 changes: 75 additions & 34 deletions cocos2d/core/renderer/webgl/assemblers/motion-streak.js
Expand Up @@ -77,6 +77,11 @@ function computeMiter (miter, lineA, lineB, halfThick, maxMultiple) {
}

export default class MotionStreakAssembler extends Assembler2D {
constructor () {
super();
this._tailShortenTime = 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

用来计算最后一节拖尾缩短的速度。原有算法不对,导致时灵时不灵。

}

initData () {
this._renderData.createFlexData(0, 16, (16 - 2) * 3);
}
Expand All @@ -91,78 +96,114 @@ export default class MotionStreakAssembler extends Assembler2D {
let tx = matrix[12], ty = matrix[13];

let points = comp._points;
let lastPos = comp._lastWPos;
let fadeTime = comp._fadeTime;

let cur;
if (points.length > 1) {
let difx = points[0].point.x - tx;
let dify = points[0].point.y - ty;
if ((difx*difx + dify*dify) < comp.minSeg) {
let moved = lastPos.x !== tx || lastPos.y !== ty;
if (moved) {
let cur;
let newHead = false;
if (points.length === 0) {
// new
let prev = new Point();
prev.setPoint(lastPos.x, lastPos.y);
this._tailShortenTime = prev.time = fadeTime;
points.push(prev);

cur = new Point();
points.unshift(cur);
}
else {
// check moved distance
cur = points[0];
let prev = points[1];
let difx = prev.point.x - tx;
let dify = prev.point.y - ty;
newHead = ((difx*difx + dify*dify) >= comp.minSeg*comp.minSeg);
}
// update head
cur.setPoint(tx, ty);
cur.time = fadeTime + dt;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

只有移动了,才能重新激活拖尾(的时间)。如果不动,拖尾就应该逐渐消失。原先每一帧都重新激活拖尾,会导致最后一节拖尾突然消失。

let prev = points[1];
cur.distance = cur.point.sub(prev.point, _vec2).mag();
_vec2.normalizeSelf();
cur.setDir(_vec2.x, _vec2.y);

let prevIsTail = points.length === 2;
if (prevIsTail) {
prev.setDir(_vec2.x, _vec2.y);
}
}

if (!cur) {
cur = new Point();
points.unshift(cur);
if (newHead) {
let point = new Point(cur.point.clone(), cur.dir.clone());
point.distance = cur.distance;
point.time = cur.time;
points.unshift(point);
}
}

cur.setPoint(tx, ty);
cur.time = comp._fadeTime + dt;

let verticesCount = 0;
let indicesCount = 0;
lastPos.x = tx;
lastPos.y = ty;

if (points.length < 2) {
return;
}

let color = comp._color,
cr = color.r, cg = color.g, cb = color.b, ca = color.a;
// cc.log(points.map(x => x.time.toFixed(2)).reverse().join(' '), ',', this._tailShortenTime.toFixed(2));

let prev = points[1];
prev.distance = cur.point.sub(prev.point, _vec2).mag();
_vec2.normalizeSelf();
prev.setDir(_vec2.x, _vec2.y);
cur.setDir(_vec2.x, _vec2.y);
let color = comp._color, ca = color.a;
let crgb = (color.b<<16) | (color.g<<8) | color.r;

let verticesCount = 0;
let indicesCount = 0;
let flexBuffer = this._renderData._flexBuffer;
flexBuffer.reserve(points.length*2, (points.length-1)*6);
let vData = flexBuffer.vData;
let uintVData = flexBuffer.uintVData;
let vertsOffset = 5;

let fadeTime = comp._fadeTime;
let findLast = false;
for (let i = points.length - 1; i >=0 ; i--) {
let p = points[i];
let point = p.point;
let dir = p.dir;
p.time -= dt;

if (p.time < 0) {

let isLast = i === points.length - 1;

if (p.time <= 0) {
if (isLast && i - 1 >= 0) {
this._tailShortenTime = points[i - 1].time - dt;
}
points.splice(i, 1);
continue;
}

let progress = p.time / fadeTime;

let next = points[i - 1];
if (!findLast) {
if (isLast) {
let next = points[i - 1];
if (!next) {
points.splice(i, 1);
continue;
}

point.x = next.point.x - dir.x * progress;
point.y = next.point.y - dir.y * progress;
let nextIsStatic = points.length >= 3;
if (nextIsStatic) {
let segmentProgress = p.time / this._tailShortenTime;
if (segmentProgress <= 1) {
point.x = next.point.x - next.distance * next.dir.x * segmentProgress;
point.y = next.point.y - next.distance * next.dir.y * segmentProgress;
}
}
else {
this._tailShortenTime = p.time;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果 point 数量不足,不缩短拖尾,因为缺少计算出平均速度的变量。会导致移动速度比较慢时,第一节拖尾始终出不来。

}
}
findLast = true;

normal(_normal, dir);
Copy link
Contributor Author

@jareguo jareguo Nov 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO:这里直接用法向量做为两个顶点的位置,效果并不是最好的,会有很多线段的交叉
image

比较好的做法是判断线段顶点的距离,确保距离之合最小,一旦发现交叉,交换左右两侧的顶点(位置换,UV 不能换),效果就会好很多。



let da = progress*ca;
let c = ((da<<24) >>> 0) + (cb<<16) + (cg<<8) + cr;
let da = progress * ca;
let c = ((da<<24) >>> 0) | crgb;

let offset = verticesCount * vertsOffset;

Expand All @@ -183,7 +224,7 @@ export default class MotionStreakAssembler extends Assembler2D {
verticesCount += 2;
}

indicesCount = verticesCount <= 2 ? 0 : (verticesCount - 2)*3;
indicesCount = verticesCount <= 2 ? 0 : (verticesCount - 2) * 3;

flexBuffer.used(verticesCount, indicesCount);
}
Expand Down