import { _decorator, Component, Node, MotionStreak, Color, Texture2D } from 'cc'; const { ccclass, property } = _decorator; /** * 子弹拖尾控制器 * 负责管理子弹的拖尾效果 */ @ccclass('BulletTrailController') export class BulletTrailController extends Component { @property({ type: MotionStreak, tooltip: '拖尾组件引用' }) public motionStreak: MotionStreak | null = null; private secondaryStreak: MotionStreak | null = null; // 拖尾配置 private trailConfig = { fadeTime: 0.5, // 拖尾消失时间 minSeg: 1, // 最小分段 stroke: 30, // 拖尾宽度 fastMode: false // 快速模式 }; // 预设颜色 private trailColors = { default: new Color(255, 255, 0, 255), // 黄色 white: new Color(255, 255, 255, 255), // 白色 fire: new Color(255, 100, 0, 255), // 橙红色 gold: new Color(255, 200, 80, 255), // 金黄(更接近外黄效果) ice: new Color(0, 200, 255, 255), // 冰蓝色 poison: new Color(100, 255, 0, 255), // 毒绿色 electric: new Color(200, 0, 255, 255) // 紫色 }; onLoad() { this.initializeTrail(); } /** * 初始化拖尾效果 */ private initializeTrail() { if (!this.motionStreak) { // 尝试从子节点中查找MotionStreak组件 this.motionStreak = this.getComponentInChildren(MotionStreak); if (!this.motionStreak) { // 尝试从当前节点获取 this.motionStreak = this.getComponent(MotionStreak); } } if (this.motionStreak) { this.applyTrailConfig(); } } /** * 应用拖尾配置 */ private applyTrailConfig() { if (!this.motionStreak) return; this.motionStreak.fadeTime = this.trailConfig.fadeTime; this.motionStreak.minSeg = this.trailConfig.minSeg; this.motionStreak.stroke = this.trailConfig.stroke; this.motionStreak.fastMode = this.trailConfig.fastMode; // 保持当前颜色,不在通用配置中强制重置为白色,避免覆盖武器专属颜色 } /** * 设置拖尾颜色 * @param colorType 颜色类型 */ public setTrailColor(colorType: 'default' | 'white' | 'fire' | 'ice' | 'poison' | 'electric') { if (!this.motionStreak) return; const color = this.trailColors[colorType]; if (color) { this.motionStreak.color = color; } } /** * 设置自定义拖尾颜色 * @param color 颜色 */ public setCustomTrailColor(color: Color) { if (!this.motionStreak) return; this.motionStreak.color = color; } /** * 设置拖尾宽度 * @param width 宽度 */ public setTrailWidth(width: number) { if (!this.motionStreak) return; this.trailConfig.stroke = width; this.motionStreak.stroke = width; } /** * 设置拖尾消失时间 * @param fadeTime 消失时间 */ public setTrailFadeTime(fadeTime: number) { if (!this.motionStreak) return; this.trailConfig.fadeTime = fadeTime; this.motionStreak.fadeTime = fadeTime; } /** * 设置拖尾最小分段(越小越平滑,减少三角形感) * @param minSeg 最小分段 */ public setTrailMinSeg(minSeg: number) { if (!this.motionStreak) return; this.trailConfig.minSeg = minSeg; this.motionStreak.minSeg = minSeg; } /** * 设置拖尾纹理 * @param texture 纹理 */ public setTrailTexture(texture: Texture2D) { if (!this.motionStreak) return; this.motionStreak.texture = texture; if (this.secondaryStreak) { this.secondaryStreak.texture = texture; } } /** * 设置快速模式(拖尾响应更灵敏) */ public setFastMode(enabled: boolean) { if (!this.motionStreak) return; this.trailConfig.fastMode = enabled; this.motionStreak.fastMode = enabled; } /** * 预设:火焰喷射拖尾(用于秋葵导弹) */ public applyPresetRocket() { if (!this.motionStreak) return; // 颜色:火焰橙红 this.setTrailColor('fire'); // 更粗的拖尾,形成喷焰柱效果 this.setTrailWidth(36); // 更短的消失时间,拖尾更紧凑 this.setTrailFadeTime(0.14); // 更小的分段让曲线更贴合,避免顶部太宽的三角形感 this.setTrailMinSeg(0.05); // 启用快速模式,响应更快 this.setFastMode(true); // 在下一帧再次强制颜色,防止其他初始化流程覆盖颜色(例如材质或默认值) this.scheduleOnce(() => { if (this.motionStreak) { this.motionStreak.color = this.trailColors.fire; } }, 0); } /** * 启用拖尾效果 */ public enableTrail() { if (this.motionStreak) { this.motionStreak.enabled = true; } } /** * 禁用拖尾效果 */ public disableTrail() { if (this.motionStreak) { this.motionStreak.enabled = false; } } /** * 重置拖尾效果 */ public resetTrail() { if (this.motionStreak) { this.motionStreak.reset(); } if (this.secondaryStreak) { this.secondaryStreak.reset(); } } onDestroy() { // 清理资源 this.motionStreak = null; this.secondaryStreak = null; } /** 创建或获取次级拖尾(用于双层效果) */ private getOrCreateSecondaryStreak(): MotionStreak | null { if (!this.motionStreak) return null; if (this.secondaryStreak && this.secondaryStreak.isValid) return this.secondaryStreak; try { const hostNode = this.motionStreak.node; // 为次级拖尾创建一个子节点,避免与主拖尾同节点可能产生的覆盖/冲突 const child = new Node('TrailEffectSecondary'); hostNode.addChild(child); this.secondaryStreak = child.addComponent(MotionStreak); // 复制基础纹理与参数 this.secondaryStreak.texture = this.motionStreak.texture; this.secondaryStreak.minSeg = this.trailConfig.minSeg; this.secondaryStreak.fadeTime = this.trailConfig.fadeTime; this.secondaryStreak.stroke = this.trailConfig.stroke; this.secondaryStreak.fastMode = this.trailConfig.fastMode; return this.secondaryStreak; } catch (e) { console.warn('[BulletTrailController] 创建次级拖尾失败:', e); return null; } } /** * 预设:双层喷焰(边缘橙红,中心白色) */ public applyPresetRocketDualLayer() { if (!this.motionStreak) return; // 主拖尾:中心白色,稍窄 this.setTrailWidth(24); this.setTrailFadeTime(0.5); this.setTrailMinSeg(1); this.setFastMode(false); this.setTrailColor('white'); // 次级拖尾:边缘橙红,更宽 const secondary = this.getOrCreateSecondaryStreak(); if (secondary) { secondary.stroke = 30; secondary.fadeTime = 0.5; secondary.minSeg = 1; secondary.fastMode = false; // 使用金黄色增强外层可见性 secondary.color = this.trailColors.gold; } // 保护色:下一帧再次写入 this.scheduleOnce(() => { if (this.motionStreak && this.motionStreak.isValid) { this.motionStreak.color = this.trailColors.white; } if (this.secondaryStreak && this.secondaryStreak.isValid) { this.secondaryStreak.color = this.trailColors.gold; } }, 0); } }