import npcHelper from "../../../dataManager/npcHelper"; import { Log, LOG_TAG } from "../../../framework/log/Log"; import dungeonLogic from "../../dungeonLogic"; import LevelLogic from "../../levelLogic"; import gameData from "../../utrl/gameData"; import { EVENT_TYPE, GAME_OBJECT_TYPE, ROLE_STATE } from "../../utrl/gameEnum"; import gameEventManager from "../../utrl/gameEventManager"; import GameObject from "../gameObject"; import PlayerObject from "../player/playerObject"; import ZombieProp from "./zombieProp"; import zombieView from "./zombieView"; const { ccclass, requireComponent, property } = cc._decorator; /**僵尸实体类 */ @ccclass @requireComponent(cc.RigidBody) export default class ZomBieObject extends GameObject { /**僵尸血条 */ @property(cc.Node) cur_hp_bar: cc.Node = null; @property /**移动速度 */ speed = 50; /**逻辑方法组件 */ zombie_prop: ZombieProp = null; /**初始化完成 */ private inited = false; /**本身刚体 */ private rigid: cc.RigidBody = null; /**视图逻辑 */ public zombie_view: zombieView = null; /**角色组,0玩家组,1僵尸组 */ private roles: cc.Node[][] = [[], []]; private barScaleX = 1; attackCb: () => void; canWalk: boolean = true; //是否可以行走 isDie: boolean = false; isPause: boolean = false; isInUI: boolean = false; onEnable() { this.rigid = this.node.getComponent(cc.RigidBody); // this.rigid.type = cc.RigidBodyType.Dynamic; gameEventManager.on(EVENT_TYPE.CHANGE_STATUS, this.changeStatue, this) this.rigid.gravityScale = 0; this.rigid.linearDamping = 5; this.rigid.fixedRotation = true; this.attackCb = () => { this.zombie_view.playIdle(); this.canWalk = true; //攻击播放完才行走 } } onDisable() { gameEventManager.off(EVENT_TYPE.CHANGE_STATUS, this.changeStatue, this); } changeStatue(flag) { this.isPause = flag; } update(dt: number) { if (this.isPause) { return; } if (this.roles[0] == null || this.roles[1] == null) { return; } this.cur_hp_bar.parent.scaleX = this.node.scaleX * this.barScaleX; let p = this.zombie_prop.cur_hp / this.zombie_prop.base_hp; if (p == 1 || p == 0) { this.cur_hp_bar.parent.active = false; } else { this.cur_hp_bar.parent.active = true; this.cur_hp_bar.width = this.cur_hp_bar.parent.width * p; } if (!this.inited) { return; } this.runState(dt); } /**初始化 */ init(id: number, pos: cc.Vec3, roles: cc.Node[][], isPause?, isInUI?) { this.isPause = isPause; this.type = GAME_OBJECT_TYPE.zombie; if (this.zombie_prop == null) { this.zombie_prop = new ZombieProp(); } if (isInUI) { this.isInUI = isInUI; } this.zombie_prop.init(id); this.zombie_view = this.node.getComponent(zombieView); this.zombie_view.init(id); this.node.setPosition(pos); this.setBarView(); this.roles = roles; this.inited = true; this.node.active = true; this.isDie = false; } setBarView() { let curID = this.zombie_prop.zombie_ID; if (npcHelper.isBoss(curID)) { if (curID == 54) { this.cur_hp_bar.parent.y += 100; } else { this.cur_hp_bar.parent.y += 200; } this.barScaleX = 2; this.cur_hp_bar.parent.scaleY = 2; } } /**运行状态机 */ runState(dt: number) { let target = this.getCloseTarget(this.roles[0], this.zombie_prop.search_range); if (target != null) { let cbk = () => { this.attack(target); }; let len = target.position.sub(this.node.position).mag(); if (len < this.zombie_prop.hand_range) { this.rigid.type = cc.RigidBodyType.Animated; // this.zombie_view.playIdle(); this.zombie_prop.attackRun(dt, cbk); } else { this.rigid.type = cc.RigidBodyType.Dynamic; this.moveToTarget(target); if (this.canWalk) { this.zombie_view.playWalk(); } } if (this.node.x > target.x) { this.zombie_view.node.scaleX = 1; } else { this.zombie_view.node.scaleX = -1; } } else { this.zombie_view.playIdle(); let o = 5 if (this.rigid.linearVelocity.x > o) { this.zombie_view.node.scaleX = -1; } else if (this.rigid.linearVelocity.x < -o) { this.zombie_view.node.scaleX = 1; } } } attack(target) { if (this.zombie_prop.zombie_ID == 56) { Log.log(LOG_TAG.DEBUG, '生成怪物攻击'); this.zombie_view.playAttack(this.attackCb); this.scheduleOnce(() => { gameEventManager.emit(EVENT_TYPE.BOSS_SKIN_ADDZOMBIE, 3, this.node) }, 0.2); } else if (this.zombie_prop.zombie_ID == 53) { Log.log(LOG_TAG.DEBUG, '子弹攻击'); this.zombie_view.playAttack(this.attackCb); this.scheduleOnce(() => { gameEventManager.emit(EVENT_TYPE.zombie_boom, this.node.position, target.position, 3, this.zombie_prop.base_damage) }, 0.2); } else if (this.zombie_prop.zombie_ID == 46) { Log.log(LOG_TAG.DEBUG, '子弹攻击'); this.zombie_view.playAttack(this.attackCb); this.scheduleOnce(() => { gameEventManager.emit(EVENT_TYPE.zombie_boom, cc.v3(this.node.x, this.node.y - 200), target.position, 1, this.zombie_prop.base_damage) }, 0.2); } else { Log.log(LOG_TAG.DEBUG, '普通攻击'); this.canWalk = false; let ts = this.getAliiCloseTargets(this.roles[0], this.zombie_prop.hand_range); this.zombie_view.playAttack(this.attackCb); this.scheduleOnce(() => { for (let t of ts) { if (!t || !cc.isValid(t)) { break; } let comp = t.getComponent(PlayerObject); if (comp.isDie) { break; } let bDie = this.zombie_prop.attack(comp, this.zombie_prop.base_damage); if (bDie) { //目标死亡 comp.die(); } else { let curWeapon = comp.player_prop.cur_weapon; let id = curWeapon ? curWeapon.id : null; comp.player_view.playBeHurt(id); } } }, 0.5) } } /**范围内最近目标 */ private getCloseTarget(nds: cc.Node[], range: number): cc.Node { let target: cc.Node = null; for (let nd of nds) { if (!nd.isValid) { continue; } let len = nd.position.sub(this.node.position).mag(); if (len < range) { range = len; target = nd; } } return target; } /**范围内所有目标 */ private getAliiCloseTargets(nds: cc.Node[], range: number): cc.Node[] { let targets: cc.Node[] = []; for (let nd of nds) { if (!nd.isValid) { continue; } let len = nd.position.sub(this.node.position).mag(); if (len < range) { targets.push(nd); } } return targets; } /**向目标移动 * @param target 目标 */ private moveToTarget(target: cc.Node) { let v_sub = target.position.sub(this.node.position).normalize(); let rad = Math.acos(v_sub.x); if (v_sub.y < 0) { rad = Math.PI * 2 - rad; } this.setLinearVelocity(rad); } /**设置刚体线性速度 * @param rad 弧度角 */ private setLinearVelocity(rad: number) { this.rigid.linearVelocity = cc.v2(Math.cos(rad), Math.sin(rad)).mul(this.speed); } }