Ejemplo n.º 1
0
        public void Move(SelfMovementContext context)
        {
            // get next target based on ghost mode and corresponding movement strategy
            var currentVertex = Position.ToTile();
            var currentTile   = context.Map[currentVertex.Y, currentVertex.X];

            // check if ghost needs to change the direction
            if (Position.Equals(currentTile.Position))
            {
                var allowedDirections = context.Map.GetNeighbors(currentVertex)
                                        .Where(neighbor => !neighbor.IsWall)
                                        .Select(neighbor => Position.ToDirection(neighbor.Position))
                                        .ToList();

                // specified direction is not allowed, so stop
                State = !allowedDirections.Contains(context.GameState.PacManNextTurn)
                    ? State with {
                    Direction = Direction.None
                }
Ejemplo n.º 2
0
        protected override Task PhysicsStep(IGameContext context, CancellationToken token)
        {
            _renderer.Render(_map.ToSprite(new Offset(0, 0)));

            _collisionDetection
            .DetectCollisions(_map.PacMan, _map.All)
            .OfType <IEatable>()
            .ToList()
            .ForEach(eatable =>
            {
                _map.PacMan.Effect(new FoodContext(_eventSink, _map, _gameState, eatable));
                eatable.Effect(new FoodContext(_eventSink, _map, _gameState, _map.PacMan));
            });

            var deadGhostSprites = _map.Ghosts
                                   .Where(ghost => ghost.Mode == GhostMode.Dead)
                                   .Cast <ISprite>()
                                   .ToList();

            _map.All
            .OfType <IRespawnSprite>()
            .ToList()
            .ForEach(respawn =>
            {
                _collisionDetection
                .DetectCollisions(respawn, deadGhostSprites)
                .OfType <IGhost>()
                .ToList()
                .ForEach(ghost => respawn.Effect(new GhostRespawnContext(ghost)));
            });

            // TODO: do the movement in a separate timers to simulate different speeds
            var selfMovementContext = new SelfMovementContext(_eventSink, _map, _gameState, _lastUpdateTime);

            _map.PacMan.Move(selfMovementContext);
            _map.PacMan.Move(selfMovementContext);
            _map.Ghosts.ToList().ForEach(ghost => ghost.Move(selfMovementContext));

            _lastUpdateTime = DateTime.Now;
            return(Task.CompletedTask);
        }
Ejemplo n.º 3
0
        public void Move(SelfMovementContext context)
        {
            // get next target based on ghost mode and corresponding movement strategy
            var currentVertex = Position.ToTile();
            var currentTile   = context.Map[currentVertex.Y, currentVertex.X];

            // check if ghost needs to change the direction
            if (Position.Equals(currentTile.Position))
            {
                CheckTimeoutBeforeBeingComforted(DateTime.Now);
                CheckTimeoutBeforeChangingMode(DateTime.Now);

                var movementContext = new GhostMovementContext(context.EventSink, context.Map, this);
                var target          = _currentMode.Execute(movementContext);
                var ghostPosition   = Position;
                var ghostDirection  = State.Direction;

                var graph     = context.Map;
                var neighbors = graph.GetNeighbors(currentVertex)
                                .Where(neighbor => !neighbor.IsWall)
                                .ToList();

                var allowedDirections = neighbors
                                        .Select(neighbor => ghostPosition.ToDirection(neighbor.Position))
                                        .Where(direction => direction != ghostDirection.ToOpposite())
                                        .Where(direction => direction != currentTile.Restriction)
                                        .ToList();

                if (allowedDirections.Count == 1)
                {
                    // there is only one way to go/turn - go/turn that way
                    State = State with {
                        Direction = allowedDirections.Single()
                    };
                }
                else if (allowedDirections.Count == 0)
                {
                    // there were no ways to go/turn, choosing the direction closest to target
                    var targetDirection = neighbors
                                          .Select(neighbor => neighbor.Position)
                                          .OrderBy(neighbor => neighbor.EuclideanDistance(target))
                                          .First();

                    State = State with {
                        Direction = ghostPosition.ToDirection(targetDirection)
                    };
                }
                else if (neighbors.Count >= 3)
                {
                    // current tile is the tile in which we need to decide where to go/turn
                    // TODO: check the direction accroding to the priorities below
                    // Direction.Up, Direction.Left, Direction.Down
                    var targetDirection = allowedDirections
                                          .Select(direction => Position.Shift(direction.ToOffset()))
                                          .OrderBy(neighbor => neighbor.EuclideanDistance(target))
                                          .First();

                    State = State with {
                        Direction = ghostPosition.ToDirection(targetDirection)
                    };
                }
            }

            var nextPosition = Position.Shift(State.Direction.ToOffset());
            var afterVertex  = nextPosition.ToTile();
            var afterTile    = context.Map[afterVertex.Y, afterVertex.X];

            Position = afterTile.IsWall ? Position : nextPosition;
        }