AIBase.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import CMath from "../../../../util/CMath";
  2. import FSprite, { SpriteActionType } from "../FSprite";
  3. import SkillBase from "../skill/SkillBase";
  4. /**
  5. * 基础AI
  6. */
  7. const {ccclass, property} = cc._decorator;
  8. /**
  9. * 基础AI设定
  10. * 1.范围巡逻
  11. * 2.攻击进入范围内的敌人
  12. * 3.距离超出后脱离战斗
  13. */
  14. @ccclass
  15. export default class AIBase extends cc.Component {
  16. /**
  17. * AI灵敏度
  18. * 发现敌人后多久开始行动
  19. */
  20. @property({
  21. displayName: '灵敏度(毫秒)'
  22. })
  23. public AI_CD:number = 1000;
  24. /**
  25. * 移动速度
  26. */
  27. @property({
  28. displayName: '角色移动速度'
  29. })
  30. public speed = 50;
  31. /**
  32. * 当前AI拥有的全部技能
  33. */
  34. public skills:Array<SkillBase> = null;
  35. /**
  36. * 当前AI控制的精灵
  37. */
  38. public sprite:FSprite;
  39. /**
  40. * 攻击目标
  41. */
  42. public target:FSprite;
  43. /**
  44. * 最后一次执行AI事件
  45. */
  46. public AI_Time = 0;
  47. /**
  48. * 最后一次执行攻击事件
  49. */
  50. public atk_Time = 0;
  51. /**
  52. * 是否可以释放技能
  53. */
  54. public canSkill = true;
  55. onLoad () {
  56. this.sprite = this.node.getComponent(FSprite);
  57. this.sprite.SPEED_WALK = this.speed;
  58. this.skills = this.node.getComponents(SkillBase);
  59. }
  60. public setTarget(target:FSprite){
  61. if(target != this.target){
  62. this.target = target;
  63. }
  64. }
  65. /**
  66. * 查询目标
  67. */
  68. public checkTarget():FSprite{
  69. if(this.target){
  70. if(this.target.isValid && this.target.hp > 0){
  71. }else{
  72. //死亡或者销毁后查询新的目标
  73. this.target = this.sprite.findEnemy(500).sprite;
  74. }
  75. }else{
  76. this.target = this.sprite.findEnemy(500).sprite;
  77. }
  78. return this.target;
  79. }
  80. update (dt) {
  81. if(this.sprite && this.sprite.isActive){
  82. if(this.sprite.gamePause){
  83. return;
  84. }
  85. this.AI();
  86. }
  87. }
  88. public AI(){
  89. //查询是否有可攻击目标
  90. //查询是否有可用技能
  91. //查询可用技能是否在当前技能攻击范围以内
  92. //超出范围,执行AI移动
  93. //执行巡逻任务
  94. if(!this.canSkill){
  95. return;
  96. }
  97. let target = this.checkTarget();
  98. if(target){
  99. if(this.skills.length > 0){
  100. let skill:SkillBase = this.checkSkill(target);
  101. if(skill){
  102. if(this.speed <= 0){
  103. this.canSkill = false;
  104. skill.exe(target,()=>{
  105. this.canSkill = true;
  106. // cc.log('技能使用结束 :',skill)
  107. });
  108. }else{
  109. let p1 = this.sprite.node.getPosition()
  110. let p2 = target.node.getPosition()
  111. let dis = CMath.getDistance(p1,p2);
  112. if(dis < skill.range){
  113. this.canSkill = false;
  114. skill.exe(target,()=>{
  115. this.canSkill = true;
  116. // cc.log('技能使用结束 :',skill)
  117. });
  118. }else{
  119. this.walk(skill.range);
  120. // this.moveToTarget(target)
  121. }
  122. }
  123. }
  124. }
  125. }
  126. // else{
  127. // if(this.AI_Time == 0){
  128. // this.AI_Time = time;
  129. // }else if(time - this.AI_Time > this.AI_CD){
  130. // this.AI_Time = time;
  131. // this.walk(0);
  132. // }
  133. // }
  134. }
  135. /**
  136. * 查询可用技能
  137. */
  138. public checkSkill(target:FSprite):SkillBase{
  139. let lists:Array<SkillBase> = [];
  140. for (let i = 0; i < this.skills.length; i++) {
  141. const element = this.skills[i];
  142. if(element.ready()){
  143. lists.push(element);
  144. }
  145. }
  146. if(lists.length <= 0){
  147. return null;
  148. }else{
  149. let index = CMath.getRandom(0,lists.length-1);
  150. return lists[index];
  151. // let p1 = this.node.getPosition();
  152. // let p2 = target.node.getPosition();
  153. // let dis = cc.Vec2.distance(p1,p2);
  154. // let fList = [];
  155. // for (let i = 0; i < lists.length; i++) {
  156. // const element = lists[i];
  157. // if(dis < element.range){
  158. // fList.push(element);
  159. // }
  160. // }
  161. // if(fList.length <= 0){
  162. // this.moveToTarget(target);
  163. // return null;
  164. // }else{
  165. // this.sprite.playAction(SpriteActionType.stand,true)
  166. // let index = CMath.getRandom(0,fList.length-1);
  167. // return fList[index];
  168. // }
  169. }
  170. }
  171. /**
  172. * 向目标移动
  173. * @param target
  174. */
  175. private moveToTarget(target:FSprite){
  176. this.sprite.playAction(SpriteActionType.move,true)
  177. let p1 = target.node.getPosition();
  178. let p2 = this.sprite.node.getPosition();
  179. this.atk_Time = 0;
  180. let tmp = {
  181. x:0,
  182. y:0
  183. }
  184. let px1 = p1.x - p2.x;
  185. if(Math.abs(px1) < 50){
  186. tmp.x = 0;
  187. }else if(px1 > 0){
  188. tmp.x = 1;
  189. }else{
  190. tmp.x = -1;
  191. }
  192. let py1 = p1.y - p2.y;
  193. if(Math.abs(py1) < 50){
  194. tmp.y = 0;
  195. }else if(py1 > 0){
  196. tmp.y = 1;
  197. }else{
  198. tmp.y = -1;
  199. }
  200. this.sprite.setDir(tmp);
  201. }
  202. /**
  203. * 远程怪物的闲逛
  204. */
  205. public walk(distance){
  206. if(this.speed > 0){
  207. this.canSkill = false;
  208. this.sprite.setDir(this.getRandState(distance));
  209. this.sprite.playAction(SpriteActionType.move,true)
  210. cc.tween(this).delay(0.5).call(()=>{
  211. this.sprite.setDir({x:0,y:0});
  212. this.sprite.playAction(SpriteActionType.stand,true)
  213. }).delay(1).call(()=>{
  214. this.canSkill = true;
  215. }).start()
  216. }else{
  217. this.canSkill = true;
  218. this.sprite.setDir({x:0,y:0});
  219. this.sprite.playAction(SpriteActionType.stand,true)
  220. }
  221. }
  222. public getRandState(distance){
  223. if(this.target && this.target.isValid && this.target.hp > 0){//如果有目标
  224. let p1 = this.target.node.getPosition();
  225. let p2 = this.sprite.node.getPosition();
  226. let dis = CMath.getDistance(p1,p2);
  227. if(dis > distance){
  228. let tmp = {
  229. x:0,
  230. y:0
  231. }
  232. let px1 = p1.x - p2.x;
  233. if(Math.abs(px1) < 50){
  234. tmp.x = 0;
  235. }else if(px1 > 0){
  236. tmp.x = 1;
  237. }else{
  238. tmp.x = -1;
  239. }
  240. let py1 = p1.y - p2.y;
  241. if(Math.abs(py1) < 50){
  242. tmp.y = 0;
  243. }else if(py1 > 0){
  244. tmp.y = 1;
  245. }else{
  246. tmp.y = -1;
  247. }
  248. return tmp;
  249. }
  250. // else if(dis < 100){
  251. // let tmp = {
  252. // x:0,
  253. // y:0
  254. // }
  255. // let px1 = p1.x - p2.x;
  256. // if(Math.abs(px1) < 50){
  257. // tmp.x = 0;
  258. // }else if(px1 > 0){
  259. // tmp.x = -1;
  260. // }else{
  261. // tmp.x = 1;
  262. // }
  263. // let py1 = p1.y - p2.y;
  264. // if(Math.abs(py1) < 50){
  265. // tmp.y = 0;
  266. // }else if(py1 > 0){
  267. // tmp.y = -1;
  268. // }else{
  269. // tmp.y = 1;
  270. // }
  271. // return tmp;
  272. // }
  273. }
  274. let rand = CMath.getRandom(1,80);
  275. if(rand < 10){
  276. return {x:1,y:0};
  277. }else if(rand < 20){
  278. return {x:1,y:1};
  279. }else if(rand < 30){
  280. return {x:1,y:-1};
  281. }else if(rand < 40){
  282. return {x:0,y:1};
  283. }else if(rand < 50){
  284. return {x:0,y:-1};
  285. }else if(rand < 60){
  286. return {x:-1,y:0};
  287. }else if(rand < 70){
  288. return {x:-1,y:1};
  289. }else{
  290. return {x:-1,y:1};
  291. }
  292. }
  293. }