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.
I'm a bit confused here. Isn't the
Display
class already handling the framebuffer stuff?The
Display
class models real displays in that it is an output device. When we send characters to theDisplay
, they will be shown on the screen, but we can't read back what is currently on the screen. TheAsciimation
class holds a copy of what we want to show on the screen, and when we call itscopyToScreen
function, it sends that content to theDisplay
.In this Step, we will fill in the definition for an
Asciimation
class. For now, it'll contain a singleSprite
object that it'll draw to the screen. In the next assignment, we'll have more than oneSprite
.
Your Task
The
Asciimation
class should have the following private data members:- An array of characters of length
MOVIE_WIDTH * MOVIE_HEIGHT
that holds all of the currently displayed characters
- An array of characters of length
- A
Sprite
object that will be displayed (our one and only “actor”!)
- A
Your
Asciimation
class should also have a parameterized constructor that takes in the name of a file with the content of aSprite
and a starting position (topLeftRow
andtopLeftColumn
), then uses them to initialize theSprite
data member.The
Asciimation
class also has two public static constants:```c++
static constexpr int MOVIE_WIDTH = 80;
static constexpr int MOVIE_HEIGHT = 40;
```
These define the size of our animation display area.
Helpful Hints
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.
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 callclearContents
. Then it should loop through all of the characters in the sprite using itsgetCharAt
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 thencurses
functionmvaddch
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:
-
clearContents
: This private member function should loop through the entire character array and set each character to a space (' '). -
updateContents
: This function should: - First call
clearContents
to clear the display - Then loop through each row and column of the sprite
- For each character, check if it would be visible on screen (considering the sprite's position)
-
If visible, copy the character from the sprite to the appropriate position in the movie's character array
-
copyToScreen
: This function should: - Loop through each position in the movie's character array
- Use
mvaddch
to place each character at the correct screen position
Helpful Hints
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).
(When logged in, completion status appears here.)