# 5: Side Scrollers

## Illuminations

#### Homework Questions?

• Lab 4: White Blood Cell (9/26/17)
Q4: Finishing Touches (9/28/17)
• Please do not put spaces in folder names of zip files turned in for homework
• The Java compiler has problems with spaces in folder or file names
• Did anyone attempt XC 2? (populate world from array using a loop)

## 5.1: Creating a Scrolling world

### Learner Outcomes

At the end of the lesson the student will be able to:

• Create a scrolling world scenario
• Automatically places tiles in a world
• Scroll tiles as the scenario runs

### 5.1.1: Scrolling Worlds

• The White Blood Cell (WBC) scenario is an example of a scrolling video game

Scenario file: WBC.gfar.

• The first scrolling video game was Kee Games Super Bug released in 1977
• "Super Bug" in this case refers to the Volkswagen Beetle, which was often referred to as a "bug"

#### WBC Character Movement

• WBC action is viewed from a side-angle view
• The main player character (PC) stays mostly stationary
• To create the illusion of motion, the background and other onscreen actors move
• Actors move by calling the `setLocation()` method in combination with `getX()` and `getY()` like:
```setLocation(getX() - speed, getY());
```
• The `getX()` and `getY()` commands return the current (x, y) coordinates
• Recall that Greenfoot Actors are located by a coordinate system that starts in the upper left-hand corner (see below)
• By adding or subtracting an amount of pixels to the current coordinates, the characters moves
• The movement is independent of the direction the character is pointing

#### Methods Controlling Movement

Method Description
getX() Return the x-coordinate of the actor's current location.
getY() Return the y-coordinate of the actor's current location.
move(distance) Move the actor the specified distance in the direction it is currently facing.
setLocation(x, y) Move the actor to the specified location.

#### Check Yourself

1. True or false: the coordinate system used by Greenfoot is the same as that used in algebra.
2. The origin of the (x, y) coordinate system is located at the ________.
1. upper left-hand corner of the window
2. upper right-hand corner of the window
3. lower right-hand corner of the window
4. lower left-hand corner of the window
3. True or false: in the coordinate system used by Greenfoot, locations shown in the window are always positive numbers.
4. To set the location of an actor we call the ________ method, passing arguments for the (x, y) coordinates

### 5.1.2: Creating a Scrolling World

• In this section we create our own scrolling world game named `scroller`
• The first step is to decide on your theme, like Space
• Once we have settled on a theme, we create a `World` subclass
• We open the editor for "MyWorld" and change it to something appropriate like "ScrollWorld"
• We leave the world with no background image ("No image")
• Some scrolling games do have a background image, like WBC
• However, we will supply the background image using scrolling tiles

#### Unbounded Worlds

• By default, Greenfoot does not allow actors to go outside the world
• In our scrolling world game, actors appear on the right and disappear on the left
• This behavior means we will see background actors suddenly appear and disappear at the edges
• WBC solved the problem by adding a border at the edge that hid the odd behavior
• Another option is to change the default behavior and allow actors to move outside the world
• Then we add and remove background actors off screen
• We allow actors to go outside the world by changing our call to `super()` in our `World` subclass
• For instance, in our `ScrollWorld` we can write
```super(600, 400, 1, false);
```
• The fourth variable, `false`, is added to let actors move outside the boundaries of the world

• We continue setting up our game by placing a `Player` character in the game as a reference
• Choose a player character image, any desired image, like `rocket.png`.
• We typically place the character on the left side of the game for a side scroller
• We will add player movement after we have set up the background
• Once we have the player positioned, we right-click on the world background and select the Save the World function
• This creates a `prepare()` method in our world and saves the location of our player

#### Scrolling Backgrounds

• For a scrolling background, we need actors that serve as the background of the game
• The background actors move across the screen to create the scrolling effect
• In the next sections, we will create a tile map for our scrolling background

#### Activity: Starting the Scenario (4m)

1. Choose a theme for a scrolling world game and create a new scenario named "scroller".

Please use the specified names if you want credit because it makes grading easier.

2. Open the editor for the world subclass and change the class name and constructor name to `ScrollWorld` like:
```public class ScrollWorld extends World
{

/**
* Constructor for objects of class ScrollWorld.
*
*/
public ScrollWorld()
// other code omitted
```
3. In addition, set the world to an unbounded state by changing the call to `super()` like:
```super(600, 400, 1, false);
```
4. Create a player character and position it in the world.
5. Right-click on the world background and select the Save the World option.
6. Save your scenario so you can update it in future exercises.

