We already have some of the code for animating a boat and a plane in our program. Now let's actually add those images.
The original "sl" program doesn't have these images, and I'm not an artist, so I went Googling for ASCII art boats, and came up with this:
|\
| \
| \
|___\
\--|----/
\_____/
There was lots of artwork to choose from, but I wanted to keep it simple. I would have preferred that the sail pointed to the left instead of to the right, but beggars can't afford to be starving artists, right? Or something like that.
However, rather than add this as a constant to our existing "images.rs" file as you might expect us to do, there's a new trick I just learned, which I'd like to try.
Put this image into its own text file, named "boat.txt" (making sure to get the spacing in the lines even, like in the image below:
You'll recall that earlier we decided against putting each drawing in its own text file, because those text files would then have to follow the program and be find-able by the program, which increased the chances that the program would work as we wanted it to. But with this new technique, using the "include_str!()" macro, we can read a text file at compile time, which means the text file only has to be with the source code, and find-able, when the program is compiled. Once compiled, the executable is standalone, and no longer needs access to the text file. It's a Win-Win!
So now that we have the art in its own file, "boat.txt", adding it to our program is ridiculously easy:
Run the program with a command like $ cargo run -- --kind=boat and watch the craft sail across your screen.
Notice, however, that if you don't have a blank line at the top of the drawing, then the top of the sail is broken. This is because our other images have a newline at the top of the image, which our program then strips out by stripping out the first character of the string that it reads as a constant. Our program doesn't know not to strip the first character out of this constant. The easy fix is just to add a blank line to the top of this image:
Also notice that there are not side-delimiting single-quote marks. The way our program is written, these are optional. The program will strip them out if they're found, and will do nothing if they're not found. I prefer to have them in the original art; it makes it easier to see the limits of the drawing:
Also notice that if you don't have a newline after the final single-quote, our program does strip out that final single-quote, leaving a "blip" in the animation. Let's add that space, and a correction to our instructions to the ASCII-artists (with text-justification adjustments in blue.
Adding a plane is just as easy. Start by finding a suitable ASCII-art image, and saving it to its own file, such as "plane.txt". I found the first frame below on line, and then duplicated that for the other three frames, and made adjustments to the propellor on frames 2 and 3 for animation purposes.
and add the appropriate changes to "get_options.rs":
and then fly to your heart's content.
You can even get fancier if you desire. Notice I did not add the single-quote marks to the image that I found on the 'Net. Again, I found the first image, added some propeller "action" marks, then duplicated it three more times, and then "tweaked" the propeller action-marks in the last three to make them distinct.
Even though we did not plan ahead to make the twin-engine plane an option on the command-line, in our "Args" struct, the program still honors the option. This is because the "Args" struct merely defines the argument and the type of data it can handle, but it does not define what the contents can be, and our "Set 'kind'" match statement is able to handle the otherwise-unknown "t" option. There's really nothing in the "Args" struct that would limit what can be entered in as the "kind"; we could use a command like cargo run -- --kind gorilla, and the Clap system would happily pass that on to our program; it's our "Set 'kind'" match section that really determines what can and can't be entered. But still, if we want the help screens to be accurate, we should touch the doc-line in the "Args" struct:
See if you can add this large and detailed motorcycle:
Hint: For the match statement, you might try: "M" | "CYCLE" | "MOTORCYCLE" => (String::from("CYCLE"), CYCLE.to_string(), "".to_string()),
.
My first attempt crashed, because I had two blank lines at the start of the image, instead of just one, and my second attempt crashed, because there are two missing spaces at the end of the last line. Ideally, our program would check for dirty data like these two things, but we're not going to do that in this tutorial.
This project is pretty close to complete. Let's work on just a few more things: making the tailing coalcar optional, implementing an accident mode, and creating some smoke patterns. Let's start by Making the Coalcar Optional.