Exemplo n.º 1
0
        // PERF: If this ends up being slow, we can mark with a dirty bit

        /**
         * Returns a path from start to end, exclusive - that is, the start and end nodes are *not* listed in the path. Does a full
         * naive search every time.
         */
        public static List <EncounterPosition> AStarWithNewGrid(
            EncounterPosition start,
            EncounterPosition end,
            EncounterState state,
            int maxAreaToExplore = 950
            )
        {
            SimplePriorityQueue <EncounterPosition> frontier = new SimplePriorityQueue <EncounterPosition>();

            frontier.Enqueue(start, 0f);

            var cameFrom = new Dictionary <EncounterPosition, EncounterPosition>();

            var costSoFar = new Dictionary <EncounterPosition, float>();

            costSoFar[start] = 0f;

            while (frontier.Count > 0 && cameFrom.Count < maxAreaToExplore)
            {
                var currentPosition   = frontier.Dequeue();
                var adjacentPositions = state.AdjacentPositions(currentPosition);

                if (currentPosition == end || (state.IsPositionBlocked(end) && adjacentPositions.Contains(end)))
                {
                    var path = new List <EncounterPosition>()
                    {
                        currentPosition
                    };

                    EncounterPosition cameFromPos;
                    while (cameFrom.TryGetValue(path[path.Count - 1], out cameFromPos) && (cameFromPos != start))
                    {
                        path.Add(cameFromPos);
                    }
                    path.Reverse();

                    return(path);
                }

                var adjacentUnblocked = adjacentPositions.Where(adjacent => !state.IsPositionBlocked(adjacent)).ToList();
                adjacentUnblocked.ForEach(adjacent => {
                    var newNextPositionCost = costSoFar[currentPosition] + 1f;
                    if (!costSoFar.ContainsKey(adjacent) || newNextPositionCost < costSoFar[adjacent])
                    {
                        costSoFar[adjacent] = newNextPositionCost;
                        // Uses straight-line distance as heuristic
                        float priority = newNextPositionCost + adjacent.DistanceTo(end);
                        frontier.Enqueue(adjacent, priority);
                        cameFrom[adjacent] = currentPosition;
                    }
                });
            }
            return(null);
        }
Exemplo n.º 2
0
        private static bool ResolveMove(MoveAction action, EncounterState state)
        {
            Entity actor             = state.GetEntityById(action.ActorId);
            var    positionComponent = state.GetEntityById(action.ActorId).GetComponent <PositionComponent>();

            if (positionComponent.EncounterPosition == action.TargetPosition)
            {
                GD.PrintErr(string.Format("Entity {0}:{1} tried to move to its current position {2}", actor.EntityName, actor.EntityId, action.TargetPosition));
                return(false);
            }
            else if (state.IsPositionBlocked(action.TargetPosition))
            {
                var blocker        = state.BlockingEntityAtPosition(action.TargetPosition.X, action.TargetPosition.Y);
                var actorCollision = actor.GetComponent <CollisionComponent>();

                if (actorCollision.OnCollisionAttack)
                {
                    Attack(actor, blocker, state);
                }
                if (actorCollision.OnCollisionSelfDestruct)
                {
                    state.TeleportEntity(actor, action.TargetPosition, ignoreCollision: true);
                    if (state.FoVCache.IsVisible(action.TargetPosition))
                    {
                        positionComponent.PlayExplosion();
                    }
                    ResolveAction(new DestroyAction(action.ActorId), state);
                }
                return(true);
            }
            else
            {
                state.TeleportEntity(actor, action.TargetPosition, ignoreCollision: false);
                return(true);
            }
        }