import CMath from "../../../../util/CMath"; import FSprite, { SpriteActionType } from "../FSprite"; import SkillBase from "../skill/SkillBase"; /** * 基础AI */ const {ccclass, property} = cc._decorator; /** * 基础AI设定 * 1.范围巡逻 * 2.攻击进入范围内的敌人 * 3.距离超出后脱离战斗 */ @ccclass export default class AIBase extends cc.Component { /** * AI灵敏度 * 发现敌人后多久开始行动 */ @property({ displayName: '灵敏度(毫秒)' }) public AI_CD:number = 1000; /** * 攻击间隔 ms * 一次攻击后间隔多久开始下次攻击 */ @property({ displayName: '攻击间隔(毫秒)' }) public atk_CD = 3000; /** * 每次攻击几颗子弹 */ @property({ displayName: '每次攻击子弹数量' }) public atk_count = 1; /** * 移动速度 */ @property({ displayName: '移动速度' }) public speed = 50; /** * 当前AI拥有的全部技能 */ public skills:Array = null; /** * 当前AI控制的精灵 */ public sprite:FSprite; /** * 攻击目标 */ public target:FSprite; /** * 最后一次执行AI事件 */ public AI_Time = 0; /** * 最后一次执行攻击事件 */ public atk_Time = 0; /** * 是否可以释放技能 */ public canSkill = true; onLoad () { this.sprite = this.node.getComponent(FSprite); this.sprite.SPEED_WALK = this.speed; this.skills = this.node.getComponents(SkillBase); } public setTarget(target:FSprite){ if(target != this.target){ this.target = target; } } /** * 查询目标 */ public checkTarget():FSprite{ if(this.target){ if(this.target.isValid && this.target.hp > 0){ }else{ //死亡或者销毁后查询新的目标 this.target = this.sprite.findEnemy(500).sprite; } }else{ this.target = this.sprite.findEnemy(500).sprite; } return this.target; } update (dt) { if(this.sprite && this.sprite.isActive){ if(this.sprite.gamePause){ return; } this.AI(); } } public AI(){ //查询是否有可攻击目标 //查询是否有可用技能 //查询可用技能是否在当前技能攻击范围以内 //超出范围,执行AI移动 //执行巡逻任务 if(!this.canSkill){ return; } let time = new Date().getTime(); let target = this.checkTarget(); if(target){ if(this.skills.length > 0){ let skill = this.checkSkill(target); if(skill){ // cc.log('开始使用技能 :',skill) this.canSkill = false; skill.exe(target,()=>{ this.canSkill = true; // cc.log('技能使用结束 :',skill) }); }else{ if(this.AI_Time == 0){ this.AI_Time = time; }else if(time - this.AI_Time > this.AI_CD){ this.AI_Time = time; this.walk(this.sprite.mButtleDis); } } } else{ if(time - this.atk_Time > this.atk_CD){ this.atk_Time = time; this.fire(target); } } }else{ if(this.AI_Time == 0){ this.AI_Time = time; }else if(time - this.AI_Time > this.AI_CD){ this.AI_Time = time; this.walk(this.sprite.mButtleDis); } } } /** * 查询可用技能 */ public checkSkill(target:FSprite):SkillBase{ let lists:Array = []; for (let i = 0; i < this.skills.length; i++) { const element = this.skills[i]; if(element.ready()){ lists.push(element); } } if(lists.length <= 0){ return null; }else{ let p1 = this.node.getPosition(); let p2 = target.node.getPosition(); let dis = cc.Vec2.distance(p1,p2); let fList = []; for (let i = 0; i < lists.length; i++) { const element = lists[i]; if(dis < element.range){ fList.push(element); } } if(fList.length <= 0){ this.moveToTarget(target); return null; }else{ this.sprite.playAction(SpriteActionType.stand,true) let index = CMath.getRandom(0,fList.length-1); return fList[index]; } } } /** * 向目标移动 * @param target */ private moveToTarget(target:FSprite){ this.sprite.playAction(SpriteActionType.move,true) let p1 = target.node.getPosition(); let p2 = this.sprite.node.getPosition(); this.atk_Time = 0; let tmp = { x:0, y:0 } let px1 = p1.x - p2.x; if(Math.abs(px1) < 50){ tmp.x = 0; }else if(px1 > 0){ tmp.x = 1; }else{ tmp.x = -1; } let py1 = p1.y - p2.y; if(Math.abs(py1) < 50){ tmp.y = 0; }else if(py1 > 0){ tmp.y = 1; }else{ tmp.y = -1; } this.sprite.setDir(tmp); } public fire(target:FSprite){ //判断是否在攻击范围内 let mts = this.sprite.mButtleDis; let p1 = target.node.getPosition(); let p2 = this.sprite.node.getPosition(); let dis = cc.Vec2.distance(p1,p2); if(dis > mts){ this.moveToTarget(target); }else{ this.sprite.setDir({x:0,y:0}); this.sprite.setShooting(true); let count = 0; this.canSkill = false; this.sprite.setFireCallback(()=>{ count ++; if(count >= this.atk_count){ this.sprite.setShooting(false); this.sprite.setFireCallback(null); cc.tween(this).delay(0.7).call(()=>{ this.walk(this.sprite.mButtleDis); }).start(); } }); } } /** * 远程怪物的闲逛 */ public walk(distance){ cc.tween(this).delay(0).call(()=>{ this.sprite.setDir(this.getRandState(distance)); this.sprite.playAction(SpriteActionType.move,true) }).delay(0.5).call(()=>{ this.canSkill = true; this.sprite.setDir({x:0,y:0}); this.sprite.playAction(SpriteActionType.stand,true) }).start(); } public getRandState(distance){ if(this.target && this.target.isValid && this.target.hp > 0){//如果有目标 let p1 = this.target.node.getPosition(); let p2 = this.sprite.node.getPosition(); let distance = this.sprite.mButtleDis; let dis = CMath.getDistance(p1,p2); if(dis > 150){ let tmp = { x:0, y:0 } let px1 = p1.x - p2.x; if(Math.abs(px1) < 50){ tmp.x = 0; }else if(px1 > 0){ tmp.x = 1; }else{ tmp.x = -1; } let py1 = p1.y - p2.y; if(Math.abs(py1) < 50){ tmp.y = 0; }else if(py1 > 0){ tmp.y = 1; }else{ tmp.y = -1; } return tmp; } // else if(dis < 100){ // let tmp = { // x:0, // y:0 // } // let px1 = p1.x - p2.x; // if(Math.abs(px1) < 50){ // tmp.x = 0; // }else if(px1 > 0){ // tmp.x = -1; // }else{ // tmp.x = 1; // } // let py1 = p1.y - p2.y; // if(Math.abs(py1) < 50){ // tmp.y = 0; // }else if(py1 > 0){ // tmp.y = -1; // }else{ // tmp.y = 1; // } // return tmp; // } } let rand = CMath.getRandom(1,80); if(rand < 10){ return {x:1,y:0}; }else if(rand < 20){ return {x:1,y:1}; }else if(rand < 30){ return {x:1,y:-1}; }else if(rand < 40){ return {x:0,y:1}; }else if(rand < 50){ return {x:0,y:-1}; }else if(rand < 60){ return {x:-1,y:0}; }else if(rand < 70){ return {x:-1,y:1}; }else{ return {x:-1,y:1}; } } }