181 lines
7.0 KiB
C#
181 lines
7.0 KiB
C#
|
using System;
|
|||
|
using System.Drawing;
|
|||
|
using System.Globalization;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Security;
|
|||
|
using System.Threading;
|
|||
|
using CC_Functions.Commandline.TUI;
|
|||
|
using CC_Functions.Misc;
|
|||
|
using D = CC_Functions.Commandline.TUI.DiffDraw;
|
|||
|
|
|||
|
namespace OnScreenKeyboard
|
|||
|
{
|
|||
|
class Program
|
|||
|
{
|
|||
|
private const string Keyboard = "qwertyuiop\nasdfghjkl_\nzxcvbnm,.-";
|
|||
|
private const int Width = 10 * 3;
|
|||
|
private const int Height = 4;
|
|||
|
private static Point _ball = new Point(0, Height - 1);
|
|||
|
private static Point _ballSpeed = new Point(1, -1);
|
|||
|
private static int _peddle = 0;
|
|||
|
private static string _input = "";
|
|||
|
static void Main(string[] args)
|
|||
|
{
|
|||
|
//args
|
|||
|
if (args.GetBool("help") || args.GetBool("?") || args.GetBool("h"))
|
|||
|
{
|
|||
|
Console.WriteLine(@"JF OSK v1
|
|||
|
|
|||
|
Usage:
|
|||
|
OSK [arguments]
|
|||
|
|
|||
|
Arguments:
|
|||
|
delay The time to wait between ball movements.
|
|||
|
no-color Do not output color. Use only if color doesn't work.
|
|||
|
peddle-length The length of the peddle.
|
|||
|
output Output the result to a file.
|
|||
|
|
|||
|
Examples:
|
|||
|
OSK --delay:0.3 --peddle-length:3
|
|||
|
OSK --no-color --output:file.txt
|
|||
|
OSK");
|
|||
|
return;
|
|||
|
}
|
|||
|
TimeSpan ballSpeed = args.Get("delay", s => s == null ? new TimeSpan(0, 0, 1) : TimeSpan.Parse($"0:0:0:{s}", CultureInfo.InvariantCulture));
|
|||
|
bool color = !args.GetBool("no-color");
|
|||
|
int peddleLength = args.Get("peddle-length", s => s == null ? 4 : int.Parse(s, CultureInfo.InvariantCulture));
|
|||
|
if (peddleLength > Width)
|
|||
|
peddleLength = Width;
|
|||
|
string outputFile = args.Get("output");
|
|||
|
//init
|
|||
|
Console.BackgroundColor = ConsoleColor.Black;
|
|||
|
Console.ForegroundColor = ConsoleColor.White;
|
|||
|
Console.Clear();
|
|||
|
bool playing = true;
|
|||
|
DateTime lastGameTick = DateTime.Now;
|
|||
|
while (playing)
|
|||
|
{
|
|||
|
//Process input
|
|||
|
bool left = false;
|
|||
|
bool right = false;
|
|||
|
bool select = false;
|
|||
|
while (Console.KeyAvailable)
|
|||
|
{
|
|||
|
switch (Console.ReadKey().Key)
|
|||
|
{
|
|||
|
case ConsoleKey.LeftArrow:
|
|||
|
case ConsoleKey.A:
|
|||
|
left = true;
|
|||
|
break;
|
|||
|
case ConsoleKey.RightArrow:
|
|||
|
case ConsoleKey.D:
|
|||
|
right = true;
|
|||
|
break;
|
|||
|
case ConsoleKey.W:
|
|||
|
case ConsoleKey.S:
|
|||
|
case ConsoleKey.UpArrow:
|
|||
|
case ConsoleKey.DownArrow:
|
|||
|
case ConsoleKey.Spacebar:
|
|||
|
case ConsoleKey.Enter:
|
|||
|
select = true;
|
|||
|
break;
|
|||
|
case ConsoleKey.Escape:
|
|||
|
playing = false;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
//Move peddle
|
|||
|
if (left)
|
|||
|
_peddle--;
|
|||
|
if (right)
|
|||
|
_peddle++;
|
|||
|
if (_peddle < 0)
|
|||
|
_peddle = 0;
|
|||
|
if (_peddle > Width - peddleLength)
|
|||
|
_peddle = Width - peddleLength;
|
|||
|
//Scheduled game tick
|
|||
|
if (lastGameTick + ballSpeed - DateTime.Now <= TimeSpan.Zero)
|
|||
|
{
|
|||
|
lastGameTick = DateTime.Now;
|
|||
|
//Move ball
|
|||
|
ball:
|
|||
|
_ball = new Point(_ball.X + _ballSpeed.X, _ball.Y + _ballSpeed.Y);
|
|||
|
if (_ball.X == 0 || _ball.X == Width - 1)
|
|||
|
_ballSpeed = new Point(-_ballSpeed.X, _ballSpeed.Y);
|
|||
|
if (_ball.Y == 0)
|
|||
|
_ballSpeed = new Point(_ballSpeed.X, -_ballSpeed.Y);
|
|||
|
if (_ball.Y == Height - 1 && _ball.X >= _peddle && _ball.X < _peddle + peddleLength)
|
|||
|
{
|
|||
|
if (_ball.X > 0 && _ball.X < Width - 1)
|
|||
|
_ball.X -= _ballSpeed.X;
|
|||
|
_ball.Y -= 1;
|
|||
|
_ballSpeed = new Point(_ballSpeed.X, -_ballSpeed.Y);
|
|||
|
goto ball;
|
|||
|
}
|
|||
|
if (_ball.Y == Height) playing = false;
|
|||
|
}
|
|||
|
//Post-input pre-draw stuff
|
|||
|
if (!playing)
|
|||
|
continue;
|
|||
|
Pixel[,] empty = new Pixel[Height, Width];
|
|||
|
empty.Populate(new Pixel(' '));
|
|||
|
D.Clear(empty);
|
|||
|
//Draw keyboard and add to output. Combined one to avoid major code duplication
|
|||
|
int y = 0;
|
|||
|
int sub = 0;
|
|||
|
for (int i = 0; i < Keyboard.Length; i++)
|
|||
|
{
|
|||
|
char t = Keyboard[i];
|
|||
|
if (t == '\n')
|
|||
|
{
|
|||
|
y++;
|
|||
|
sub = i + 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Point start = new Point((i - sub) * 3, y);
|
|||
|
bool selected = _ball.Y == start.Y && _ball.X >= start.X && _ball.X < start.X + 3;
|
|||
|
if (selected && select)
|
|||
|
_input += t;
|
|||
|
DrawString(start,
|
|||
|
$" {t} ",
|
|||
|
selected ? Console.BackgroundColor : Console.ForegroundColor,
|
|||
|
selected ? Console.ForegroundColor : Console.BackgroundColor);
|
|||
|
}
|
|||
|
}
|
|||
|
//Draw ball
|
|||
|
D.Set(_ball, new Pixel(Console.ForegroundColor, Console.BackgroundColor, 'X'));
|
|||
|
//Draw paddle
|
|||
|
DrawString(new Point(_peddle, Height - 1), new string('█', peddleLength), Console.ForegroundColor, Console.BackgroundColor);
|
|||
|
//Finish frame
|
|||
|
D.Draw(color);
|
|||
|
Console.CursorLeft = 0;
|
|||
|
Console.CursorTop = Height;
|
|||
|
Console.Write(_input);
|
|||
|
}
|
|||
|
Console.ResetColor();
|
|||
|
Console.Clear();
|
|||
|
Console.WriteLine(_input);
|
|||
|
if (outputFile != null)
|
|||
|
try
|
|||
|
{
|
|||
|
File.WriteAllText(outputFile, _input);
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
Console.WriteLine($"Could not save output: {e.Message}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static void DrawString(Point start, string chars, ConsoleColor foreColor, ConsoleColor backColor)
|
|||
|
{
|
|||
|
foreach (string s in chars.Split('\n'))
|
|||
|
for (int i = 0; i < s.Length; i++)
|
|||
|
{
|
|||
|
char t = s[i];
|
|||
|
D.Set(start.X + i, start.Y, new Pixel(backColor, foreColor, t));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|