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