//查找一定范围内的敌人 public List <BattleUnit> SearchBattleUnits(GridUnit centerGridUnit, int range) { List <BattleUnit> battleUnits = new List <BattleUnit>(); BattleMap battleMap = centerGridUnit.battleMap; bool[,] flag = new bool[battleMap.mapWidth, battleMap.mapHeight]; flag[centerGridUnit.column, centerGridUnit.row] = true; Queue <GridUnit> checkList = new Queue <GridUnit>(); GridUnit currentUnit = centerGridUnit; checkList.Enqueue(currentUnit); while (checkList.Count > 0) { currentUnit = checkList.Dequeue(); List <GridUnit> gridUnitList = battleMap.GetNearbyGrid(currentUnit); foreach (GridUnit gridUnit in gridUnitList) { if (range < centerGridUnit.Distance(gridUnit)) { continue; } if (!flag[gridUnit.column, gridUnit.row]) { flag[gridUnit.column, gridUnit.row] = true; if (gridUnit.battleUnit != null) { battleUnits.Add(gridUnit.battleUnit); } checkList.Enqueue(gridUnit); } } } return(battleUnits); }
//使用技能 public void UseSkill(SO_BattleSkill battleSkill, BattleUnit targetBattleUnit = null, GridUnit targetGridUnit = null) { if (battleSkill == null) { UtilityHelper.LogError("Use skill error. Battle skill is none."); return; } GridUnit temp = targetGridUnit; if (temp == null && targetBattleUnit != null) { temp = targetBattleUnit.mapGrid; } if (temp != null && mapGrid.Distance(temp) > battleSkill.GetReleaseRadius(mapGrid)) { return; } BattleSkillEffectAnalysis analysis = BattleCalculator.Instance.AnalyseBattleSkillEffect(battleSkill, this, targetBattleUnit, targetGridUnit); if (analysis == null) { UtilityHelper.LogError("Use skill error. Analysis failed:" + battleSkill.skillName); return; } skillResults.Clear(); //主要影响 for (int i = 0; i < analysis.mainReceiver.Count; ++i) { skillResults.Add(BattleCalculator.Instance.CalcSingle(this, analysis.mainReceiver[i], battleSkill, true)); } //次要影响 for (int i = 0; i < analysis.minorReceiver.Count; ++i) { skillResults.Add(BattleCalculator.Instance.CalcSingle(this, analysis.minorReceiver[i], battleSkill, false)); } //连招combo统计 if (battleUnitAttribute.manualOperation) { UtilityHelper.Log("Check combo now"); //返回真表示连招成立,则调用连招效果 int comboID = battleUnitAttribute.comboJudge((int)battleSkill.damageType); if (comboID != -1) { //对于即时生效的技能需要直接改变skillResult ComboEffect(comboID, battleUnitAttribute); } } //产生使用技能的动作 BattleUnitSkillAction skillAction = BattleUnitActionEvent.CreateEvent <BattleUnitSkillAction>(BattleUnitActionType.UseSkill, this); skillAction.battleSkill = battleSkill; skillAction.skillResult = skillResults.ToArray(); skillAction.targetBattleUnit = targetBattleUnit; skillAction.targetGrid = targetGridUnit; skillAction.selfAttribute = BattleSkillCostEnergy(battleSkill); battleField.AppendBattleAction(skillAction); //伤害产生效果,计算仇恨 for (int i = 0; i < skillResults.Count; ++i) { //接收伤害,属性变更 skillResults[i].battleUnit.AcceptSkillResult(skillResults[i].syncAttribute); //产生仇恨 if (battleSkill.damageType != BattleSkillDamageType.Heal && !skillResults[i].battleUnit.Equals(this)) { //新仇记录 for (int j = 0; j < enemyTeam.battleUnits.Count; ++j) { if (!enemyTeam.battleUnits[j].CanAction) { continue; } //每个战斗单位都需要知道发生了什么 if (!enemyTeam.battleUnits[j].battleUnitAttribute.manualOperation) { enemyTeam.battleUnits[j].battleBehaviourSystem.RecordSkillResult(this, skillResults[i]); } } } } }
//点击了地块、战斗单位 -- 在当前是选择移动目标的情况下 private void OnBattleUnitAndGridTouched_StateMove(GridUnit gridTouched, BattleUnit battleUnitTouched) { //点中了战斗单位 if (battleUnitTouched != null) { //显示战斗单位的详情 UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } //点中了地图 else { //障碍物不能作为移动目标(暂时) if (gridTouched.GridType == GridType.Obstacle) { UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } else { //点击是否超出了范围 GridUnit fromGrid = manualOperatingBattleUnitRenderer.battleUnit.mapGrid; if (fromGrid.Distance(gridTouched) > manualOperatingBattleUnitRenderer.battleUnit.battleUnitAttribute.mobility) { UtilityHelper.Log("超出了移动半径!"); UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } else { MapNavigator.Instance.NewNavigate( manualOperatingBattleUnitRenderer.battleUnit, fieldRenderer.battleField.battleMap, fromGrid, gridTouched, UtilityObjs.gridUnits); //判断移动是否可以到达 //bool result = MapNavigator.Instance.Navigate( // fieldRenderer.battleField.battleMap, // fromGrid, // gridTouched, // UtilityObjs.gridUnits, // null, // manualOperatingBattleUnitRenderer.battleUnit.battleUnitAttribute.mobility // ); bool result = MapNavigator.Instance.NewNavigate( manualOperatingBattleUnitRenderer.battleUnit, fieldRenderer.battleField.battleMap, fromGrid, gridTouched, UtilityObjs.gridUnits); //判断是否可以到达(导航成功且可以可以到达) if (result && UtilityObjs.gridUnits[UtilityObjs.gridUnits.Count - 1].Equals(gridTouched)) { //可以到达 ManualMoveTo(gridTouched, UtilityObjs.gridUnits.ToArray()); UtilityObjs.gridUnits.Clear(); } else { //不可以到达 UtilityHelper.Log("点击位置不可到达!"); UIViewManager.Instance.ShowView(UIViewName.BattleFieldUnitInfo, gridTouched, battleUnitTouched); } } } } }
/// <summary> /// 导航至某个位置 /// </summary> /// <returns>The navigate.</returns> /// <param name="battleMap">地图</param> /// <param name="from">起始格子</param> /// <param name="to">目标格子</param> /// <param name="path">保存导航路径</param> /// <param name="searched">搜索过的路径</param> /// <param name="mobility">步数限制(移动区域半径)</param> /// <param name="stopDistance">距离目标的停止距离</param> /// <param name="containsTargetGrid">路径是否包含目标</param> public bool Navigate( BattleMap battleMap, GridUnit from, GridUnit to, List <GridUnit> path, List <GridUnit> searched = null, int mobility = -1, int stopDistance = 0) { //没有设置地图 if (battleMap == null) { return(false); } if (path != null) { path.Clear(); } if (searched != null) { searched.Clear(); } //这种情况基本上也就不用寻路了吧... if (to.runtimePasses == 0 && stopDistance <= 1 && from.Distance(to) > 1) { return(false); } //本来就在停止距离内 if (from.Distance(to) <= stopDistance) { return(true); } int tryTimes = battleMap.GridCount; List <NavigationData> opening = new List <NavigationData>(); opening.Add(GetEmptyNavigationData(from, null, 0, from.Distance(to))); int retry = 0; bool catched = false; //当前探索方向 int curDir = 0; //上次探索方向 int lastDir = 0; //每次检测方向的次数 int checkTimes = 0; //判断是否需要遍历open列表 NavigationData gift = null; //距离最近的格子(接下来要移动的) NavigationData next_0 = null; //距离次近的格子 NavigationData next_1 = null; int minStep = EGameConstL.Infinity; while (retry <= tryTimes && !catched) { ++retry; //从open中查找最近的节点 if (gift != null) { next_0 = gift; gift = null; } else if (next_1 != null) { next_0 = next_1; next_1 = null; } else { minStep = EGameConstL.Infinity; if (opening.Count == 0) { break; } for (int i = opening.Count - 1; i >= 0; --i) { if (!opening[i].open) { opening.RemoveAt(i); } else if (opening[i].F < minStep) { next_0 = opening[i]; minStep = next_0.F; } else if (next_1 == null && next_0 != null && opening[i].F == next_0.F) { next_1 = opening[i]; } } } //标志为已关闭 next_0.open = false; //放入已搜索中 if (searched != null) { searched.Add(next_0.thisGrid); } checkTimes = 6; curDir = lastDir; //遍历最近节点的周围6个节点,依次放入close中 int roads = next_0.thisGrid.NavigationPassable ? 63 : next_0.thisGrid.roadPasses; while (checkTimes > 0) { //沿着当前探索方向继续探索 if ((roads & (1 << curDir)) != 0) { //获取该路通向的下一个item GridUnit sibling = battleMap.GetGridByDir(next_0.thisGrid.row, next_0.thisGrid.column, curDir); if (sibling == null) { //没路 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个不能移动 else if (sibling.GridType == GridType.Obstacle && !sibling.NavigationPassable) { //没路 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个格子有战斗单位且可以战斗 else if (sibling.battleUnit != null && sibling.battleUnit.CanAction && !sibling.NavigationPassable) { //无法通过 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个item就是目标或者已经进入了停止距离 else if ((stopDistance > 0 && sibling.Distance(to) <= stopDistance) || sibling.Equals(to)) { catched = true; if (path != null) { path.Add(sibling); NavigationData current = next_0; while (current != null) { if (current.thisGrid != from) { path.Add(current.thisGrid); } current = current.preGrid; } //翻转一下 path.Reverse(); } break; } else { //尝试判断这个是否为closed NavigationData nd = sibling.tempRef == null ? null : (NavigationData)(sibling.tempRef); if (nd == null) { //这个格子没有探索过,新建并添加 nd = GetEmptyNavigationData(sibling, next_0, next_0.G + 1, sibling.Distance(to)); //这个格子不错哦 if (nd.F <= next_0.F && gift == null) { //保存礼物 gift = nd; //记录下次起始的更新方向 lastDir = curDir; } //比第二目标好 else if (next_1 != null && nd.F < next_1.F) { //替换第二目标 next_1 = nd; opening.Add(nd); } else { //已经设置了礼物,因此只能放入opening列表中,以后再更新了呢 opening.Add(nd); } } else { //只处理没有被探索过的格子 if (nd.open) { //已经在Open列表中了 if ((next_0.G + 1) < nd.G) { //比原来的近,应该不可能 nd.G = next_0.G + 1; nd.H = sibling.Distance(to); nd.F = nd.G + nd.H; nd.preGrid = next_0; nd.thisGrid = sibling; } //这个格子不错哦 if (nd.F <= next_0.F && gift == null) { gift = nd; //保存当前探索方向 lastDir = curDir; } else if (next_1 != null && nd.F < next_1.F) { //替换第二目标 next_1 = nd; } } } } } ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; } } opening.Clear(); //重置池子 ResetPool(); //有步数限制 if (catched && path != null && mobility > 0) { for (int i = 0; i < path.Count; ++i) { if (path[i].Distance(from) > mobility) { path.RemoveRange(i, path.Count - i); break; } } } return(catched); }