#### Check Yourself

1. True or false: by default, Greenfoot prevents actors from moving outside the world boundaries.
2. If you want an unbounded world, set the fourth parameter of the `World` constructor, which is called using `super()`, to ________.
3. True or false: "off screen" means an actor is outside what can be seen on the game screen.
4. The default background color of a world when no images are selected is ________.

### 5.1.3: Tiles and Tile Maps

• A common approach for developing game worlds is to use tile maps
• A tile map is a technique for generating large graphics from a number of smaller graphics
• Tile maps have been used for many years in games such as the early Legend of Zelda games
• The technique is still popular today because:
1. Tile maps save main computer memory
2. Tile maps increase real-time rendering performance

#### Laying Out Tile Maps

• A tile map breaks down a game world into a grid as shown in the diagram below
• Each cell in the grid contains either a small tile object or nothing

• Tile-based maps are like creating a game world with building blocks
• We use only a few different blocks but we can use as many of each block as we want
• Each tile object in the map contains a reference to the image that belongs in a cell of the grid
• When Greenfoot draws the tile at a location, it takes the referenced image and draws it on the screen
• The program thus uses the same image at many places on the screen
• By reusing the image many times, the program needs to store fewer images
• Thus we only need a few small images to draw an entire scenario

#### Check Yourself

1. For the above image, and ignoring the grid lines, to draw the tile map you need ________ image(s).
2. In the above tile map, the number of time the same image is displayed is ________.
3. Of the following statements, the one that correctly describes how a tile maps saves memory space is ________.
1. tiles are arranged in a two-dimensional grid to create a larger image.
2. not all grids locations are filled with tile objects.
3. the program draws the same small image at multiple places in the world
4. each tile object is smaller than the entire world.

### 5.1.4: Tiles and Constant Variables

• In this section we create a tile background for our scrolling game
• The first step is to create a `Tile` actor and assign it an image
• For example, for our space game we choose the `space.jpg` background for the tile

#### Finding the Image Size

• Once we choose the tile background, we need to know the size of the image
• We will be using the image size to calculate where to place the images in our scenario
• We can usually discover the image size by looking in our scenario's image folder
• Another way to discover the size is to temporarily add the following code to the `act()` method of the `Tile` class
```GreenfootImage img = getImage();
System.out.println("Width: " + img.getWidth());
System.out.println("Height: " + img.getHeight());
```
• By adding a tile to the world and pressing the Act button once, the terminal window displays the image size like:
```Width: 64
Height: 64
```
• The size of the image should be small to conserve memory and increase performance

#### Constant Variables

• Once we know the size of the background image we need to save its size for use in some calculations
• One good way to save the size is to use a constant variable
• A constant variable (or constant) is a variable that cannot change after being assigned a value
• A constant variable seems oxymoronic, but is actually quite useful
• To declare a constant in Java, we use the keyword: `final`
```public static final int WIDTH = 64;
public static final int HEIGHT = 64;
```
• We must assign a value when the constant is declared
• If we tried to assign a value in a later statement, we get a compile-time error
• Notice that the name is all uppercase letters with an underscore separator
• This is a common coding convention that professional programmers follow and you should as well
• The advantage of saving the size in a variable is we can easily change the tile image
• When we make a change, all we will need to do is update the constant and our calculations still work

#### Keyword `static`

• We usually make a constant an instance variable and use the keyword `static`
```public static final int WIDTH = 600;
public static final int HEIGHT = 400;
```
• When used with a variable, the keyword `static` makes a single copy of the variable available to all objects of a class
• The `static` keyword is used because only one constant value is needed for all objects
• After creating the constant variable, we substitute it for all numbers like:
```super(WIDTH, HEIGHT, 1, false);
```
• Then if we ever decide to change the height we can adjust by changing a single number
• Another advantage of using constants is that you can easily tell what the number is for
• Using a constant variable instead of a literal number is a way of documenting what the number means
• Yet another advantage of a constant is that we can declare them `public` if necessary
• Since constants cannot change it is acceptable programming practice to declare them `public`
• When declaring `public` constants, other classes can know the value without causing problems
• Thus in the case of the world size, other classes can easily know the size of the world class using code like:
```int worldWidth = SrollingWorld.WIDTH;
```

