예제 #1
0
        // todo Implement PromtUser method


        // todo Implement ShowNotification/overload for AskUser method
        // todo Add overload taking string[] param for multiple-row message
        // todo Add param for more display positions (center, top-left etc..)
        /// <summary>
        /// Shows one-row long message
        /// </summary>
        /// <param name="message"></param>
        /// <param name="brush"></param>
        /// <returns></returns>
        public CancellationTokenSource ShowNotification(string message, PaintBrush brush)
        {
            CancellationTokenSource cts = new CancellationTokenSource();

            Task.Run(() =>
            {
                Canvas notificationCanvas = new Canvas
                {
                    Width          = message.Length + 4,
                    Height         = 5,
                    RenderPosition = RenderPosition.TopLeft
                };
                // render
                brush.RenderCanvas(notificationCanvas);

                for (int i = 0; i < message.Length; i++)
                {
                    brush.Render(
                        notificationCanvas,
                        new Position(notificationCanvas.CenterXPosition - (int)Math.Ceiling(message.Length / 2.0) + i, 1),
                        message[i]);
                }

                // wait for cancelation
                WaitHandle.WaitAll(new[] { cts.Token.WaitHandle });

                // derender
                brush.DerenderCanvas(notificationCanvas);
            }, cts.Token);

            return(cts);
        }
예제 #2
0
        // todo Implement PromtUser method


        // todo Implement ShowNotification/overload for AskUser method
        // todo Add overload taking string[] param for multiple-row message
        // todo Add param for more display positions (center, top-left etc..)
        /// <summary>
        /// Shows one-row long message
        /// </summary>
        /// <param name="message"></param>
        /// <param name="brush"></param>
        /// <param name="slowWrite"></param>
        /// <returns></returns>
        public CancellationTokenSource ShowNotification(string message, PaintBrush brush, bool slowWrite = false)
        {
            CancellationTokenSource cts = new CancellationTokenSource();

            Task.Run(() =>
            {
                Canvas notificationCanvas = new Canvas
                {
                    Width          = message.Length + 5,
                    Height         = 5,
                    RenderPosition = RenderPosition.TopLeft
                };
                // render
                lock (consoleGuardian)
                {
                    brush.RenderCanvas(notificationCanvas);
                }

                lock (consoleGuardian)
                {
                    if (slowWrite)
                    {
                        for (int i = 0; i < message.Length; i++)
                        {
                            brush.Render(
                                notificationCanvas,
                                new Position(notificationCanvas.CenterXPosition - (int)Math.Ceiling(message.Length / 2.0) + i, 1),
                                message[i]);
                        }
                    }
                    else
                    {
                        notificationCanvas.SetCursorPosition(notificationCanvas.CenterXPosition - (int)Math.Ceiling(message.Length / 2.0), 1);
                        Console.Write(message);
                    }
                }

                // wait for cancelation
                WaitHandle.WaitAll(new[] { cts.Token.WaitHandle });

                // derender
                lock (consoleGuardian)
                {
                    brush.DerenderCanvas(notificationCanvas);
                }
            }, cts.Token);

            return(cts);
        }
예제 #3
0
        private static void Reload(GameContext ctx, PaintBrush brush, NPCProvider npcProvider, PathFinderProvider pathFinder, Timer timeTimer, Logger logger)
        {
            timeTimer.Change(UInt32.MaxValue, 0);

            Init(ctx, brush, npcProvider, pathFinder, logger).Wait();

            int amountOfPeopleOnSquare = (int)GetAmountOfPeople(ctx.Square, ctx.Player.DifficultyLevel, logger);

            ctx.Enemies = npcProvider.GenerateEnemies(
                ctx.Square,
                new List <Position>
            {
                ctx.Player.Position
            },
                amountOfPeopleOnSquare);

            brush.Render(ctx.Square, ctx.Enemies.Select(x => x.Position).ToList(), Enemy.BodyCharacter);

            ctx.Player.Position.X = 0;
            ctx.Player.Position.Y = 0;

            timeTimer.Change(0, 1000);
        }
