import { _decorator, Component, Node, Sprite, SpriteFrame, resources, tween, Vec3 } from 'cc'; const { ccclass, property } = _decorator; // 角色位置 type CharacterPosition = 'left' | 'center' | 'right'; // 角色数据 interface CharacterData { id: string; name: string; emotion: string; position: CharacterPosition; visible: boolean; } @ccclass('CharacterView') export class CharacterView extends Component { @property(Node) leftCharacter: Node; @property(Node) centerCharacter: Node; @property(Node) rightCharacter: Node; // 角色资源缓存 private characterAssets: Map> = new Map(); onLoad() { // 初始化所有角色隐藏 this.hideAllCharacters(); } /** * 显示角色 */ showCharacter(characterId: string, name: string, emotion: string, position: CharacterPosition) { const node = this.getCharacterNode(position); if (!node) return; // 加载角色立绘 this.loadCharacterSprite(characterId, emotion, (spriteFrame) => { if (spriteFrame) { const sprite = node.getComponent(Sprite); if (sprite) { sprite.spriteFrame = spriteFrame; } // 显示节点 node.active = true; // 播放出场动画 this.playEnterAnimation(node); } }); } /** * 隐藏角色 */ hideCharacter(characterId: string) { // 遍历所有位置查找并隐藏 [this.leftCharacter, this.centerCharacter, this.rightCharacter].forEach(node => { if (node && node.active) { node.active = false; } }); } /** * 隐藏所有角色 */ hideAllCharacters() { [this.leftCharacter, this.centerCharacter, this.rightCharacter].forEach(node => { if (node) { node.active = false; } }); } /** * 切换角色表情 */ setEmotion(emotion: string) { // 这个方法需要在具体场景中根据当前显示的角色来实现 // 可以通过在场景中保存当前角色ID来调用 console.log('切换表情:', emotion); } /** * 获取角色节点 */ private getCharacterNode(position: CharacterPosition): Node { switch (position) { case 'left': return this.leftCharacter; case 'center': return this.centerCharacter; case 'right': return this.rightCharacter; default: return this.centerCharacter; } } /** * 加载角色立绘 */ private loadCharacterSprite(characterId: string, emotion: string, callback: (spriteFrame: SpriteFrame) => void) { const path = `characters/${characterId}/${emotion}`; // 检查缓存 if (this.characterAssets.has(characterId)) { const emotionMap = this.characterAssets.get(characterId); if (emotionMap && emotionMap.has(emotion)) { callback(emotionMap.get(emotion)); return; } } // 加载新资源 resources.load(path, SpriteFrame, (err, spriteFrame) => { if (err) { console.warn(`加载角色立绘失败: ${path}`, err); callback(null); return; } // 缓存 if (!this.characterAssets.has(characterId)) { this.characterAssets.set(characterId, new Map()); } this.characterAssets.get(characterId).set(emotion, spriteFrame); callback(spriteFrame); }); } /** * 播放出场动画 */ private playEnterAnimation(node: Node) { // 从下方进入 const originalPos = node.position.clone(); node.setPosition(originalPos.x, originalPos.y - 200, originalPos.z); tween(node) .to(0.3, { position: originalPos }, { easing: 'backOut' }) .start(); } /** * 播放退场动画 */ playExitAnimation(node: Node, callback?: () => void) { tween(node) .to(0.3, { position: new Vec3(node.position.x, node.position.y - 200, node.position.z) }) .call(() => { node.active = false; if (callback) callback(); }) .start(); } /** * 预加载角色资源 */ preloadCharacter(characterId: string, emotions: string[]) { emotions.forEach(emotion => { const path = `characters/${characterId}/${emotion}`; resources.preload(path, SpriteFrame); }); } /** * 清除缓存 */ clearCache() { this.characterAssets.clear(); } }