public readonly UnitType unitTypeBuild; // Nullable

        #endregion Fields

        #region Constructors

        public Order(OrderType orderType, Position targetPosition=null, Unit targetUnit=null, UnitType unitTypeBuild=null)
        {
            this.orderType = orderType;
            this.targetPosition = targetPosition;
            this.targetUnit = targetUnit;
            this.unitTypeBuild = unitTypeBuild;
        }
 public static Position FindNextStep( Engine engine, Unit unit, Tile start, Tile end )
 {
     List<Position> temp = FindPath(engine, unit, start, end);
     if (temp != null && temp.Count > 1)
         return temp[1];
     else
         return null;
 }
        public Unit NearestUnitTo(Unit startUnit, int maxDistance, Position startPosition=null)
        {
            if (startPosition == null)
            {
                startPosition = startUnit.position;
            }
            if (!Inside(startPosition))
            {
                var nearestPosition = new Position(Math.Max(0, Math.Min(startPosition.x, width - 1)),
                    Math.Max(0, Math.Min(startPosition.y, height - 1)));
                maxDistance -= nearestPosition.Distance(startPosition);
                startPosition = nearestPosition;
            }

            Chunk chunk = GetChunk(startPosition);

            // Breadth first search
            HashSet<Chunk> haveBeenInFrontier = new HashSet<Chunk> {chunk};
            LinkedList<Chunk> frontier = new LinkedList<Chunk>(haveBeenInFrontier);
            while (frontier.Count > 0)
            {
                var top = frontier.First();
                frontier.RemoveFirst();
                // Try to find nearest in this chunk
                Unit closestUnit = null;
                int nearestDistance = Int32.MaxValue;
                foreach (var unit in top.units)
                {
                    int distance = startPosition.Distance(unit.position);
                    if (distance <= nearestDistance && unit != startUnit)
                    {
                        nearestDistance = distance;
                        closestUnit = unit;
                    }
                }
                if (closestUnit != null && nearestDistance <= maxDistance)
                {
                    return closestUnit;
                }
                // if a unit has not been found yet, try the neighbors
                foreach (var neighbor in top.neighbors)
                {
                    if (!haveBeenInFrontier.Contains(neighbor) && neighbor.GetDistanceFrom(startPosition) <= maxDistance)
                    {
                        frontier.AddLast(neighbor);
                        haveBeenInFrontier.Add(neighbor);
                    }
                }
            }
            return null; // Didn't find a unit within maxDistance
        }
 public void OrderProduce(Unit factory, UnitType unitType, Position targetPosition = null)
 {
     factory.orders.Add(Order.CreateProduceOrder(unitType, targetPosition));
     ScheduleUpdate(1, factory);
 }
 public void OrderGather(Unit gatherer, Position target)
 {
     gatherer.orders.Add(Order.CreateGatherOrder(target));
     ScheduleUpdate(1, gatherer);
 }
 public void OrderMove(Unit unit, Position targetPosition)
 {
     unit.orders.Add(Order.CreateMoveOrder(targetPosition));
     ScheduleUpdate(1, unit);
 }
        // Kinda private methods
        public void MoveUnit(Unit unit, Position targetPosition)
        {
            Debug.Assert(targetPosition.Distance(unit.position) == 1);
            Debug.Assert(unitGrid[targetPosition.x, targetPosition.y] == null);

            CacheRemoveUnitAt(unit.position);
            unit.previousPosition = unit.position;
            unit.position = targetPosition;
            unit.animationStartTick = currentTick;
            CacheSetUnitAt(unit);
        }
 public void OrderAttack(Unit attacker, Unit target)
 {
     attacker.orders.Add(Order.CreateAttackOrder(target));
     ScheduleUpdate(1, attacker);
 }
 public static Order CreateAttackOrder(Unit target)
 {
     Debug.Assert(target != null);
     return new Order(OrderType.Attack, targetUnit: target, targetPosition: target.position);
 }
 public Unit FindNearestEnemy(Unit unit, int maxDistance)
 {
     Unit nearestEnemy = null;
     int nearestDistance = int.MaxValue;
     foreach (var player in players)
     {
         if (player.team != unit.owner.team)
         {
             Unit nearUnit = unitQuadtrees[player].NearestUnitTo(unit, maxDistance);
             if (nearUnit != null)
             {
                 int distance = nearUnit.position.Distance(unit.position);
                 if (nearestEnemy == null || distance < nearestDistance)
                 {
                     nearestEnemy = nearUnit;
                     nearestDistance = distance;
                 }
             }
         }
     }
     return nearestEnemy;
 }
        public void SwapUnits(Unit a, Unit b)
        {
            Debug.Assert(a.position.Distance(b.position) == 1);

            var targetPosition = b.position;
            // Remove a
            CacheRemoveUnitAt(a.position);
            // Tell b to move into a's spot
            Debug.Assert(b.orders.Count == 0, "Swap: b still had orders left.");
            b.orders.Add(Order.CreateMoveOrder(a.position));
            b.Update(); // This will force the unit to wait the appropriate amount of time before moving back
            // Debug.Assert(b.position.Equals(a.position), "Swap: b did not move back to original position.");
            // Add a to b's old position
            a.previousPosition = a.position;
            a.position = targetPosition;
            a.animationStartTick = currentTick;
            CacheSetUnitAt(a);
            // Give an order to b to go back to his original position
            OrderMove(b, targetPosition);
        }
        public Unit AddUnit(UnitType unitType, Position position, Player owner)
        {
            if (!map.Inside(position)) return null;

            var newUnit = new Unit(GetNextId(), this, unitType, position, owner);
            units.Add(newUnit);
            unitQuadtrees[owner].AddUnit(newUnit);
            CacheSetUnitAt(newUnit);
            return newUnit;
        }
 public void AddUnit(Unit unit)
 {
     var chunk = GetChunk(unit.position);
     if (chunk != null) chunk.AddUnit(unit);
     previousUnitPositions[unit] = new Position(unit.position);
 }
 public void RemoveUpdate(Unit unit)
 {
     if (!futureUpdates.ContainsKey(unit.nextMove))
     {
         return;
     }
     if( futureUpdates[unit.nextMove].Contains(unit))
     {
         if (unit.nextMove != currentTick) // Don't remove from the current update list because WE ARE ITERATING OVER IT
         {
             futureUpdates[unit.nextMove].Remove(unit);
         }
     }
 }
 public void RemoveUnit(Unit unit)
 {
     units.Remove(unit);
 }
 public bool Contains(Unit unit)
 {
     return units.Contains(unit);
 }
 public void AddUnit(Unit unit)
 {
     Debug.Assert(Inside(unit.position));
     units.Add(unit);
 }
        public void UpdateUnit(Unit unit)
        {
            // It is an error to call this when unit was never added to the quadtree
            Debug.Assert(previousUnitPositions.ContainsKey(unit));

            Position previousPosition = previousUnitPositions[unit];
            var previousChunk = GetChunk(previousPosition);
            var newChunk = GetChunk(unit.position);
            if (previousChunk != newChunk)
            {
                if (previousChunk != null) previousChunk.RemoveUnit(unit);
                if (newChunk != null) newChunk.AddUnit(unit);
            }

            previousUnitPositions[unit] = unit.position;
        }
        public void RemoveUnit(Unit unit)
        {
            // It is an error to call this when unit was never added to the quadtree
            Debug.Assert(previousUnitPositions.ContainsKey(unit));

            GetChunk(previousUnitPositions[unit]).RemoveUnit(unit);
            previousUnitPositions.Remove(unit);
        }
        public void ScheduleUpdate(int ticksFromNow, Unit unit)
        {
            if (unit.nextMove < currentTick + (inTick ? 1 : 0))
            {
                if (!futureUpdates.ContainsKey(currentTick + ticksFromNow))
                {
                    futureUpdates[currentTick + ticksFromNow] = new List<Unit>();
                }

                futureUpdates[currentTick + ticksFromNow].Add(unit);
                unit.nextMove = currentTick + ticksFromNow;
            }
        }
 public static Position FindNextStep( Engine engine, Unit unit, Position start, Position end)
 {
     return FindNextStep(engine, unit, engine.map.GetTileAt(start), engine.map.GetTileAt(end));
 }
 private void CacheSetUnitAt(Unit unit)
 {
     Debug.Assert(unit != null);
     if (map.Inside(unit.position))
     {
         unitGrid[unit.position.x, unit.position.y] = unit;
         unitQuadtrees[unit.owner].UpdateUnit(unit);
     }
 }
        public static List<Position> FindPath( Engine engine, Unit unit, Tile start, Tile end )
        {
            List<Position> path = null;

            if (!unit.CanMove(end.position))
            {
                foreach (Position pos in BreadthFirst(engine, end.position, -1, 500))
                {
                    if (unit.CanMove(pos))
                    {
                        end = engine.map.tiles[pos.x, pos.y];
                        break;
                    }
                }
            }
            if (!unit.CanMove(end.position))
            {
                return null;
            }

            bool success = false;
            start.pathParent = null;
            start.pathDistance = 0;
            start.pathHeuristic = start.pathDistance + FValue(start, end);
            PriorityQueue<Tile> openSet = new PriorityQueue<Tile>();
            openSet.Enqueue(start);
            int count = 0;

            //generate path
            while ( openSet.Count() > 0 )
            {
                count += 1;
                Tile currentBest = openSet.Dequeue();
                currentBest.pathIndex = pathCounter;
                // if we are at the goal end
                if (currentBest.position.Equals(end.position))
                {
                    success = true;
                    break;
                }
                // Give up if we backtrack too far
                if ((currentBest.pathHeuristic >= start.pathHeuristic*14 &&
                    count > 2000) || count > 4000)
                {
                    break;
                }
                // Take current best, generate all possible nodes, push them onto queue
                foreach (var neighbor in currentBest.neighbors)
                {
                    if (!unit.CanMove(neighbor.position))
                    {
                        continue;
                    }
                    double tentativeCost = currentBest.pathDistance + neighbor.tileType.movementCost;
                    if (neighbor.pathIndex < pathCounter)
                    {
                        neighbor.pathIndex = pathCounter;
                        neighbor.pathParent = currentBest;
                        neighbor.pathDistance = tentativeCost;
                        neighbor.pathHeuristic = neighbor.pathDistance + FValue(neighbor, end);
                        openSet.Enqueue(neighbor);
                    }
                    else if (tentativeCost < neighbor.pathDistance)
                    {
                        // Update costs if the current path is better than the existing one
                        neighbor.pathParent = currentBest;
                        neighbor.pathDistance = tentativeCost;
                        neighbor.pathHeuristic = neighbor.pathDistance + FValue(neighbor, end);
                        openSet.HeapifyUp(neighbor);
                    }
                }
            }
            if ( success )
            {
                // Generate path by following parent from end to start
                path = new List<Position>();
                Tile runner = end;
                while (runner != null)
                {
                    path.Insert(0, runner.position);
                    runner = runner.pathParent;
                }
            }

            pathCounter += 1;

            return path;
        }
        public void Attack( Unit attacker, Unit target )
        {
            Debug.Assert(attacker.AttackRange() >= attacker.position.Distance(target.position));

            target.health -= Math.Max(1, attacker.AttackStrength() - target.Defense());
            if (target.health<=0) // Target dead
            {
                RemoveUpdate(target);
                CacheRemoveUnitAt(target.position);
                units.Remove(target);
                unitQuadtrees[target.owner].RemoveUnit(target);
                target.status = Unit.Status.Dead;
            }
            else // I'm not dead yet
            {
                // Retaliate!
                if (target.CanAttack() && target.orders.Count == 0)
                {
                    OrderAttack(target, attacker);
                }
            }
        }
Exemple #25
0
        public Vector2 getHPBarDrawPosition(Unit unit)
        {
            Vector2 drawPosition = (unit.GetAnimatedPosition() - tileIndex) * (tilePxSize + pxMod);

            // add offset for HP bar position
            drawPosition.Y += tilePxSize + pxMod;

            return drawPosition;
        }