// 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); }
// 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); }
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 }