1. Start Greenfoot and open the scrolling world scenario from the last Activity.
2. Open the `ScrollWorld` class and record the width and height of the world using two `public static` constant variables like:
```public static final int WIDTH = 600;
public static final int HEIGHT = 400;
```
3. Now update the world size command to use these constant variables in the world constructor like:
```super(WIDTH, HEIGHT, 1, false);
```
4. Next create a `Tile` subclass of `Actor` and assign it an image.
5. Find the width and height of the tile image you chose
6. Record the width and height in two `public static` constant variables in the `Tile` class like:
```public static final int WIDTH = 64;
public static final int HEIGHT = 64;
```

Your `WIDTH` and `HEIGHT` values will depend on the image you selected. We can use the same constant names since we are declaring the variables in different classes.

7. Compile your scenario to make sure the changes were made correctly.

If you have problems, ask a classmate or the instructor for help as needed.

8. Save your scenario so you can update it in future exercises.

#### Check Yourself

1. A better solution than adding the same number to several places in a class is to add a __________ variable.
2. The keyword Java uses to make a variable constant is __________.
3. True or false: you should use named constants rather than literal numbers in your code so you can easily tell what the number means.
4. True or false: constants should be written in lower case letters so you cannot easily tell the variable is constant.

### 5.1.5: Placing Tiles

• Now that we have a tile for the background we need to place the tiles
• We could manually place all the tiles and call the Save the World function
• However, manual placement is a tedious and error prone activity
• Also, what if we decide to change the tile image?
• A better approach than manual placement is to add code that automatically place tiles

#### Calculating Tile Position

• The first tile we want to place is in the upper-left-hand corner of the screen
• We carefully place the tile and check its (x, y) coordinates
• When checking, notice that the coordinates of the first tile are ½ the tile width and height
• This is because Greenfoot calculates the position of an actor from the center of its image
• Thus we can calculate the position of the first tile by adding the following code to the `prepare()` method:
```int leftX = Tile.WIDTH / 2; // leftmost x-coordinate for a tile
int topY = Tile.HEIGHT / 2; // highest y-coordinate for a tile
```
• Notice the use of the `new` operator: `new Tile()`
• As we discussed in lesson 4.2.3, we are constructing a new `Tile` object
• The keyword `new` tells Java to construct a new object from the class
• We use the `World` method `addObject()` to add the new tile object to the world
• To add more tiles, we would place them exactly one tile width to the side until the row is complete
• Then we would add the next row and repeat the placement process to position all the tiles in the world

#### Repeating Calculations with the `for`-Loop

• We need to repeat our calculation for tile locations and place additional tiles
• To repeat code we use `for`-loops and arithmetic to calculate locations
• We can visualize the `for`-loop as a series of steps to reach a goal
• In this case, the steps to reach our goal are the placement of tiles within the grid system of our world
• Recall from lesson 4.2.4 the syntax of the `for`-loop:
```           ❶    ⇛    ❷   ⇚   ❸
for (int i = start; i < end; i = i + 1) {
...
}
```
• Where:
• i: the name of a counter variable
• start: the initial starting value
• end: the final ending value
• As an example, we could place a row of tiles in the world by adding the following code to the start of the `prepare()` method:
```int leftX = Tile.WIDTH / 2;  // leftmost x-coordinate for a tile
int topY = Tile.HEIGHT / 2;  // highest y-coordinate for a tile
int tilesHorz = WIDTH / Tile.WIDTH + 2; // number of tiles across
for (int x = 0; x < tilesHorz; x++)
{
int tileY = topY;
int tileX = leftX + Tile.WIDTH * x;
}
```
• The first two lines calculate the position of the first tile
• The third line calculates the number of tiles needed across the screen
• We add an extra tile to allow tiles to be off screen when being added to or removed from the world
• The `for`-loop counts the number of tiles across one at a time
• Inside the `for`-loop we calculate the new tile's x-coordinate on the first line:
```int tileX = leftX + Tile.WIDTH * x;
```
• The last line of the `for`-loop adds a new tile at the calculated position
• Lets trace the calculation of the x-coordinate of the tile

#### Activity: Tracing the Loop (4m)

