local BattleConst = require "app/module/battle/battle_const" local BattleUnitComp = class("BattleUnitComp", LuaComponent) local UNIT_STATE = BattleConst.UNIT_STATE local SIDE_ATK = BattleConst.SIDE_ATK local SPINE_ANIMATION_NAME = BattleConst.SPINE_ANIMATION_NAME function BattleUnitComp:ctor() end function BattleUnitComp:initPosition() if self.unitEntity:getSide() == SIDE_ATK then self.baseObject:setLocalPosition(-BattleConst.INIT_POS_X, 0, 0) self.body:setLocalScaleX(1) self.direction = 1 else self.baseObject:setLocalPosition(BattleConst.INIT_POS_X, 0, 0) self.body:setLocalScaleX(-1) self.direction = -1 end end function BattleUnitComp:playBorn() self:playAnimation(SPINE_ANIMATION_NAME.IDLE, true, false) end function BattleUnitComp:_initBase() self.isClear = false self.isDead = false self.isMove = false self.attackTime = 0 self.currAttackDuration = 0 self.currAttackKeyTime = 0 self.isPlayHurt = 0 self.attackDurationMap = {} self.currState = UNIT_STATE.INIT end function BattleUnitComp:initWithEntity(modelId, entity, battleController, target) self.modelId = modelId self.unitEntity = entity self.battleController = battleController self.target = target self.body = self.baseObject:getChildByName("body") self.side = entity:getSide() self:_initBase() self:initPosition() self:playBorn() end function BattleUnitComp:hideOutsideScreen() if self.unitEntity:getSide() == SIDE_ATK then self.baseObject:setLocalPosition(-GConst.UI_SCREEN_WIDTH/2 - BattleConst.UNIT_BODY_WIDTH, 0, 0) else self.baseObject:setLocalPosition(GConst.UI_SCREEN_WIDTH/2 + BattleConst.UNIT_BODY_WIDTH, 0, 0) end end function BattleUnitComp:playAnimation(name, loop, forceRefresh) self.currAnimationName = name self.baseObject:playAnimation(name, loop, forceRefresh) end function BattleUnitComp:getAnimationDuration(aniName) local duration = self.attackDurationMap[aniName] if duration == nil then duration = self.baseObject:getAnimationDuration(aniName) self.attackDurationMap[aniName] = duration end return duration or 0 end function BattleUnitComp:useNormalSkill(count, callback) self.actionOverCallback = callback self.normalSkillCount = count if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then self.actionOverCallback = nil callback() end end function BattleUnitComp:changeState(state) if self.currState == state and not self:repeatCurrState() then return false end if self.isDead then -- 死亡后只能去死亡状态 if state ~= UNIT_STATE.DEAD then return false end end -- 离开当前状态 if self.currState == UNIT_STATE.IDLE then self:exitIdleState() elseif self.currState == UNIT_STATE.NORMAL_ATTACK then self:exitNormalAttackState() elseif self.currState == UNIT_STATE.SKILL then self:exitSkillState() elseif self.currState == UNIT_STATE.DEAD then self:exitDeadState() end -- 进入目标状态 self.currState = state if state == UNIT_STATE.IDLE then self:enterIdleState() elseif state == UNIT_STATE.NORMAL_ATTACK then self:enterNormalAttackState() elseif state == UNIT_STATE.SKILL then self:enterSkillState() elseif state == UNIT_STATE.DEAD then self:enterDeadState() elseif self.currState == UNIT_STATE.BORN then self:enterBornState() end return true end function BattleUnitComp:repeatCurrState() if self.currState == UNIT_STATE.IDLE then return false elseif self.currState == UNIT_STATE.NORMAL_ATTACK then return true elseif self.currState == UNIT_STATE.SKILL then return true elseif self.currState == UNIT_STATE.DEAD then return false end return false end function BattleUnitComp:exitIdleState() end function BattleUnitComp:enterIdleState() self:playAnimation(SPINE_ANIMATION_NAME.IDLE, true, false) end function BattleUnitComp:updateIdle(dt) self:updateHurt(dt) end function BattleUnitComp:updateHurt(dt) if self.isPlayHurt == 0 then return end if self.isPlayHurt == 1 then self.hurtTime = self.hurtTime + dt if self.hurtTime >= self.currHitDuration then self:playAnimation(SPINE_ANIMATION_NAME.IDLE, true, false) self.isPlayHurt = 0 end elseif self.isPlayHurt == 2 then self.hurtTime = self.hurtTime + dt if self.hurtTime >= self.currHitGroundDuration then self.isPlayHurt = 0 end end end function BattleUnitComp:enterNormalAttackState() self.attackOver = false self.attackTime = 0 self.currAttackKeyTime = 0.1 local skill = self.unitEntity:getNormalSkill() if skill:getMoveType() == BattleConst.SKILL_MOVE_TYPE.MOVE then self.isMove = true self.positionX = self.baseObject:fastGetLocalPosition() if self.side == BattleConst.SIDE_ATK then self.targetX = BattleConst.UNIT_FRONT_POS_X self.moveDirection = 1 else self.targetX = -BattleConst.UNIT_FRONT_POS_X self.moveDirection = -1 end else self.isMove = false local attackName = skill:getRandomNormalAttackName() self.currAttackDuration = self:getAnimationDuration(attackName) self:playAnimation(attackName, false, false) end end function BattleUnitComp:exitNormalAttackState() end function BattleUnitComp:updateNormalAttack(dt) if self.isMove then local addX = dt*BattleConst.MOVE_SPEED*self.moveDirection self.positionX = self.positionX + addX if (self.moveDirection > 0 and self.positionX >= self.targetX) or (self.moveDirection < 0 and self.positionX <= self.targetX) then self.isMove = false self.positionX = self.targetX if self.attackOver then -- 归位后该下一步了 self:changeState(UNIT_STATE.IDLE) local callback = self.actionOverCallback self.actionOverCallback = nil if callback then callback() end else -- 到位置该攻击了 self:playAnimation(SPINE_ANIMATION_NAME.ATTACK, false, false) end end self.baseObject:setLocalPosition(self.positionX, 0, 0) return end self.attackTime = self.attackTime + dt if self.attackTime >= self.currAttackDuration then self.attackOver = true self.normalSkillCount = self.normalSkillCount - 1 if self.normalSkillCount <= 0 then local skill = self.unitEntity:getNormalSkill() if skill:getMoveType() == BattleConst.SKILL_MOVE_TYPE.MOVE then self.isMove = true self.positionX = self.baseObject:fastGetLocalPosition() if self.side == BattleConst.SIDE_ATK then self.targetX = -BattleConst.INIT_POS_X self.moveDirection = -1 else self.targetX = BattleConst.INIT_POS_X self.moveDirection = 1 end else self:changeState(UNIT_STATE.IDLE) local callback = self.actionOverCallback self.actionOverCallback = nil if callback then callback() end end return else -- 继续攻击 self.attackTime = 0 self:playAnimation(SPINE_ANIMATION_NAME.ATTACK, false, false) end end if self.currAttackKeyTime > 0 and self.attackTime >= self.currAttackKeyTime then -- 到达关键后使用 self.currAttackKeyTime = self.currAttackDuration end end function BattleUnitComp:tick(dt) if self.isClear then return end if self.isDead then self:updateDead(dt) return end if self.currState == UNIT_STATE.IDLE then self:updateIdle(dt) return end if self.currState == UNIT_STATE.NORMAL_ATTACK then self:updateNormalAttack(dt) elseif self.currState == UNIT_STATE.SKILL then self:updateSkill(dt) end end return BattleUnitComp