/// <summary> /// 开始回放 /// </summary> /// <param name="vo"></param> public static void StartReplay(BattleReplayVO vo) { #if UNITY_EDITOR BattleManager.logClear(); #endif // UNITY_EDITOR BattleManager.Instance.BattleStartTime = DateTimeUtil.UnixTimestampMSToDateTime(vo.battleStartTime); _recordData = vo; _operation.Clear(); // REMARK:把List转换为LinkedList,提高remove的效率。 foreach (var op in vo.battleInputs) { _operation.AddLast(new OpPlaceSoldier() { frame = op.frame, operationId = op.battleOperationType, x = op.battleOperationPlaceSoldierVO.x, y = op.battleOperationPlaceSoldierVO.y, soldierId = op.battleOperationPlaceSoldierVO.cid }); } // 设置随机数种子(TODO:类型不一致) BattleRandom.SetSeed((int)vo.seed); // 从0帧开始 _frame = 0; _battleEnded = false; }
/// <summary> /// 从建筑区域随机获取一个移动格子(REMARK:如果当前目标已经在建筑区域内,则根据距离作为权重随机获取,否则直接随机获取。) /// </summary> /// <param name="inBuildArea"></param> /// <returns></returns> private TilePoint RandomMoveGrid(bool inBuildArea) { if (inBuildArea) { if (_buildArea.Count == 1) { return(_buildArea[0]); } else { // 权重算法:距离越大(权重越低、距离越近权重越高、距离0跳过) int maxDis = _buildArea.Count - 1; List <TilePoint> randomList = new List <TilePoint>(); TilePoint selfPos = Entity.GetTilePos(); foreach (var grid in _buildArea) { int dis = Mathf.Abs(selfPos.x - grid.x) + Mathf.Abs(selfPos.y - grid.y); if (dis > 0) { int weight = maxDis + 1 - dis; for (int i = 0; i < weight; i++) { randomList.Add(grid); } } } return(randomList[BattleRandom.Range(0, randomList.Count)]); } } else { return(_buildArea[BattleRandom.Range(0, _buildArea.Count)]); } }
/// <summary> /// 从目标列表里根据距离时间等权重筛选最有目标 /// </summary> /// <param name="targeters"></param> /// <param name="_targetPos"></param> /// <param name="_targetRoute"></param> /// <returns></returns> private List <TileEntity> SelectTargeters(List <TileEntity> targeters, out TilePoint?_targetPos, out LinkedList <IMoveGrid> _targetRoute) { _targetPos = null; _targetRoute = null; // 先在监视范围内寻找时间消耗最低的目标 IsoGridTarget targetInfos = FindTargetsNearestTimeCost(Attacker, targeters); if (targetInfos != null) { Assert.Should(targetInfos.MoveRoute != null); if (targetInfos.MoveRoute.Count > 1) { _targetRoute = targetInfos.MoveRoute; } return(AuxConvertToList(targetInfos.Targeter)); } // 未找到则直接寻找直线最近的目标 var nearest_targets = FindTargetsNearestLinear(Attacker.GetCurrentPositionCenter(), targeters, 1); var targeter = nearest_targets[0]; Vector2 p = targeter.GetCurrentPositionCenter(); //int randomOffset = Mathf.Min((int)(targeter.blockingRange / 2.0f + Attacker.model.range), targeter.width / 2); // TODO:如果该值过大导致移动结束后目标不在攻击范围内(则会导致重新锁定目标) 则需要酌情调整该值算法 int randomOffset = Mathf.Min((int)Attacker.model.range, targeter.width / 2); int x = (int)p.x; int y = (int)p.y; if (randomOffset > 0) { x = BattleRandom.Range(x - randomOffset, x + randomOffset); y = BattleRandom.Range(y - randomOffset, y + randomOffset); } _targetPos = new TilePoint(x, y); return(nearest_targets); }
protected override void DoActionIdle() { //m_tempTargeters = null; //Entity.State = EntityStateType.Idle; //m_timePassed = BattleRandom.Range(3f, 10f); AuxRecycleAllBulletLoopEffect(); m_tempTargeters = null; Entity.State = EntityStateType.Idle; m_timePassed = BattleRandom.Range(0.5f, 1.5f); #if UNITY_EDITOR BattleManager.logWaitTime.Add(GameRecord.Frame + ":timePassed:" + m_timePassed); #endif // UNITY_EDITOR if (Entity.AimTarget) { // 背向地图中央 var center = new Vector2(Constants.WIDTH / 2, Constants.HEIGHT / 2); var dir = Entity.GetCurrentPositionCenter() - center; var angle = MathUtil2D.GetAngleFromVector(IsoHelper.TileDirectionToScreenDirection(dir)); Entity.PlayAnimationAtScreenAngle(AnimationNames.Stand, BattleRandom.Range(angle - 45, angle + 45)); } else { Entity.PlayAnimation(AnimationNames.Stand); } }
/// <summary> /// 执行行动-发呆 /// </summary> protected virtual void DoActionIdle() { AuxRecycleAllBulletLoopEffect(); m_tempTargeters = null; Entity.State = EntityStateType.Idle; m_timePassed = BattleRandom.Range(0.5f, 1.5f); Entity.PlayAnimation(AnimationNames.Stand); }
/// <summary> /// [回调] 子弹命中目标 或 子弹命中目标点 /// </summary> /// <param name="bullet"></param> private void OnBulletHitted(GameBullet bullet) { // TODO:如果子弹命中回调时自身已经挂了的情况是否需要考虑?? //if (this.Entity.IsDead()) // return; Vector2 hitPos = Vector2.zero; float randomRadius = 0.0f; switch (bullet.bulletType) { case EntityBulletType.Point: // 对地点伤害 { Assert.Should(bullet.targetEntity == null); ProcessDamagePoint(bullet.targetPosition); hitPos = bullet.targetPosition; randomRadius = 0.3f; // REMARK:打目标点的按照半格计算 } break; case EntityBulletType.Target: // 对目标伤害 { Assert.Should(bullet.targetEntity != null); if (Entity.model.splashRange > 0) { ProcessDamagePoint(bullet.targetEntity.GetCurrentPositionCenter()); } else { GameDamageManager.ProcessDamageOneTargeter(bullet.targetEntity, Entity.model, Entity); } hitPos = bullet.targetEntity.GetCurrentPositionCenter(); randomRadius = Mathf.Max(0.3f, bullet.targetEntity.blockingRange / 6.0f); } break; default: Assert.Should(false, "invalid bullet type..."); break; } // 命中效果(范围内随机设置个命中点) if (randomRadius > 0) { hitPos.x = BattleRandom.Range(hitPos.x - randomRadius, hitPos.x + randomRadius); hitPos.y = BattleRandom.Range(hitPos.y - randomRadius, hitPos.y + randomRadius); } GameEffectManager.Instance.AddEffect(Entity.model.hitEffectName, new Vector3(hitPos.x, 0, hitPos.y)); }
/// <summary> /// 开始录像 /// </summary> /// <param name="attacker"></param> /// <param name="defender"></param> public static void StartRecord() { #if UNITY_EDITOR BattleManager.logClear(); #endif // UNITY_EDITOR BattleManager.Instance.BattleStartTime = ServerTime.Instance.Now(); _battleEnded = false; _frame = 0; _recordData = new BattleReplayVO() { seed = BattleRandom.Range(0, 0xffff), battleStartTime = DateTimeUtil.DateTimeToUnixTimestampMS(BattleManager.Instance.BattleStartTime), }; BattleRandom.SetSeed((int)_recordData.seed); }
private void DoActionBuild() { Entity.State = EntityStateType.Attacking; var dir = Entity.GetDir8FromTargeter(_buildTargeter); //工人只有攻击右上动画 if (dir == EntityDirection.Right) { dir = EntityDirection.TopRight; } else if (dir == EntityDirection.Left) { dir = EntityDirection.TopLeft; } Entity.PlayAnimationAtDir8(AnimationNames.Attack, dir); m_timePassed = BattleRandom.Range(1.0f, 3.5f); }
private TilePoint RandomGrid() { float mindiff = Mathf.Max(Entity.model.speed * 2.0f, 1.5f); float mindiff2 = mindiff * mindiff; List <TilePoint> recommendedGrids = new List <TilePoint>(); foreach (var grid in m_passableGrids) { float diff2 = Entity.DistanceSquareTo(grid.x, grid.y); if (diff2 >= mindiff2) { recommendedGrids.Add(grid); } } if (recommendedGrids.Count > 0) { return(recommendedGrids[BattleRandom.Range(0, recommendedGrids.Count)]); } else { return(m_passableGrids[BattleRandom.Range(0, m_passableGrids.Count)]); } }
private void DoActionIdle(float min = 0.5f, float max = 1.5f) { Entity.State = EntityStateType.Idle; m_timePassed = BattleRandom.Range(min, max); Entity.PlayAnimation(AnimationNames.Stand); }