diff --git a/ConsoleSnake/AsciiArt.cs b/ConsoleSnake/AsciiArt.cs new file mode 100644 index 0000000..6f2dac0 --- /dev/null +++ b/ConsoleSnake/AsciiArt.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ConsoleSnake +{ + internal static class AsciiArt + { + public enum TextAlignment + { + Left, + Centered, + Right, + Top, + Bottom + } + private static (Int32 left, Int32 top) FindStartingPosition(Int32 numLines, Int32 numColumns, TextAlignment horizontalAlignment, TextAlignment verticalAlignment, int offsetLeft = 0, int offsetTop = 0) + { + Int32 left; + Int32 top; + + switch(horizontalAlignment) + { + default: + case TextAlignment.Left: + left = 0; + break; + case TextAlignment.Centered: + left = Console.WindowWidth / 2 - numColumns / 2; + break; + case TextAlignment.Right: + left = Console.WindowWidth - numColumns; + break; + } + + switch(verticalAlignment) + { + default: + case TextAlignment.Top: + top = 0; + break; + case TextAlignment.Centered: + top = Console.WindowHeight / 2 - numLines / 2; + break; + case TextAlignment.Bottom: + top = Console.WindowHeight - numLines; + break; + } + + return (left + offsetLeft, top + offsetTop); + } + + private static void DrawAt(ref string[] str, TextAlignment horizontalAlignment, TextAlignment verticalAlignment, ConsoleColor col = ConsoleColor.White, int offsetLeft = 0, int offsetTop = 0) + { + (Int32 left, Int32 top) startingPos = FindStartingPosition(str.Count(), str[0].Length, horizontalAlignment, verticalAlignment, offsetLeft, offsetTop); + + Console.SetCursorPosition(startingPos.left, startingPos.top); + Console.ForegroundColor = col; + + foreach(var item in str) + { + Console.WriteLine(item); + Console.CursorLeft = startingPos.left; + } + } + + public static void IntroAnimation() + { + bool loopRunning = true; + + (ConsoleColor col, Int32 sleepFor)[] animFrames = + { + (ConsoleColor.DarkGray, 150), + (ConsoleColor.Gray, 100), + (ConsoleColor.White, 170), + (ConsoleColor.Gray, 90), + (ConsoleColor.DarkGray, 190), + (ConsoleColor.White, 40), + (ConsoleColor.DarkGray, 100), + (ConsoleColor.Gray, 160), + (ConsoleColor.DarkGray, 100), + (ConsoleColor.DarkGray, 60), + (ConsoleColor.Gray, 100), + (ConsoleColor.DarkGray, 40), + }; + + while (loopRunning) + { + foreach ((ConsoleColor col, Int32 sleepFor) frame in animFrames) + { + CNake(TextAlignment.Centered, TextAlignment.Top, frame.col, offsetTop: 4); + Thread.Sleep(frame.sleepFor); + if (Console.KeyAvailable) + { + Console.ReadKey(); + loopRunning = false; + } + } + } + + Console.Clear(); + } + + public static void CNake(TextAlignment horizontalAlignment = TextAlignment.Centered, TextAlignment verticalAlignment = TextAlignment.Centered, ConsoleColor col = ConsoleColor.White, Int32 offsetLeft = 0, Int32 offsetTop = 0) + { + string[] lines = + { + @" _____ _____ ______ ____ ____ ____ ______ ", + @" ___|\ \|\ \ |\ \ ____|\ \ | | | | ___|\ \ ", + @" / /\ \ \ \| \ \ / /\ \ | | | | | \ \ ", + @"| | | |\| \ \ || | | || | / // | ,_____/|", + @"| | |____| | \ | || |__| || |/ _ _// | \--'\_|/", + @"| | ____ | \ | || .--. || |\ \' | /___/| ", + @"| | | | | |\ \| || | | || | \ \ | \____|\ ", + @"|\ ___\/ /| |____||\_____/||____| |____||____| \____\ |____ ' /|", + @"| | /____/ | | |/ \| ||| | | || | | || /_____/ |", + @" \|___| | / |____| |___|/|____| |____||____| |____||____| | /", + @" \( |____|/ \( )/ \( )/ \( )/ \( |_____|/ ", + @" ' )/ ' ' ' ' ' ' ' )/ ", + @" ' ' ", + @" ", + @" PRESS ANY KEY " + + + }; + DrawAt(ref lines, horizontalAlignment, verticalAlignment, col, offsetLeft, offsetTop); + } + + public static void GameOver(TextAlignment horizontalAlignment = TextAlignment.Centered, TextAlignment verticalAlignment = TextAlignment.Centered, ConsoleColor col = ConsoleColor.White, Int32 offsetLeft = 0, Int32 offsetTop = 0) + { + string[] lines = + { + @" ___ ___ ", + @" / __|__ _ _ __ ___ / _ \__ _____ _ _ ", + @" | (_ / _` | ' \/ -_) | (_) \ V / -_) '_|", + @" \___\__,_|_|_|_\___| \___/ \_/\___|_| ", + @" ", + @" ", + @" PRESS ANY KEY " + + + }; + DrawAt(ref lines, horizontalAlignment, verticalAlignment, col, offsetLeft, offsetTop); + } + + public static void Countdown(TextAlignment horizontalAlignment = TextAlignment.Centered, TextAlignment verticalAlignment = TextAlignment.Centered, ConsoleColor col = ConsoleColor.White, Int32 offsetLeft = 0, Int32 offsetTop = 0) + { + string[][] numbers = + { + new string[] { + @" ____", + @" |__ /", + @" |_ \", + @" |___/", + @" " + }, + new string[] + { + @" ___ ", + @" |_ )", + @" / / ", + @" /___|", + @" " + }, + new string[] + { + @" _ ", + @" / | ", + @" | | ", + @" |_| ", + @" " + } + }; + + foreach(string[] lines in numbers) + { + string[] curLines = lines; + DrawAt(ref curLines, horizontalAlignment, verticalAlignment, col, offsetLeft, offsetTop); + Thread.Sleep(1000); + } + + string[] clearArea = new string[] + { + @" ", + @" ", + @" ", + @" ", + @" " + }; + DrawAt(ref clearArea, horizontalAlignment, verticalAlignment, col, offsetLeft, offsetTop); + } + + + } + + +} diff --git a/ConsoleSnake/Menu.cs b/ConsoleSnake/Menu.cs new file mode 100644 index 0000000..6d2b90d --- /dev/null +++ b/ConsoleSnake/Menu.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ConsoleSnake +{ + internal class Menu + { + internal class MenuItem + { + //public delegate bool MenuAction(object? customData = null); + public delegate bool MenuAction(); + public string Label { get; set; } + public string Description { get; set; } + public MenuAction Action { get; set; } + } + + private Dictionary _menuItems = new Dictionary(); + private string _selectedEntry = ""; + public Menu() { } + public void Show() + { + + Console.CursorTop = 10; + foreach (var item in _menuItems) + { + Console.CursorLeft = 30; + if (_selectedEntry == item.Key) + { + Console.BackgroundColor = ConsoleColor.Green; + } + else + { + Console.BackgroundColor = ConsoleColor.Black; + } + Console.WriteLine(item.Key); + } + while (true) + { + Thread.Sleep(1000); + break; + } + } + + public void AddItem(string label, string description, MenuItem.MenuAction action, bool selected = false) + { + MenuItem menuItem = new MenuItem(); + + menuItem.Label = label; + menuItem.Description = description; + menuItem.Action = action; + + if (_selectedEntry == null || selected) + _selectedEntry = label; + + _menuItems.Add(label, menuItem); + } + + public bool RemoveItem(string label) => _menuItems.Remove(label); + public void Clear() => _menuItems.Clear(); + } +} diff --git a/ConsoleSnake/Program.cs b/ConsoleSnake/Program.cs index 47a3cdf..3d7995f 100644 --- a/ConsoleSnake/Program.cs +++ b/ConsoleSnake/Program.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.Design; - -namespace ConsoleSnake +namespace ConsoleSnake { internal class Program { @@ -48,8 +46,14 @@ namespace ConsoleSnake } } + const Int32 MINWIDTH = 82; + const Int32 MINHEIGHT = 35; + private static PlayArea _playArea = new PlayArea(1, 4, Console.WindowWidth - 2, Console.WindowHeight - 2); + + private static bool _gameRunning = true; private static bool _running = true; + private static Snake[] _snakes = { new Snake(), new Snake() @@ -59,24 +63,49 @@ namespace ConsoleSnake private static Int32 _desiredFrameTime = 75; private static DateTime _frameTiming = DateTime.Now; + + static void Setup() + { + Console.SetWindowSize(MINWIDTH, MINHEIGHT); + Console.SetBufferSize(Console.WindowWidth, Console.WindowHeight); + Console.CursorVisible = false; + } static void Main(string[] args) { Console.ReadKey(); + Setup(); + AsciiArt.IntroAnimation(); + MainLoop(); + } - Console.SetBufferSize(Console.WindowWidth, Console.WindowHeight); + private static void ShowMenu() + { + Menu menu = new Menu(); + menu.AddItem("Play [1P]", "Play a single-player game.", () => { return false; }); + menu.AddItem("Play [2P]", "Play a two-player game.", () => { return false; }); + menu.AddItem("Quit", "Quit the game.", () => { return _gameRunning = false; }); + menu.Show(); + } - DrawPlayArea(); - - //Console.WindowWidth -= 1; - Console.ReadKey(true); - Reset(); - - - while (_running) + private static void MainLoop() + { + //foreach (ConsoleColor col in Enum.GetValues(typeof(ConsoleColor))) + //{ + // Console.ForegroundColor = col; + // Console.WriteLine(col); + //} + while (_gameRunning) { - TimeFrame(); - HandleInput(); - AllSnakeThings(); + ShowMenu(); + Reset(); + DrawPlayArea(); + AsciiArt.Countdown(col: ConsoleColor.Magenta); + while (_running) + { + TimeFrame(); + HandleInput(); + AllSnakeThings(); + } } } @@ -113,6 +142,10 @@ namespace ConsoleSnake } private static void Reset() { + Console.ForegroundColor = ConsoleColor.White; + Console.BackgroundColor = ConsoleColor.Black; + Console.Clear(); + _playArea = new PlayArea(1, 4, Console.WindowWidth - 2, Console.WindowHeight - 2); _running = true; @@ -122,6 +155,8 @@ namespace ConsoleSnake _snakes[1].Color = ConsoleColor.Cyan; _snakes[0].Segments.Clear(); _snakes[1].Segments.Clear(); + _snakes[0].Alive = true; + _snakes[1].Alive = true; // Set up anew _snakes[0].Segments.Add(_snakes[0].HeadPosition = new Position2D(Console.BufferWidth / 2, Console.BufferHeight / 2)); @@ -196,13 +231,18 @@ namespace ConsoleSnake { if (snake.Alive) { - // is this snake running into the other snake or itself? + // is this snake running into the other snake or itself? -> pepsi if (SnakeCollision(snake.HeadPosition)) { KillSnake(snake); // everyone pepsi? game over?! if (!_snakes[0].Alive && !_snakes[1].Alive) + { _running = false; + AsciiArt.GameOver(); + Console.ReadKey(); + } + continue; }