views:

838

answers:

2

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!

+6  A: 

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);
        }
    }
}
Philip Daubmeier
Imagine if we just had a backbuffered cmd window =D
Jonas B
@JonasB - what do you mean by backbuffered?
Hamish Grubijan
Wow, this is great! I plan to use it (in Debug mode of course).
Hamish Grubijan
@Hamish it was mostly a joke, backbuffering is a technique you use when you draw to the backbuffer and then swap it to the front in order to reduce flickering hehe
Jonas B
I see ... a multithreaded animation ... why not!?
Hamish Grubijan
+2  A: 

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);
        }
    }
}
VirtualBlackFox
This is a fun thread ... I love it.
Hamish Grubijan