```int leftX = Tile.WIDTH / 2; // leftmost x-coordinate for a tile
int topY = Tile.HEIGHT / 2; // highest y-coordinate for a tile
int tilesHorz = WIDTH / Tile.WIDTH + 2; // number of tiles across
for (int x = 0; x < tilesHorz; x++)
{
int tileY = topY;
int tileX = leftX + Tile.WIDTH * x;
}
```

For the above code, trace the loop and enter the first three values of `tileX` and `tileY` into the following table. Assume that `Tile.WIDTH == 64` and `Tile.HEIGHT == 64`. Press the Submit button to record your answer.

Tracing the Loop
`x` `tileX` `tileY`
0
1
2

#### Testing Our Trace

• We should always test to verify our understanding
• In general, we should test our code every time we add a few lines
• To test our tile placement, we right-click a Tile object and select Inspect

#### Filling the Screen

• To finish filling the screen with background tiles we need to calculate the y-coordinate as well the x-coordinate
• First we need to calculate the number of tiles to place vertically:
```int tilesVert = HEIGHT / Tile.HEIGHT + 1; // +1 for top/bottom buffer
```
• We simply divide the world height by the tile height
• Unless the world height is an exact multiple of the tile height, we need to add one more tile
• Once we know the number of tiles, we add another loop around the existing loop as shown below

#### Example Code to Place Tiles in the World

```int leftX = Tile.WIDTH / 2; // leftmost x coordinate for a tile
int topY = Tile.HEIGHT / 2;    // highest y coordinate for a tile
int tilesVert = HEIGHT / Tile.HEIGHT + 1; // +1 for top/bottom buffer
int tilesHorz = WIDTH / Tile.WIDTH + 2;   // +2 for scrolling buffer
for (int y = 0; y < tilesVert; y++)
{
int tileY = topY + Tile.HEIGHT * y;
for (int x = 0; x < tilesHorz; x++)
{
// int tileY = topY;
int tileX = leftX + Tile.WIDTH * x;
}
}
```

#### Nested Loops

• Notice that the above code has a `for`-loop nested inside another `for`-loop
• By analogy, nested loops are like an odometer on a car
• The numbers to the right loop completely before the number to the left increments by one

• The inner loop is like the numbers to the right in the odometer
• An inner loop runs to completion every time the outer loop executes once

#### Analyzing a Nested Loop

• The best way to understand nested loops is to work from the inside out
• The inner loop in our example places all the tiles in a row
```for (int x = 0; x < tilesHorz; x++)
{
int tileX = leftX + Tile.WIDTH * x;
}```
• The outer loop moves the y-coordinate from one row to the next
```for (int y = 0; y < tilesVert; y++)
{
int tileY = topY + Tile.HEIGHT * y;
// inner loop here or call placeRow()
}
```
• Oftentimes people place inner loops inside a method to clarify the logic

#### Check Yourself

1. Instead of repeating statements we can often use a ________.
2. When you clap your hands 10 times:
1. You know when to stop because you ________
2. Every time you clap, the count ________.
3. For the example loop shown below, the loop repeats ________ times.
```for (int counter = 0; counter < 5; counter++)
{
System.out.println(counter);
}
```
4. True or false: the purpose of the variable `counter` in the above loop is to keep track of the number of repetitions.
5. True or false: a loop can be nested inside another loop.
6. By analogy to an odometer, an inner loop is like the digits to the ________.
7. Every time an outer loop iterates once, an inner loop runs ________.
1. completely
2. incrementally
3. partially
4. twice

### 5.1.6: Moving the Tiles

• We can now automatically place the background tiles
• To create the illusion of motion, we move the background tiles
• The player character is more or less stationary
• The tiles move in the opposite direction we want the player character to seem to move

#### Moving the Tiles

• To move the tiles we call `setLocation()` from the `act()` method of `Tile`
```private static final int SPEED = 1; // some values leave gaps

public void act()
{
setLocation(getX() - SPEED, getY());
}
```
• With the above code, every call to the `act()` method moves the tile to the left

#### Wrapping the Tiles

• Within a short time, the tiles will all move left off the screen
• To keep the illusion going, we need to add tiles to the right of the screen
• We can delete old tiles and make new ones as needed, which is the approach used in WBC
• Another technique is to reuse the tiles

#### Reusing Tiles

• To reuse the tiles, we add an `if`-statement to test when the tiles goes off screen
• When the tile goes off screen, we reposition it off screen to the right
• As the `act()` method executes, the repositioned tile eventually moves on screen
• We can see the complete `act()` method in the following code example