예제 #4
0
        public static async Task Init(
            GameContext ctx,
            PaintBrush brush,
            NPCProvider npcProvider,
            PathFinderProvider pathFinder,
            Logger logger)
        {
            logger.Trace("Init method called");

            Configurations config = new Configurations();

            Console.Title = config.GetConsoleTitle;

            Console.OutputEncoding = System.Text.Encoding.UTF8;

            // App.config doesnt have to be valid
            try
            {
                logger.Info("Setting up Console size");
                Console.BufferWidth  = Console.WindowWidth = config.GetConsoleWidth;
                Console.BufferHeight = Console.WindowHeight = config.GetConsoleHeight;

                Console.WindowLeft = Console.WindowTop = 0;

                logger.Info("Setting up Square");
                // Console's grid is indexed from zero => doesnt need to add 1 to startX of ctx.Square
                ctx.Square.StartX = ctx.Square.StartY = config.GetComponentMargin;
                ctx.Square.Width  = config.GetSquareWidth;
                ctx.Square.Height = config.GetSquareHeight;
                // TODO: Move Title to AppConfig
                ctx.Square.Title = "Main field - Square";

                logger.Info("Setting up ScoreBoard");
                ctx.ScoreBoard.StartX = (config.GetComponentMargin * 3) + ctx.Square.Width;
                ctx.ScoreBoard.StartY = ctx.Square.StartY;
                ctx.ScoreBoard.Width  = config.GetScoreBoardWidth;
                ctx.ScoreBoard.Height = (int)Math.Ceiling(config.GetScoreBoardHeight / 2.0) - config.GetComponentMargin;
                ctx.ScoreBoard.Title  = "Info board";

                ctx.MovementLog.StartX = ctx.ScoreBoard.StartX;
                ctx.MovementLog.StartY = ctx.ScoreBoard.Height + (config.GetComponentMargin * 3);
                ctx.MovementLog.Width  = ctx.ScoreBoard.Width;
                ctx.MovementLog.Height = ctx.ScoreBoard.Height - 1;
                ctx.MovementLog.Title  = "Movement History";
            }
            catch (FormatException ex)
            {
                logger.Error($"Some of App.config parameters were incorrect. Exception message: {ex.Message}");
            }
            catch (ArgumentNullException ex)
            {
                logger.Error($"Some of App.config parameters were null. Exception message: {ex.Message}");
            }

            Console.CursorVisible = false;

            DialogProvider dialogProvider = new DialogProvider();

            logger.Info("Setting players base position");
            ctx.Player.Position = new Position
            {
                X = 0,
                Y = 0
            };

            ctx.Target = new Position(ctx.Square.ContentWidth - 1, ctx.Square.ContentHeight - 1);

            logger.Info("User asked to choose difficulty");
            // Ask for difficulty
            ctx.Player.DifficultyLevel = await dialogProvider.AskUser(new Menu <DifficultyLevel>
            {
                Question = "Select difficulty:",
                Choices  = new Dictionary <DifficultyLevel, string>
                {
                    {
                        DifficultyLevel.Easy,
                        "Sir, let me have some drink"
                    },
                    {
                        DifficultyLevel.Medium,
                        "Alcoholic (professional)"
                    },
                    {
                        DifficultyLevel.Hard,
                        "I alcohol therefor I am"
                    }
                },
                Position = RenderPosition.Center,
                Margin   = 1
            }, brush);

            logger.Debug($"User picked {ctx.Player.DifficultyLevel.ToString()}");

            CancellationTokenSource notificationCts = dialogProvider.ShowNotification("Loading...", brush);

            #region PathFinder for securing game playability
            int          amountOfPeopleOnSquare = (int)GetAmountOfPeople(ctx.Square, ctx.Player.DifficultyLevel, logger);
            PathSolution solution;

            do
            {
                ctx.Enemies = npcProvider.GenerateEnemies(ctx.Square, new List <Position>
                {
                    ctx.Player.Position,
                    ctx.Target
                }, amountOfPeopleOnSquare);

                solution = PathFindingProcess(logger, ctx, brush, npcProvider, pathFinder);
            } while (solution.Path.Count == 0);

            notificationCts.Cancel();

            #endregion

            #region Rendering

            // Draws Walls for game field
            brush.RenderCanvas(ctx.Square);
            logger.Info($"canvas {ctx.Square.Title} rendered");

            // Draws Walls for score board
            brush.RenderCanvas(ctx.ScoreBoard);
            logger.Info($"canvas {ctx.ScoreBoard.Title} rendered");

            brush.RenderCanvas(ctx.MovementLog);
            logger.Info($"canvas {ctx.MovementLog.Title} rendered");

            // Draws player
            brush.Render(ctx.Square, ctx.Player.Position, Player.BodyCharacter);
            logger.Info($"Player rendered in canvas {ctx.Square.Title}");

            // render enemies
            brush.Render(ctx.Square, ctx.Enemies.Select(x => x.Position).ToList(), Enemy.BodyCharacter);

            // Show result path of path finding
            brush.ShowPath(
                ctx.Square,
                solution.Path,
                animated: true,
                animationDelay: 10,
                visibleLength: 40,
                visibleFor: 300,
                underlineTrail: true,
                underlineChar: CharacterMap.LightTrail,
                foregroundColor: ConsoleColor.Green,
                backgroundColor: ConsoleColor.Cyan);

            #endregion
        }
