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 }
public static void Main() { Logger logger = LogManager.GetCurrentClassLogger(); Configurations configurations = new Configurations(); GameContext context = new GameContext { Player = new Player(), ScoreBoard = new TextCanvas(), Square = new Canvas(), MovementLog = new TextCanvas() }; PaintBrush brush = new PaintBrush(ConsoleGuardian); NPCProvider npcProvider = new NPCProvider(); // Path finder PathFinderProvider pathFinder = new PathFinderProvider(); Init(context, brush, npcProvider, pathFinder, logger).Wait(); Timer timer = new Timer(state => { lock (ConsoleGuardian) { context.ScoreBoard.Clear(); context.ScoreBoard .WriteLine($"Current Time: {DateTime.Now:hh:mm:ss}"); context.ScoreBoard .WriteLine($"Position: [{context.Player.Position.X:000},{context.Player.Position.Y:000}]"); } }, null, 0, 1000); Task task = null; CancellationTokenSource cts = null; do { // Wait for GUI to finish if (!task?.IsCompleted ?? false) { continue; } // Shutdown Game if (cts?.IsCancellationRequested ?? false) { return; } // To empty Console buffer while (Console.KeyAvailable) { Console.ReadKey(true); } ConsoleKey key = Console.ReadKey(true).Key; cts = new CancellationTokenSource(); task = Task.Run(() => { UserAction action = GetUserAction(key, logger); // Copy Players Position and Direction Position newPlayerPosition = Position.Copy(context.Player.Position); Position oldPosition = Position.Copy(context.Player.Position); Direction newPlayerDirection = context.Player.Direction; #region Handle User Actions switch (action) { case UserAction.DirectionUp: { newPlayerPosition.Y--; newPlayerDirection = Direction.Up; break; } case UserAction.DirectionDown: { newPlayerPosition.Y++; newPlayerDirection = Direction.Down; break; } case UserAction.DirectionLeft: { newPlayerPosition.X--; newPlayerDirection = Direction.Left; break; } case UserAction.DirectionRight: { newPlayerPosition.X++; newPlayerDirection = Direction.Right; break; } case UserAction.Reload: { Reload(context, brush, npcProvider, pathFinder, timer, logger); return; } case UserAction.ShowPath: { brush.ShowPath( context.Square, PathFindingProcess(logger, context, brush, npcProvider, pathFinder).Path, animated: true, animationDelay: 10, visibleLength: 40, visibleFor: 300, underlineTrail: true, underlineChar: CharacterMap.LightTrail, foregroundColor: ConsoleColor.Green, backgroundColor: ConsoleColor.Cyan); break; } case UserAction.QuitGame: { cts.Cancel(); break; } } #endregion TripAndCollisionLogic(context, oldPosition, newPlayerPosition, newPlayerDirection, brush); Thread.Sleep(configurations.GetMainDelay); }, cts.Token); } while (true); }