static void Main() { // Setup playable area Console.Title = "Falling Rocks"; Console.CursorVisible = false; Console.WindowHeight = boardHeight + 2; Console.BufferHeight = boardHeight + 2; Console.WindowWidth = boardWidth; Console.BufferWidth = boardWidth; // First draw Console.BackgroundColor = ConsoleColor.Black; Console.Clear(); ClearBoard(); DrawBoard(); DrawGround(); DrawScore(); // Initialize screen elements ScreenElement dwarf = new ScreenElement("\x1B\x02\x1A", (byte)(boardWidth / 2), (byte)(boardHeight - 2)); Enemy.lastID = maxRocks; // Set lastID to the end of the array, on next spawn call the index will roll over for (int i = 0; i < maxRocks; i++) { rocks[i] = new Enemy(); // Fill array with dead elements } // Initialize clock Stopwatch timer = new Stopwatch(); timer.Start(); TimeSpan frameLast = new TimeSpan(0); TimeSpan frameThis = new TimeSpan(); double lastSpawn = 0.0; // Last time an enemy was spawned int lastSeeker = 0; // Last score a seeker was spawned // Game loop ConsoleKeyInfo pressedKey; bool escapePressed = false; while (true) { frameThis = timer.Elapsed; // Process input if (Console.KeyAvailable) { pressedKey = Console.ReadKey(true); switch (pressedKey.Key) { case ConsoleKey.LeftArrow: dwarf.MoveLeft(); break; case ConsoleKey.RightArrow: dwarf.MoveRight(); break; case ConsoleKey.Escape: escapePressed = true; break; default: break; } // Escape is used to terminate if (escapePressed) { break; } } // Process enemies double elapsed = frameThis.TotalMilliseconds - frameLast.TotalMilliseconds; // Calculate elapsed time if (frameThis.TotalMilliseconds > lastSpawn + (500 - frameLast.TotalMilliseconds * 0.0055)) { // Rocks spawn at an increasing rate, SpawnRock(frameThis.TotalMilliseconds); // reaching peak at 90 seconds lastSpawn = frameThis.TotalMilliseconds; // (spawning every tick, if possible) } // Seeker spawnrate peaks at 90 seconds, which theretically should mean regular intervals, // however enemy movement speed is out of phase (peaking at 60 seconds), meaning fewer // seekers up to 60 seconds and more seekers later. if (score - lastSeeker > (100 + frameLast.TotalMilliseconds / 225)) { lastSeeker = score; SpawnSeeker(frameThis.TotalMilliseconds, (byte)(dwarf.Left + 1)); } UpdateRocks(elapsed); // Make 'em fall frameLast = frameThis; // Commit elements and render board dwarf.Draw(frameLast); // Character is comitted last for collision detecion DrawBoard(); DrawScore(); ClearBoard(); // Check alive state if (health < 1) { break; } } // Exit DrawEndscreen(); // Display final score; this will trigger when exiting with Escape }