예제 #5
0
        /// <summary>
        /// Checks if next position will be collision and handles it
        /// </summary>
        /// <param name="context"></param>
        /// <param name="lastPosition"></param>
        /// <param name="newPlayerPosition"></param>
        /// <param name="newPlayerDirection"></param>
        /// <param name="brush"></param>
        private static void TripAndCollisionLogic(
            GameContext context,
            Position lastPosition,
            Position newPlayerPosition,
            Direction newPlayerDirection,
            PaintBrush brush)
        {
            Random random = new Random(DateTime.Now.Millisecond);

            bool collided = newPlayerPosition.PredictCollision(context.Enemies.Select(enemy => enemy.Position));

            bool tripped = false;

            if (!collided)
            {
                tripped = random.Next(1, 5) == 1;                 // 25% chance
            }

            if (collided)
            {
                SimulationResult simulationResult = null;

                do
                {
                    // TODO: Move constnat numbres to App.config
                    Simulation simulation = (simulationResult?.Obstacle ?? newPlayerPosition)
                                            .SimulateCollision(
                        lastPosition,
                        newPlayerDirection,
                        3, 4);

                    newPlayerDirection = newPlayerDirection.Reverse();

                    simulationResult = context.Square.ExecuteSimulation(simulation, newPosition =>
                    {
                        return(!newPosition.PredictCollision(context.Enemies.Select(enemy => enemy.Position)));
                    }, brush);

                    lastPosition = simulationResult.LastSafePosition;
                } while (!simulationResult.HasSuccessfulyFinished);

                context.Player.Position = simulationResult.LastSafePosition;
            }
            else if (tripped)
            {
                SimulationResult simulationResult = null;

                do
                {
                    Simulation simulation;

                    // TODO: Move constnat numbres to App.config
                    if (!simulationResult?.HasSuccessfulyFinished ?? false)
                    {
                        simulation = lastPosition
                                     .SimulateCollision(
                            newPlayerPosition,
                            newPlayerDirection,
                            3, 4);

                        newPlayerDirection = newPlayerDirection.Reverse();
                    }
                    else
                    {
                        simulation = newPlayerPosition
                                     .SimulateTrip(
                            simulationResult?.LastSafePosition ?? lastPosition,
                            newPlayerDirection,
                            2, 4);
                    }

                    simulationResult = context.Square.ExecuteSimulation(simulation, newPosition =>
                    {
                        return(!newPosition.PredictCollision(context.Enemies.Select(enemy => enemy.Position)) ||
                               newPosition.Y < 0 || newPosition.X < 0);                            // TODO: Finish validation
                    }, brush, true);

                    newPlayerPosition = simulationResult.Obstacle;
                    lastPosition      = simulationResult.LastSafePosition;
                } while (!simulationResult.HasSuccessfulyFinished);

                context.Player.Position = simulationResult.LastSafePosition;
            }
            else
            {
                brush.Derender(context.Square, context.Player.Position);

                // Update position and direction
                context.Player.Direction = newPlayerDirection;
                context.Player.Position  = newPlayerPosition;

                brush.Render(context.Square, context.Player.Position, Player.BodyCharacter);
            }
        }