CS 70

Homework 3: Define and Implement the Asciimation Class

In the previous parts, you saw the BoundingBox, Sprite and Display classes. Now it's time to put them together in the Asciimation class, which will manage the overall animation.

What the Asciimation Class Does

The job of the Asciimation twofold:

  • It acts as a framebuffer, storing the content that needs to be shown on the display.
  • It acts as a sprite manager, putting the content of one or more Sprite objects into the framebuffer at the right locations.
  • Cat speaking

    I'm a bit confused here. Isn't the Display class already handling the framebuffer stuff?

  • LHS Cow speaking

    The Display class models real displays in that it is an output device. When we send characters to the Display, they will be shown on the screen, but we can't read back what is currently on the screen. The Asciimation class holds a copy of what we want to show on the screen, and when we call its copyToScreen function, it sends that content to the Display.

  • RHS Cow speaking
  • LHS Cow speaking

    In this Step, we will fill in the definition for an Asciimation class. For now, it'll contain a single Sprite object that it'll draw to the screen. In the next assignment, we'll have more than one Sprite.

Your Task

  • RHS Cow speaking

    The Asciimation class should have the following private data members:

  • LHS Cow speaking
    • An array of characters of length MOVIE_WIDTH * MOVIE_HEIGHT that holds all of the currently displayed characters
  • RHS Cow speaking
    • A Sprite object that will be displayed (our one and only “actor”!)
  • LHS Cow speaking

    Your Asciimation class should also have a parameterized constructor that takes in the name of a file with the content of a Sprite and a starting position (topLeftRow and topLeftColumn), then uses them to initialize the Sprite data member.

  • RHS Cow speaking

    The Asciimation class also has two public static constants:

  • LHS Cow speaking

    ```c++

  • RHS Cow speaking

    static constexpr int MOVIE_WIDTH = 80;

  • LHS Cow speaking

    static constexpr int MOVIE_HEIGHT = 40;

  • RHS Cow speaking

    ```

  • LHS Cow speaking

    These define the size of our animation display area.

  • RHS Cow speaking

Helpful Hints

  • LHS Cow speaking

    Here are some hints for the Asciimation class.

Accessing a Static Member

You can access a class's static member variable using the class name and the scope-resolution operator; for example, ClassName::variableName.

Initializing the Sprite

Remember that the default constructor for the Sprite class is disabled! When (and how) should we initialize the Sprite data member so that not having a default constructor won't cause us problems?

Once you've finished this step, you should be able to compile and link everything again—but you will still get warnings about unused variables because you haven't implemented everything needed in the Asciimation class yet.

Use the Member-Initialization List

To receive full idioms points, your constructor must properly use the member-initialization list. You can read about this expectation in Section 4.1 of the CS 70 Idioms Page, and you can read more about member-initialization lists in the lessons and in Chapter 1.1 of the Unofficial CS70 textbook.

Name Your Data Members Correctly

You should name your Sprite data member sprite_ to be consistent with other parts of the starter code.

To Complete This Part of the Assignment

You'll know you're done with this part of the assignment when you've done all of the following:

Background: How Animation Works

Animation is a medium in which successive still images are rapidly presented one-after-another to give viewers the impression of smooth movements. To understand how this process works, imagine being presented with a still photograph of an object in motion. Then, a short while later, imagine you were shown another image of the same motion in progress (and then another, and another). As the delay between seeing the photographs decreases, the depicted motion would begin to appear smoother—it would be as if you were watching the original motion itself rather than a series of snapshots. The point at which a viewer perceives smooth motion from successively presented still images is known as the flicker-fusion threshold. It occurs for most humans when these images (known as frames) are presented at a rate of about 10–15 still images per second.

In traditional animation, frames might be drawn directly onto celluloid (“cel” animation), photographed physical objects (as in plasticine or clay animation), or “rendered” with computers (where each frame is computed from various data sources). But for this assignment we will be using the terminal to display our animation.

What's Already Done

We've given you an implementation for the play member function in the Asciimation class. It controls a loop to update and display a movie until the user exits by pressing q. You shouldn't need to modify this code at all, but you should read through it and make sure you understand how it works.

The content that is displayed by play is determined by a few other member functions of the Asciimation class:

  • clearContents wipes out whatever was on the screen in the previous step by stepping through the character array and replacing everything with spaces.
  • updateContents copies characters from the movie's sprite to its character array. It should first call clearContents. Then it should loop through all of the characters in the sprite using its getCharAt function, placing each character at the right spot in the movie's character array.
  • copyToScreen copies characters from the movie's character array to the screen. It should use the ncurses function mvaddch to copy each element of the movie's character array to the right spot on the screen.

Your Task

Complete the implementation of these three functions to make the display system work:

  1. clearContents: This private member function should loop through the entire character array and set each character to a space (' ').

  2. updateContents: This function should:

  3. First call clearContents to clear the display
  4. Then loop through each row and column of the sprite
  5. For each character, check if it would be visible on screen (considering the sprite's position)
  6. If visible, copy the character from the sprite to the appropriate position in the movie's character array

  7. copyToScreen: This function should:

  8. Loop through each position in the movie's character array
  9. Use mvaddch to place each character at the correct screen position

Helpful Hints

  • RHS Cow speaking

    Here are some tips for implementing the display functions!

Using mvaddch

The way you use mvaddch is: mvaddch(row of character to add, column of character to add, character to add);

For example:

mvaddch(5, 10, 'X');  // Places an 'X' at row 5, column 10

Coordinate Calculations

When implementing updateContents, you'll need to:

  • Calculate where each sprite character should go in the movie array
  • Check if the sprite character is within the bounds of the movie display
  • Handle cases where the sprite is partially off-screen

Array Indexing

Remember that both the sprite and movie arrays are one-dimensional. You'll need to convert between 2D coordinates (row, column) and 1D array indices. The formula is:

index = row * width + column

Testing Your Display

Once you've implemented these functions, you can test them by running your program. The sprite should appear on screen (though it won't move yet—that comes in Part 7).

To Complete This Part of the Assignment

You'll know you're done with this part of the assignment when you've done all of the following:

(When logged in, completion status appears here.)