15

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!

2
  • Just updated my answer. Have fun :) Commented Apr 27, 2010 at 22:52
  • Hmm, it's the very definition of flicker, not a single "pixel" is the same from one frame to the next. Move it fast. Commented Apr 27, 2010 at 23:02

2 Answers 2

22

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);
        }
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Imagine if we just had a backbuffered cmd window =D
@JonasB - what do you mean by backbuffered?
Wow, this is great! I plan to use it (in Debug mode of course).
@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
No bit flipping in console. :(
14

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);
        }
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.