#### Example Tile Code for Horizontal Scrolling

```public void act()
{
if (getX() <= -WIDTH / 2)
{
// Reposition tile to use again at the right edge off-screen
int newX = (ScrollWorld.WIDTH / WIDTH + 1) * WIDTH + WIDTH / 2;
setLocation(newX, getY());
}
setLocation(getX() - SPEED, getY());
}
```

### Exercise 5.1: Scrolling the Background (5m)

In this exercise, we do scroll the background of our scrolling world.

#### Specifications

1. Start Greenfoot and open the scroller scenario from the previous Activities:
2. Open the editor for the ScrollWorld class and add the following code to the beginning of the `prepare()` method:
```int leftX = Tile.WIDTH / 2; // leftmost x coordinate for a tile
int topY = Tile.HEIGHT / 2;    // highest y coordinate for a tile
int tilesVert = HEIGHT / Tile.HEIGHT + 1; // +1 for top/bottom buffer
int tilesHorz = WIDTH / Tile.WIDTH + 2;   // +2 for scrolling buffer
for (int y = 0; y < tilesVert; y++)
{
int tileY = topY + Tile.HEIGHT * y;
for (int x = 0; x < tilesHorz; x++)
{
int tileX = leftX + Tile.WIDTH * x;
}
}
```
3. Compile the scenario and verify there are no errors.

You should see the background of the world fill completely with tiles. Resolve any errors you find, getting help from a guild member or the instructor as needed.

4. Open the source code editor of the Tile class and add the following constant to the class:
```private static final int SPEED = 1; // some values leave gaps
```
5. Also in the Tile class, update the `act()` method as shown below:
```public void act()
{
if (getX() <= -WIDTH / 2)
{
// Reposition tile to use again at the right edge off-screen
int newX = (ScrollWorld.WIDTH / WIDTH + 1) * WIDTH + WIDTH / 2;
setLocation(newX, getY());
}
setLocation(getX() - SPEED, getY());
}```
6. Compile and run your scenario to verify all the changes work well.

You should see the background scroll to the left with the player character stationary. If you have problems, ask a classmate or the instructor for help as needed.

7. Save a copy of your final scenario with all the changes made to upload to Canvas as part of the next lab.

We will be adding more code to these files in subsequent exercises, so it is not time to submit them to Canvas yet. However, it is a good idea to have a backup copy in case of problems later in development.

## 5.4: Midterm Preparation

### Learner Outcomes

At the end of the lesson the student will be able to:

• Describe the ground rules for the midterm exam
• Start preparing for the midterm exam

#### Important Midterm Exam Information

Date: 10/5/17
Location: Regular classroom
Start time: During the regular class time

• The exam covers material from the first four lessons
• Exam question types include multiple choice and short programming problems
• You will have about 45 minutes to complete the exam

#### Ground Rules

• You must attend the exam or you will receive a score of zero (0)
• Except by prior arrangement with the instructor
• I am using Canvas to administer the test
• The exam is closed books and closed notes
• However, you may have one 3" x 5" card of handwritten notes for the exam
• You may use a computer from the classroom, but only to take the exam in Canvas
• You may have blank scratch paper
• You may NOT use the computer to compile or run programs
• You may NOT use the computer to view documents on the Internet
• You may NOT use a cell phone, calculator or other electronic device
• Thus, you may NOT use your own computer to take the exam
• If you have a cell phone visible or in use during the exam, you will automatically fail
• You may NOT communicate with anyone but the instructor during the exam

#### 3"x5" Card Requirements

• Maximum card or paper size is 3 inches by 5 inches
• You may use both sides of the card
• Notes must be handwritten and NOT photocopied
• No more than three statements in a sequence on the card — only snippets
• Any 3" x 5" cards violating these rules will be confiscated before the test
• You must turn in your 3" x 5" card after the exam in any case

### 5.4.2: Test Preparation Self Assessment

#### Discussions Questions

• How are these practices beneficial?
• What are your successful strategies for exam preparation?
• How much time do you dedicate to test preparation?

### 5.4.3: How to Study for the Exam

• No one can ace a test without studying and understanding the material
• To get an "A" you need to thoroughly prepare for the test well in advance
• With the midterm approaching, you have a choice:
• Study and do well, or
• Not study and do less than your best
• Victims are people who let their lives control them, like a pawn on a chessboard
• Creators are people who controls their own life, like a person playing chess
• You can take responsibility for studying and do well on a test
• Or you can make excuses and do less than you are capable of on a test

