欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > egret 拖尾的实现 MotionStreak

egret 拖尾的实现 MotionStreak

2024/11/30 11:39:54 来源:https://blog.csdn.net/u014686778/article/details/141302467  浏览:    关键词:egret 拖尾的实现 MotionStreak

背景:egret项目中需要用到拖尾效果,引擎原生没有提供,参考cocos2dx 的 MotionStreak实现拖尾效果。

原理

拖尾的原理很简单,定时记录节点的位置,根据运行的轨迹和指定的拖尾宽度生成拖尾网格,然后将纹理绘制在拖尾网格上。

1.记录运行轨迹。若记拖尾的长度为4,则只保留4个路径点,即下次记录的新点E,并且需要删除点A.
在这里插入图片描述

2.拖尾宽度就按照轨迹点线性减小,注意每个路径点的拖尾宽度不是固定不变的,当A点被删除时 B点就成为了最尾端,此时B点的拖尾宽度就为0。
在这里插入图片描述
3.计算网格点,由于每个路径点对应拖尾宽度是不断变化的,所以每次绘制时都要重新计算网格点。我们可以根据相邻路径点来计算网格点相对于路径的坐标偏移系数,这个值可以保存下来,因为对于确定的路径点,系数是不会变的。
在这里插入图片描述
4.将拖尾纹理按照节点数划分,绘制到网格上即可。
在这里插入图片描述

代码

在BitMap类上做扩展,使用 MeshNode作为$renderNode。

namespace egret {class StreakData { //移动路径数据x:number; //global xy:number; //global yxCoefficient:number = 0; //与位置、拖尾宽度结合计算顶点x坐标yCoefficient:number = 0; //与位置、拖尾宽度结合计算顶点y坐标public constructor(_x:number,_y:number) {this.x = _x;this.y = _y;}}export class MotionStreak extends Bitmap {private stroke:number;    //拖尾的宽度private tail:number;      //拖尾的节点数private streakDatas: StreakData[]; //拖尾的数据private uvs: number[];private indices: number[];/*** @param value egret Texture* @param stroke 拖尾的宽度 单位:像素 默认值:10* @param tail 拖尾的节点数 默认值:11*/public constructor(value: Texture, stroke:number = 10, tail: number = 11) {super(value);this.stroke = stroke;this.tail = tail;this.$renderNode = new sys.MeshNode();}protected createNativeDisplayObject(): void {this.$nativeDisplayObject = new egret_native.NativeDisplayObject(egret_native.NativeObjectType.SPRITE);}//没有必要$hitTest(stageX:number, stageY:number):DisplayObject {return null;}$updateRenderNode(): void {let image = this.$bitmapData;if (!image) {return;}let node = <sys.MeshNode>this.$renderNode;node.smoothing = this.$smoothing;node.image = image;node.imageWidth = this.$sourceWidth;node.imageHeight = this.$sourceHeight;let destW: number = !isNaN(this.$explicitBitmapWidth) ? this.$explicitBitmapWidth : this.$textureWidth;let destH: number = !isNaN(this.$explicitBitmapHeight) ? this.$explicitBitmapHeight : this.$textureHeight;let tsX: number = destW / this.$textureWidth;let tsY: number = destH / this.$textureHeight;let bitmapWidth: number = this.$bitmapWidth;let bitmapHeight: number = this.$bitmapHeight;node.drawMesh(this.$bitmapX, this.$bitmapY,bitmapWidth, bitmapHeight,this.$offsetX * tsX, this.$offsetY * tsY,tsX * bitmapWidth, tsY * bitmapHeight);}$onAddToStage(stage: Stage, nestLevel: number): void {super.$onAddToStage(stage, nestLevel);this.addEventListener(Event.ENTER_FRAME, this.parseData, this);this.streakDatas = [];this.uvs = [];this.indices = [];//需要渲染 this.tail-1个四边形let deltaU = 1/(this.tail-1);let gPos = this.localToGlobal(this.x, this.y);for (let i = 0, datas = this.streakDatas = [];; i++) {datas[i] = new StreakData(gPos.x,gPos.y);//纹理uvthis.uvs.push(i * deltaU);this.uvs.push(0);this.uvs.push(i * deltaU);this.uvs.push(1);if (i == this.tail-1)break;/**顶点索引方式* 0    2     4  ...* |    |     | *  >>> xy 历史路径点 >>>  ...* |    |     |* 1    3     5  ...*/let ii = i*6, iv = i*2;this.indices[ii++] = iv + 0;this.indices[ii++] = iv + 1;this.indices[ii++] = iv + 2;this.indices[ii++] = iv + 2;this.indices[ii++] = iv + 1;this.indices[ii++] = iv + 3;}}$onRemoveFromStage(): void {super.$onRemoveFromStage();this.removeEventListener(Event.ENTER_FRAME,this.parseData, this);}private parseData(): void {let first = this.streakDatas.shift();this.streakDatas.push(first);//记录 当前位置let cur = this.streakDatas[this.tail-1];let gPos = this.localToGlobal(0, 0);cur.x = gPos.x;cur.y = gPos.ylet last = this.streakDatas[this.tail-2];let dX = cur.x - last.x;let dY = cur.y - last.y;let dis = Math.sqrt(dX*dX+dY*dY);if (dis > 0) {cur.xCoefficient = last.xCoefficient = dY / dis;cur.yCoefficient = last.yCoefficient = dX / dis;} else {cur.xCoefficient = 0;cur.yCoefficient = 0;}let node: egret.sys.MeshNode = <egret.sys.MeshNode>this.$renderNode;node.uvs = this.uvs;node.indices = this.indices;node.vertices.length = this.uvs.length;let widthStride = this.stroke/2/(this.tail-1);let tempPoint = new egret.Point();for (let i = 0, datas = this.streakDatas; i < this.tail; i++) {let data = datas[i];let iv = i * 4;this.globalToLocal(data.x + widthStride * i * data.xCoefficient,data.y - widthStride * i * data.yCoefficient, tempPoint)node.vertices[iv] = tempPoint.x;node.vertices[iv+1] = tempPoint.y;this.globalToLocal(data.x - widthStride * i * data.xCoefficient,data.y + widthStride * i * data.yCoefficient, tempPoint)node.vertices[iv+2] = tempPoint.x;node.vertices[iv+3] = tempPoint.y;}}}
}

测试

测试的纹理:
在这里插入图片描述
效果如下:

请添加图片描述

对调一下纹理:

请添加图片描述

完结。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com