import { _decorator, Component, Node, log, AnimationComponent, RigidBodyComponent, Vec3, find, ParticleSystemComponent, instantiate, Prefab, loader } from 'cc'; import { SoundManager } from '../../../../engines/sounds/SoundManager'; import CCSAnimationUtils from '../../../../engines/utils/CCSAnimationUtils'; import { MathUtils } from '../../../../engines/utils/MathUtils'; import GameConfigManager from '../../../models/GameConfigManager'; import { GameController } from '../GameController'; import { MonsterHP } from './MonsterHP'; import { MonsterHPUIPool } from './MonsterHPUIPool'; const { ccclass, property } = _decorator; @ccclass('MonsterBase') export class MonsterBase extends Component { config:any; monsterConfig:any; hpView:MonsterHP; /** * 血量 */ hp:number=0; /** * 最大血量 */ maxHP:number=0; /** * 伤害 */ damage:number; private speedVec3:Vec3=new Vec3(); private speedVec3N:Vec3=new Vec3(); private endNode:Node; private animation:AnimationComponent; /** * 0 移动 1攻击 2 被攻击 3死亡 */ private state:number=0; /** * 攻击类型 0攻击栅栏 1攻击玩家 */ private attackType:number=0; /** * 弹痕粒子 */ private danHen:ParticleSystemComponent; start () { this.monsterConfig=GameConfigManager.GetMonsterConfig(this.config.monsterId); this.hp=this.maxHP=this.config.hp; this.damage=this.config.damage; this.animation=this.getComponent(AnimationComponent); if(this.animation==null){ throw new Error("动画组件为空!"); } this.InitAnimations(); this.InitPostitionAndEndPos(); this.InitScale(); } /** * 子节点收集 * @param root * @param list */ private getChildren(root:Node,list:Node[]):void{ root.children.forEach(element => { list.push(element); if(element.children.length>0){ this.getChildren(element,list); } }); } /** * 动画数据初始化 */ private InitAnimations():void{ CCSAnimationUtils.SetAnimationSpeed(this.animation,this.monsterConfig.moveAnimation,this.monsterConfig.moveAnimationSpeed); CCSAnimationUtils.SetAnimationSpeed(this.animation,this.monsterConfig.attackAnimation,this.monsterConfig.attackAnimationSpeed); // CCSAnimationUtils.SetAnimationEvent(this.animation,this.monsterConfig.attackAnimation,this.monsterConfig.attackAnimationEvents); CCSAnimationUtils.SetAnimationSpeed(this.animation,this.monsterConfig.dieAnimation,this.monsterConfig.dieAnimationSpeed); } /** * 初始化开始位置及结束位置 */ private InitPostitionAndEndPos():void{ //左 if(this.config.startPos==0){ this.endNode=GameController.single.leftEndNode; }else if(this.config.startPos==1){//中 this.endNode=GameController.single.middleEndNode; }else{//右 this.endNode=GameController.single.rightEndNode; } Vec3.subtract(this.speedVec3N,this.endNode.worldPosition,this.node.worldPosition); this.speedVec3N.normalize(); this.Move(); } /** * 初始化Scale */ private InitScale():void{ let scale:Vec3=this.node.scale; scale.x*=this.monsterConfig.scale.x; scale.y*=this.monsterConfig.scale.y; scale.z*=this.monsterConfig.scale.z; this.node.setScale(scale); } update (deltaTime: number) { if(GameController.single.GameOver){ return; } if(GameController.single.paused){ this.animation.pause(); return; }else{ this.animation.resume(); } if(this.isDie){ return; } let dis:number; if(GameController.single.fence.IsDie==false){ dis=Vec3.distance(GameController.single.fence.node.worldPosition,this.node.worldPosition); if(dis<2){ this.Attack(0); }else{ this.Move(); } }else{ dis=Vec3.distance(this.endNode.worldPosition,this.node.worldPosition); //到达终点 if(dis<0.5){ //攻击 this.Attack(1); return; }else{ this.Move(); } } if(this.state==0){ this.MoveUpdate(deltaTime); } } /** * 开始移动 */ Move():void{ if(this.state>0){ return; } this.removeAllAnimationEvent(); this.state=0; } private MoveUpdate(deltaTime:number):void{ this.animation.crossFade(this.monsterConfig.moveAnimation); let currentPos:Vec3=this.node.position; Vec3.multiplyScalar(this.speedVec3,this.speedVec3N,this.monsterConfig.moveSpeed*deltaTime); Vec3.add(currentPos,currentPos,this.speedVec3); this.node.setPosition(currentPos); } /** * 攻击 */ private Attack(attackType:number):void{ this.attackType=attackType; if(this.state==1||this.state==2){ return; } this.state=1; this.removeAllAnimationEvent(); this.animation.on(AnimationComponent.EventType.FINISHED,this.AttackComplete,this,true); this.animation.play(this.monsterConfig.attackAnimation); } // /** // * 攻击生效帧回调 // */ // AttackDamageFrame():void{ // console.log(this.config.mId+"攻击"+this.attackType); // GameController.single.MonsterAttack(this.attackType,this.config.damage); // } private AttackComplete():void{ console.log(this.config.mId+"攻击"+this.attackType); GameController.single.MonsterAttack(this.attackType,this.config.damage); this.state=0; this.Move(); } /** * 受伤 * @param value */ Damage(value:number):void{ if(this.hp==0){ return; } this.hp-=value; if(this.hp<=0){ this.hp=0; this.Die(); }else{ if(this.state==3){ return; } this.state=2; this.removeAllAnimationEvent(); if(this.animation==null){ return; } this.animation.on(AnimationComponent.EventType.FINISHED,this.DamageComplete,this,true); this.animation.play(this.monsterConfig.damageAnimation); } //音效 let v:number=Math.random()*10; let url:string; if(v<5){ url="sounds/zombieDamage"; }else{ url="sounds/zombieDamage1"; } if(SoundManager.single.ChannelIsPlaying(this.config.id)){ SoundManager.single.PlaySound(this.config.id,url); } //弹痕 if(this.danHen==null){ let prefab:Prefab=loader.getRes(this.monsterConfig.damageParticle); let danhenNode:Node=instantiate(prefab); this.danHen=danhenNode.getComponent(ParticleSystemComponent); this.node.addChild(danhenNode); } this.danHen.node.active=true; let pos:Vec3=this.danHen.node.position; pos.x=MathUtils.RandomRange(-0.08,0.08); pos.y=MathUtils.RandomRange(0.5,0.8); this.danHen.node.position=pos; this.danHen.stop(); this.danHen.play(); } private DamageComplete():void{ this.state=0; this.Move(); } Die():void{ if(this.state==3){ return; } this.state=3; SoundManager.single.PlaySound(this.config.id,"sounds/zombieDie"); this.removeAllAnimationEvent(); this.animation.on(AnimationComponent.EventType.FINISHED,this.DieComplete,this,true); this.animation.play(this.monsterConfig.dieAnimation); } private DieComplete():void{ this.node.active=false; this.node.destroy(); } onDestroy():void{ SoundManager.single.ClearSound(this.config.id); this.danHen=null; MonsterHPUIPool.Recycle(this.hpView); this.hpView=null; } private removeAllAnimationEvent():void{ if(this.animation==null){ return; } if(this.animation.hasEventListener(AnimationComponent.EventType.FINISHED,this.DamageComplete,this)){ this.animation.off(AnimationComponent.EventType.FINISHED,this.DamageComplete,this); } if(this.animation.hasEventListener(AnimationComponent.EventType.FINISHED,this.AttackComplete,this)){ this.animation.off(AnimationComponent.EventType.FINISHED,this.AttackComplete,this); } if(this.animation.hasEventListener(AnimationComponent.EventType.FINISHED,this.DieComplete,this)){ this.animation.off(AnimationComponent.EventType.FINISHED,this.DieComplete,this); } } get isDie():boolean{ if(this.hp<=0){ return true; } return false; } /** * 血条显示位置 */ get hpSocket():Node{ let socket:Node=find("RootNode/Root/HpSocket",this.node); return socket?socket:this.node; } }