Here are some steps you can take to improve your test results:

1. Compile a list of topics you might be tested on.

Look over your quests, labs, and lecture notes to determine what we covered. Write a list of topics from these sources.

2. Make sure you understand all the topics on your list.

Correct any mistakes you may have made in your quests, labs or boss events.

3. Identify the most probable exam topics for thorough study.

To do well, you need deep understanding of the test topics. Gaining a deep understanding takes time. Often you can tell what is on a test simply by which topics the instructor spends the most time talking about.

4. Create a list of possible test questions.

Turn headings from the textbook and lecture notes into questions. Look at the section summaries in the lectures and read the Check Yourself questions.

5. Study your questions over and over until you know them perfectly.

Make flash cards (or use an app) with questions on one side and answers on the other. Carry the cards with you and review them when you have a few minutes available. Have other people ask you questions from your flash cards. Do practice problems to gain a an even deeper understanding of coding techniques.

6. Prepare your 3"x5" card of test notes.

Since the instructor allows a 3"x5" card, make use of it. For the topics you had the most trouble with, write down a short note or summary. If the pressure of the test causes you to forget something, you can refer to your card.

### Exercise 5.4: Preparing Exam Questions (3m)

Take three minutes to review and choose one of the following topics for Lab 5. Post the questions in the Discussions area of Canvas titled "Midterm 1 Study Questions" for XP.

If there are fewer topics than students, you can reselect a topic. However, there cannot be more than two posts per topic and all the questions for a post must be unique. Thus if two people select the same topic, the second person who posts on the topic must have different questions than the first person.

#### Exam Topics

1. Objects, instances and class diagrams (1.3.4, 2.1.3)
2. Calling methods and returning values (1.3.5, 3.4.3)
3. Calling methods with parameters (1.3.6, 3.4.4)
4. Creating `World` and `Actor` subclasses (2.1.3, 2.1.4, 2.1.5)
5. Actor movement, rotation and API methods (2.2.5, 2.2.6, 2.4.2)
6. Coding `if`-statements (2.3.2, 3.2.3, 4.3.6, 4.3.7, 4.4.2)
7. Errors and debugging (2.3.3, 2.3.4)
8. Variable declaration, assignment and order (2.4.1, 3.1)
9. Defining new methods (2.4.2, 2.4.3, 3.4)
10. Random numbers and applications (3.2.1, 3.2.2, 3.2.4, 3.2.5)
11. Relational operators (3.2.3, 3.2.5)
12. Simple actor interaction (3.3)
13. Strings (3.5.1, 3.5.2)
14. Responding to keyboard input (3.5.2)
15. Playing sounds and stopping (3.5.3, 3.5.4)
16. Coding constructors (4.2.1, 4.3.5)
17. Creating and adding objects to the world (4.2.3, 4.2.2)
18. Coding `for`-loops (4.2.4)
19. Animation (4.3)
20. Instance variables versus local variables (4.3.4)
21. Reference variables (4.3.5)
22. Counting, numbers and arithmetic (4.4)

### 5.4.4: More Test Preparation

• To help you study, you can use this review game: Greenfoot Jeopardy
• Must view in Internet Explorer (not Edge, Chrome or Firefox)
• Do NOT update Java before playing Greenfoot Jeopardy
• Press the Run button
• Start the game with the "basics.txt" file

#### Practice Exam

• To help your understanding of how the midterm will operate, I am providing a practice exam in Canvas
• The questions are intended to help you get a "feel" for taking an exam in Canvas
• The questions are NOT intended to tell you everything that is on the exam
• Suggestion: prepare first and then try the practice exam
• This will give you a better understanding of how much more preparation you need

#### Exam Taking Tips

• If you get stuck on a question, make your best guess and return later
• If you are equally uncertain between two choices, go with your first impression
• When writing code, do NOT add more than the problem asks for
• You do not need to comment code for tests and exams
• Unless specifically instructed to in the exam question
• Use the full time available
• Check your work if you finish early
• Any questions?

## Wrap Up

Due Next:
Q4: Finishing Touches (9/28/17)
Lab 5: Test Questions (10/3/17)
Q5: Basic Arcane Studies (10/5/17)