views:

414

answers:

3

I have to write a text image program in C for a class. Nothing complicated just write an image using text.

In regards to this: towel.blinkenlights.nl, how can I animate my text?

+2  A: 

What platform is this for? If you want something multiplatform, I would suggest you use ncurses.

If its just for Windows, you can probably use conio.h and graphics.h among others. I found this which seem to have some basic drawing/animating examples in C using some Windows headers. Be advised that this is extremely unportable code and Windows specific.

Update: I also found this which includes a few examples in using graphics.h

nmuntz
I do not want graphics to be displayed, but using text characters to look like graphics.
HollerTrain
ncurses and conio are for exactly that. Well, not just for that, but they are ways to manipulate on-screen characters with much more control than by simply printing lines. One thing they can do is "animate" characters.
Tyler McHenry
A: 

If you're allowed to use external libraries, AALib looks like it would help. If not, you could probably use the system() function and pass "cls" (I'm assuming Windows here. For Linux or Mac, use "clear"):

#include <stdlib.h>
#ifdef WIN32
    system("cls");
#else
    system("clear");
#endif

After that, it should be a simple job to print out a frame and wait until it's time to print the next one.

computergeek6
+2  A: 

Here's an example to show you how to animate something. This is exactly what that Star Wars animation is. It's a gigantic text file split up into individual frames. Read the FAQ at the Star Wars ASCIImation page to find out more about it.

The general idea is that you have a set of frames. Each frame contains one image in the animation. You clear the screen, show a frame, and then wait for some time period. Do that over and over, and you have a text animation.

So first you create a file with your frames. Call it frames.txt. To allow variable-length frames, we follow each frame by a line that begins with @! followed by the number of animation ticks that frame should stay on the screen. For example, if you're drawing at 15 frames per second and the line is @! 15, then the frame will be on screen for 1 second (15 ticks).

+---------+
| frame 1 |
+---------+
@! 15
.-----------.
| frame 2   |
|           |
`-----------'
@! 15
+-------------+
| frame 3     |
|             |
|             |
|             |
+-------------+
@! 15
.-----------.
| frame 4   |
|           |
.-----------.
@! 15
+---------+
| frame 5 |
+---------+
@! 3
+---------+
|  rame 5 |
+---------+
@! 3
+---------+
|   ame 5 |
+---------+
@! 3
+---------+
|    me 5 |
+---------+
@! 3
+---------+
|     e 5 |
+---------+
@! 3
+---------+
|       5 |
+---------+
@! 3
+---------+
|         |
+---------+
@! 3

Then compile and run this program. On Linux or OSX, I just save it as *text_animate.cpp* and run *make text_animate*. On Windows maybe the only thing you'll have to do is change the line that says system("clear") to system("cls"), but I don't know for sure.

#include <iostream>
#include <string>
#include <ctime>
#include <fstream>

const char *FRAME_DELIM = "@!";
unsigned int FRAME_DELIM_LEN = strlen(FRAME_DELIM);

int main(int argc, char *argv[]) {
    if( argc != 2 ) {
        std::cout << "Usage: text_animate <frames file>\n";
        exit(1);
    }
    std::string frames_fn = argv[1];
    struct timespec sleep_time = {0, 1000000000 / 15}; // 15 fps

    std::ifstream file_stream;
    file_stream.open(frames_fn.c_str(), std::ios::in);
    if( !file_stream.is_open() ) {
        std::cout << "Couldn't open [" << frames_fn.c_str() << "]\n";
        return -1;
    }

    std::string frame_line;
    unsigned int frame_ticks = 0;
    while( true ) {
            system("clear");

            bool is_frame_delim = false;
            do {
                getline(file_stream, frame_line);
                if( file_stream.fail() && file_stream.eof()) {
                    file_stream.clear();
                    file_stream.seekg(0, std::ios::beg);

                    getline(file_stream, frame_line);
                }
                else if( file_stream.fail() ) {
                    std::cout << "Error reading from file.\n";
                    break;
                }

                is_frame_delim = strncmp(frame_line.c_str(),FRAME_DELIM,
                                         FRAME_DELIM_LEN) == 0;
                if( !is_frame_delim ) {
                    std::cout << frame_line << "\n";
                }
            } while( !is_frame_delim );

     frame_ticks = atoi(&(frame_line.c_str()[FRAME_DELIM_LEN + 1]));

     while( frame_ticks-- > 0 ) {
                    nanosleep(&sleep_time, NULL);
     }
    }

    file_stream.close();

    return 0;
}

Then just run ./text_animate frames.txt. Press CTRL-C to exit since it loops forever.

indiv