How to create ASCII animation in Windows Console application using C#?
I would like it to display non-flickery animation 开发者_运维百科like this awesome Linux command; sl
http://www.youtube.com/watch?v=9GyMZKWjcYU
I would appreciate a small & stupid example of say ... a fly.
Thanks!
Just use Console.SetCursorPosition
for moving the cursor to a certain position, then Console.Write
a character. Before each frame you have to delete the previous one by overwriting it with spaces. Heres a little example I just built:
class Program
{
static void Main(string[] args)
{
char[] chars = new char[] { '.', '-', '+', '^', '°', '*' };
for (int i = 0; ; i++)
{
if (i != 0)
{
// Delete the previous char by setting it to a space
Console.SetCursorPosition(6 - (i-1) % 6 - 1, Console.CursorTop);
Console.Write(" ");
}
// Write the new char
Console.SetCursorPosition(6 - i % 6 - 1, Console.CursorTop);
Console.Write(chars[i % 6]);
System.Threading.Thread.Sleep(100);
}
}
}
You could for instance take an animated gif, extract all single frames/images from it (see how to do that here), apply an ASCII transformation (how to do that is described here for example) and print these frame by frame like in the above code example.
Update
Just for fun, I implemented what I just described. Just try it out replacing @"C:\some_animated_gif.gif"
with the path to some (not to large) animated gif. For example take an AJAX loader gif from here.
class Program
{
static void Main(string[] args)
{
Image image = Image.FromFile(@"C:\some_animated_gif.gif");
FrameDimension dimension = new FrameDimension(
image.FrameDimensionsList[0]);
int frameCount = image.GetFrameCount(dimension);
StringBuilder sb;
// Remember cursor position
int left = Console.WindowLeft, top = Console.WindowTop;
char[] chars = { '#', '#', '@', '%', '=', '+',
'*', ':', '-', '.', ' ' };
for (int i = 0; ; i = (i + 1) % frameCount)
{
sb = new StringBuilder();
image.SelectActiveFrame(dimension, i);
for (int h = 0; h < image.Height; h++)
{
for (int w = 0; w < image.Width; w++)
{
Color cl = ((Bitmap)image).GetPixel(w, h);
int gray = (cl.R + cl.G + cl.B) / 3;
int index = (gray * (chars.Length - 1)) / 255;
sb.Append(chars[index]);
}
sb.Append('\n');
}
Console.SetCursorPosition(left, top);
Console.Write(sb.ToString());
System.Threading.Thread.Sleep(100);
}
}
}
Just for fun :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
class Program
{
static void ConsoleDraw(IEnumerable<string> lines, int x, int y)
{
if (x > Console.WindowWidth) return;
if (y > Console.WindowHeight) return;
var trimLeft = x < 0 ? -x : 0;
int index = y;
x = x < 0 ? 0 : x;
y = y < 0 ? 0 : y;
var linesToPrint =
from line in lines
let currentIndex = index++
where currentIndex > 0 && currentIndex < Console.WindowHeight
select new {
Text = new String(line.Skip(trimLeft).Take(Math.Min(Console.WindowWidth - x, line.Length - trimLeft)).ToArray()),
X = x,
Y = y++
};
Console.Clear();
foreach (var line in linesToPrint)
{
Console.SetCursorPosition(line.X, line.Y);
Console.Write(line.Text);
}
}
static void Main(string[] args)
{
Console.CursorVisible = false;
var arr = new[]
{
@" ________________. ___ .______ ",
@" / | / \ | _ \",
@" | (-----| |----`/ ^ \ | |_) |",
@" \ \ | | / /_\ \ | /",
@" .-----) | | | / _____ \ | |\ \-------.",
@" |________/ |__| /__/ \__\| _| `.________|",
@" ____ __ ____ ___ .______ ________.",
@" \ \ / \ / / / \ | _ \ / |",
@" \ \/ \/ / / ^ \ | |_) || (-----`",
@" \ / / /_\ \ | / \ \",
@" \ /\ / / _____ \ | |\ \---) |",
@" \__/ \__/ /__/ \__\|__| `._______/",
};
var maxLength = arr.Aggregate(0, (max, line) => Math.Max(max, line.Length));
var x = Console.BufferWidth/2 - maxLength/2;
for (int y = -arr.Length; y < Console.WindowHeight + arr.Length; y++)
{
ConsoleDraw(arr, x, y);
Thread.Sleep(100);
}
}
}
精彩评论