13: NPCs and Files

What We Will Cover


Illuminations

Questions from last class or the Reading?

Homework Questions?

What to take next?

13.1: Creating Non-Player Characters

Learner Outcomes

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

  • Add non-player characters to a scenario
  • Resolve collisions between the player and NPCs
  • Discuss how to override a method
  • Describe the state of a sprite
  • Describe the purpose of a copy constructor

13.1.1: Adding Non-Player Characters

  • The hero of our platform scenario is all alone in his world
  • To make the scenario more interesting, we add non-player characters (NPCs)
  • A non-player character is any character not controlled by a human player
  • In a video game, the NPC is usually controlled by the computer
  • To develop an NPC, we generally follow these steps:
    1. Decide on the purpose of the NPC in the game
    2. Decide on the actions of the NPC and how it will interact with the player
    3. Make and load the animations
    4. Create a subclass for the NPC
    5. Code the actions of the NPC into its class
  • We will develop an example NPC in the following sections

Adding NPCs to a Scenario

  • Let us look at an example scenario with NPCs
  • We start by downloading and starting the Platformer 4 scenario:
  • Scenario file: platformer4.zip.

  • Save the file to a convenient location like the Desktop and unzip the file
  • Double-click the project.greenfoot file in the unzipped folder to start Greenfoot and open the scenario
  • We will add or change these classes:
    • Creature: a new superclass for NPCs
    • Gorilla: an new class showing an example NPC
    • GameManager: add Gorillas to the scenario
    • Player: add support for dying
    • Sprite: add support for tracking state

Finding the Player

  • One common problem in a scenario is obtaining a reference to a particular object
  • For example, when an NPC runs into a player, the player dies
  • To start the player dying, the NPC needs to call a method of the Player class
    player.startDying();
  • Our NPC needs a reference to the player to call this method

Getting a Reference to the Player

  • One easy way to get a reference to the player is to track the player in GameManager
    private Player george;
    
  • When the GameManager adds a player to the scenario, the player object is assigned to the player variable
    george = new Player();
    addObject(george, getWidth() / 2, 0);
    
  • Then we add a getPlayer() method to the GameManager
    public Player getPlayer()
    {
        return george;
    }
    
  • Now when an NPC needs a reference to the player, it can get it from the GameManager
    GameManager world = (GameManager) getWorld();
    Player p = world.getPlayer();
    

Try It: Getting the Player (4m)

  1. Download the following scenario file, save it to a convenient location like the Desktop and unzip the file.

    Scenario file: platformer4.gfar or platformer4.zip.

  2. Double-click the project.greenfoot file in the unzipped folder to start Greenfoot and open the scenario.
  3. Open the editor for the GameManager class and verify the following instance variable exists:
    private Player george;
    
  4. Add the following method to the GameManager class.
    public Player getPlayer()
    {
        return george;
    }
    
  5. Compile the scenario to verify you implemented the changes correctly.
  6. Test the change by right-clicking on the world background sky and selecting the getPlayer() method.

    You will see a popup box explaining what was returned.

  7. Save your updated scenario as we will be adding to it as the lesson continues.
  8. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. Of the following, ________ is an NPC.
    1. a player character
    2. a sprite controlled by the game player
    3. a sprite controlled by the computer
    4. a background image like a sign
  2. True or false: sometimes an actor needs to call methods of another actor.
  3. True or false: one convenient way to access an actor is to keep track of the actor in the scenario world.
  4. True or false: getWorld() returns the current subclass of world as a World object.
  5. The following code causes a compiler error:
    GameManager world = getWorld();
    Enter the code to correct the problem.

    answer

13.1.2: The State of a Sprite

  • When we have characters interact in a scenario, things happen to them (like getting blown up)
  • To track what is happening, we add the ability to track the state of a sprite

    State: a mode or condition of being

  • For example, a sprite like our player may be alive, dying or dead
  • To keep track of the ever changing state of a sprite, we add a variable and two methods to the Sprite class
    private int state;
    
    public void setState(int newState)
    {
        state = newState;
    }
    
    public int getState()
    {
        return state;
    }
    private void updateDyingState()
    {
        // Method stub to be completed later
    }
    
  • We define the meaning of the state integer in the subclasses

The Player's State

  • To track the state of the player, we add the following state variables in the Player class:
    public static final int STATE_NORMAL = 0;
    public static final int STATE_DYING = 1;
    public static final int STATE_DEAD = 2;
    
  • When the Player changes state, we set a new value like:
    setState(STATE_DYING);
  • To test the state of the Player, we write code like:
    if (getState() == STATE_DYING)
    {
        updateDyingState();
    }
    
  • For example, we add the following method to find out if a player is alive

Player Methods Using State

/**
 * Returns true if this player is alive, false otherwise.
 *
 * @return true if this player is alive, false otherwise.
 */
public boolean isAlive()
{
    return (getState() == STATE_NORMAL);
}

/**
 * Start the dying sequence.
 */
public void startDying()
{
    stopMoving();
    setState(STATE_DYING);
}

Try It: Adding State (3m)

  1. Start Greenfoot and open the scenario from the last Try It! exercise.

    If you did not keep the scenario, then complete Try It: Getting the Player now and then continue with these instructions.

  2. Open the editor for the Sprite class and add the state variable.
    private int state;
    
  3. In addition, add the following two methods to the Sprite class:
    public void setState(int newState)
    {
        state = newState;
    }
    
    public int getState()
    {
        return state;
    }
    
  4. Compile the scenario to verify you added the code correctly.
  5. Open the editor for the Player class and add the following constants:
    public static final int STATE_NORMAL = 0;
    public static final int STATE_DYING = 1;
    public static final int STATE_DEAD = 2;
    
  6. In addition, add the following methods to the Player class:
    public boolean isAlive()
    {
        return (getState() == STATE_NORMAL);
    }
    
    public void startDying()
    {
        stopMoving();
        setState(STATE_DYING);
    }
    
    private void updateDyingState()
    {
        // Method stub to be completed later
    }
    
  7. Finally, update the act() method as follows:
    public void act()
    {
        if (getState() == STATE_DYING)
        {
            updateDyingState();
        }
        else
        {
            checkKeys();
            checkCollisionHorizontal();
            checkVertical();
        }
        move();
    }
    
  8. Compile the scenario to verify you implemented the changes correctly.
  9. Save your updated scenario as we will be adding to it as the lesson continues.
  10. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. What is meant by state? Give an example. (an answer)
  2. The two methods used to keep track of a sprite's state are ________ and ________.
  3. What are examples of states that may be appropriate for a sprite in a game?
  4. True or false: we add method stubs to our code as a placeholder until we complete the method body.

13.1.3: Creature Features

  • All NPCs are sprites and we want to add several NPCs to our game
  • To make it easy to add multiple NPCs, we add a general superclass named Creature

    Creature inheritance hierarchy

  • Then we subclass Creature to create individual NPCs like Gorilla

Creating the Creature Superclass

  • The Creature superclass provides a common set of code, making it easier to create multiple NPCs
  • Since Creature is a subclass of Sprite, it supports state and has a move() method
  • In addition, Creature implements the methods described below to support moving and dying
  • Also, Creature has a predefined set of actions taken in the act() method as shown below
  • To code an NPC, simply write two constructors as shown in the Gorilla class

Constructors and Methods of the Creature Superclass

Constructor/Method Description
Creature() Constructs a creature with no animations.
setAnimations(animLeft, animRight, dyingLeft, dyingRight) Sets the animations and default values for moving, collisions with the player and dying.
act() Move this sprite within its specified range and track the process if it dies.
moveLeft() Move to the left.
moveRight() Move to the right.
processCollision() Decide on the effects of a collision with the player and process accordingly.
setDyingTime(intNewTime) Set the number of act() method calls the dying animation is displayed.
startDying() Start the dying sequence.
setRangeX(leftX, rightX) Set the movement range from the leftmost to the rightmost x-coordinate.

Default act() Method

public void act()
{
    if (getX() <= leftX)
    {
        moveRight();
    }
    else if (getX() >= rightX)
    {
        moveLeft();
    }
    GameManager world = (GameManager) getWorld();
    Player p = world.getPlayer();
    if (intersects(p))
    {
        processCollision();
    }
    if (getState() == STATE_DYING)
    {
        updateDyingState();
    }
    move();
}

Overriding the act() Method

  • We can write a method in a subclass that has the same signature as a superclass
  • This is referred to as overriding a method
  • To override a method, both the superclass and subclass method must have the same method signature
  • If we want to change the action of an NPC, we can override the act() method of the Creature superclass

Try It: Adding Creature Features (3m)

  1. Start Greenfoot and open the scenario from the last Try It! exercise.

    If you did not keep the scenario, then complete Try It: Adding State now and then continue with these instructions.

  2. Download the Creature class and save it in the main scenario folder.

    If you have problems, ask a guild member or the instructor for help.

  3. Restart Greenfoot and then open and inspect the new Creature class to verify you downloaded it correctly.
  4. Save your updated scenario as we will be adding to it as the lesson continues.
  5. When finished please help those around you.
  6. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. The two public methods of the Creature class that support dying are ________ and ________.
  2. By default, an NPC will move back and forth between two endpoints. To set the endpoints, call the method ________.
  3. The method called in act() to check for a collision with the player is named ________.
  4. To change the default behavior of an NPC, override the ________ method.

13.1.4: Creating an NPC

  • Our first NPC is a gorilla whose purpose is to act as a guardian
  • Our gorilla will move back and forth patrolling an area
  • If the gorilla hits (touches) a player, then the player dies
  • If the player jumps on the gorilla, then the gorilla dies
  • We get the images for the animations, shown below, from Ari Feldman's SpriteLib
  • Notice that each set of images are the same size and that the size for a set is as small as possible
  • Having all images the same size helps align the animation sequence
  • Minimizing transparent pixels around the image reduces the appearance of separation during collisions

Gorilla Animation Images

Moving
Gorilla 1 Gorilla 2 Gorilla 3
Dead
Gorilla dead

Setting Up the Animation

  • We add a Gorilla class as a subclass of Creature with "Gorilla1.png" as the image
  • To start our Gorilla class, we add variables for the movement speed and animation images:
    // Default values
    private static final double MOVE_SPEED = 0.75;
    private static final int DYING_TIME = 60;
    private static final int MOVE_COUNT = 3;
    private static final int MOVE_COUNT_PER_FRAME = 8;
    
    // Cache images for multiple instances.
    private static GreenfootImage[] moveLeftImgs;
    private static GreenfootImage[] moveRightImgs;
    private static GreenfootImage dieLeftImg;
    private static GreenfootImage dieRightImg;
    
  • The GreenfootImage variables will cache our images for multiple Gorilla objects
  • We create our animations using the technique covered in lesson 8.2.2 and lesson 12.2.3
  • We load and cache the images using the code shown below

Method to Load the Images in Gorilla

public static void initializeImages()
{
    if (moveLeftImgs == null || moveRightImgs == null)
    {
        moveLeftImgs = new GreenfootImage[MOVE_COUNT];
        moveRightImgs = new GreenfootImage[MOVE_COUNT];
        for (int i = 0; i < moveRightImgs.length; i++)
        {
            String fileName = "gorilla" + (i + 1) + ".png";
            moveLeftImgs[i] = new GreenfootImage(fileName);
            moveRightImgs[i] =
                new GreenfootImage(moveLeftImgs[i]);
            moveRightImgs[i].mirrorHorizontally();
        }
    }
    if (dieLeftImg == null || dieRightImg == null)
    {
        dieLeftImg =
            new GreenfootImage("gorilla-dead.png");
        dieRightImg = new GreenfootImage(dieLeftImg);
        dieRightImg.mirrorHorizontally();
    }
}

Coding the Constructor

  • To finish our Gorilla class we only need to add a constructor
  • The constructor simply sets animation images, number of cycles to show each frame and number of cycles over which the NPC dies
  • Unless we decide to add more behavior, we need only these two methods in an NPC class:
    • Constructor
    • initializeImages()

Gorilla Constructor

public Gorilla()
{
    initializeImages();
    setAnimations(moveLeftImgs, moveRightImgs, dieLeftImg, dieRightImg);
    setMoveFrameCount(MOVE_COUNT_PER_FRAME);
    setDyingTime(DYING_TIME);
}

Scrolling with NPCs

  • One other complication we run into when adding NPCs is scrolling
  • As the world scrolls, we need to update the range of the NPC's movement
  • We use the instanceof operator to test for a Creature
  • When we find a Creature we update its range of movement

Updated scrollHorizontal() that Changes NPC Ranges

public void scrollHorizontal(double dx)
{
    List<Actor> actors = getObjects(null);
    for (Actor a : actors)
    {
        if (a instanceof Player)
        {
            // Allow smooth moving of Player
            Player p = (Player) a;
            double moveX = p.getExactX() - dx;
            p.setLocation(moveX, p.getExactY());
        }
        else if (a instanceof Creature)
        {
            Creature c = (Creature) a;
            // Allow smooth moving
            c.setLocation(c.getExactX() - dx, c.getExactY());
            // Set endpoints
            int leftX = (int)Math.round(c.getLeftX() - dx);
            int rightX = (int)Math.round(c.getRightX() - dx);
            c.setRangeX(leftX, rightX);
        }
        else
        {
            int moveX = (int) Math.round(a.getX() - dx);
            a.setLocation(moveX, a.getY());
        }
    }
}

Try It: Adding a Gorilla NPC (6m)

  1. Start Greenfoot and open the scenario from the last Try It! exercise.

    If you did not keep the scenario, then complete Try It: Adding Creature Features now and then continue with these instructions.

  2. Create a new subclass of Creature named Gorilla with "Gorilla1.png" as the image.
  3. Open the editor for the Gorilla class and add the following constants and instance variables:
    // Default values
    private static final double MOVE_SPEED = 0.75;
    private static final int DYING_TIME = 60;
    private static final int MOVE_COUNT = 3;
    private static final int MOVE_COUNT_PER_FRAME = 8;
    
    // Cache images for multiple instances.
    private static GreenfootImage[] moveLeftImgs;
    private static GreenfootImage[] moveRightImgs;
    private static GreenfootImage dieLeftImg;
    private static GreenfootImage dieRightImg;
    
  4. Delete the act() method as the Gorilla uses the act() method in Creature.
  5. In addition, add the following initializeImages() method:
    public static void initializeImages()
    {
        if (moveLeftImgs == null || moveRightImgs == null)
        {
            moveLeftImgs = new GreenfootImage[MOVE_COUNT];
            moveRightImgs = new GreenfootImage[MOVE_COUNT];
            for (int i = 0; i < moveRightImgs.length; i++)
            {
                String fileName = "gorilla" + (i + 1) + ".png";
                moveLeftImgs[i] = new GreenfootImage(fileName);
                moveRightImgs[i] =
                    new GreenfootImage(moveLeftImgs[i]);
                moveRightImgs[i].mirrorHorizontally();
            }
        }
        if (dieLeftImg == null || dieRightImg == null)
        {
            dieLeftImg =
                new GreenfootImage("gorilla-dead.png");
            dieRightImg = new GreenfootImage(dieLeftImg);
            dieRightImg.mirrorHorizontally();
        }
    }
    
  6. Finally, add the following Gorilla constructor:
    public Gorilla()
    {
        initializeImages();
        setAnimations(moveLeftImgs, moveRightImgs, dieLeftImg, dieRightImg);
        setMoveFrameCount(MOVE_COUNT_PER_FRAME);
        setDyingTime(DYING_TIME);
    }
    
  7. Compile the scenario to verify you added the code correctly.
  8. Test the Gorilla class by adding a new Gorilla object to the world and then running the scenario.

    The gorilla should walk. If the gorilla does not walk, make sure you deleted the act() method as specified in step 4. Notice that the gorilla will pay no attention to floors or walls. To create the proper illusion we need to carefully place and set the range of the gorilla's movement.

  9. Open the editor for the GameManager class and add the following method:
    public void makeGorillas()
    {
        Gorilla g1 = new Gorilla();
        g1.setRangeX(384, 667);
        GreenfootImage img = g1.getImage();
        int gorillaY = topY + TILE_HEIGHT * 35 / 2 - img.getHeight() / 2;
        addObject(g1, 667, gorillaY);
        Gorilla g2 = new Gorilla();
        g2.setRangeX(640, 800);
        gorillaY = topY + TILE_HEIGHT * 21 / 2 - img.getHeight() / 2;
        addObject(g2, 646, gorillaY);
    }
    
  10. Call the makeGorillas() method from the constructor of the GameManager.
  11. Compile and run the scenario and verify the gorillas are walking correctly.
  12. Now update the scrollHorizontal() method as follows.
    public void scrollHorizontal(double dx)
    {
        List<Actor> actors = getObjects(null);
        for (Actor a : actors)
        {
            if (a instanceof Player)
            {
                // Allow smooth moving of Player
                Player p = (Player) a;
                double moveX = p.getExactX() - dx;
                p.setLocation(moveX, p.getExactY());
            }
            else if (a instanceof Creature)
            {
                Creature c = (Creature) a;
                // Allow smooth moving
                c.setLocation(c.getExactX() - dx, c.getExactY());
                // Set endpoints
                int leftX = (int)Math.round(c.getLeftX() - dx);
                int rightX = (int)Math.round(c.getRightX() - dx);
                c.setRangeX(leftX, rightX);
            }
            else
            {
                int moveX = (int) Math.round(a.getX() - dx);
                a.setLocation(moveX, a.getY());
            }
        }
    }
    
  13. Compile and run the scenario and verify the gorillas are walking correctly even while scrolling.
  14. Save your updated scenario as we will be adding to it as the lesson continues.
  15. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. True or false: the purpose of having a Creature superclass for Gorilla is to make it easier to add similar NPCs to the scenario.
  2. Why is Creature a subclass of Sprite rather than Actor? (answer)
  3. True or false: all the images of an animation should be the same size to make it easier to align the images during the animation.
  4. What is the order of files loaded by the above initializeImages() code? (answer)
  5. To add falling and landing capabilities to an NPC, what methods would we need to place in Creature or Sprite? Click to show answer

13.1.5: Collisions with the Player

  • The act() method of Creature checks for a collision using an intersection method:
    if (intersects(player))
    {
        processCollision();
    }
    
  • To win in a collision, the player must jump on top of a creature
  • To check this condition, we first calculate the lowest point of the player and the highest point of the creature
  • However, because the code does not react to a collision until the objects intersect, the player will always move below the top of the creature
  • We must calculate the maximum possible overlap to resolve the collision
    int maxOverlap = (int)(player.getVelocityY()
        + player.GRAVITY + 0.5);
    
  • Then we can test to resolve who won the collision
    if (playerBottom - maxOverlap <= creatureTop)
    
  • If the player has not descended more than the maximum overlap, then the player wins in the collision

Method processCollision() of the Creature Class

public void processCollision() {
    if (!player.isAlive()) {
        return;
    }
    int playerBottom = player.getY() + player.getHeight() / 2;
    int creatureTop = getY() - getHeight() / 2;
    int maxOverlap = (int)(player.getVelocityY() + player.GRAVITY + 0.5);
    if (playerBottom - maxOverlap <= creatureTop
        || getState() == STATE_DYING)
    {
        // player wins
        int h2 = (getHeight() + player.getHeight()) / 2;
        int backoffY = getY() - player.getY() - h2;
        player.setLocation(player.getX(), player.getY() + backoffY);
        player.setVelocityY(-player.getVelocityY());
        if (getState() != STATE_DYING)
        {
            Greenfoot.playSound("squish.wav");
            startDying();
        }
    } else {
        // creature wins
        player.startDying();
    }
}

Simulating Dying

  • Now that we have creatures who can potentially kill our player, we need a set of animations for dying
  • Conflict and its consequences is common in games, literature and other entertainment
  • For our dying animation, the player collapses and fades away

Player Fades Away

Player dying image 1 Player dying image 2 Player dying image 3 Player dying image 4 Player dying image 5 Player dying image 6 Player dying image 7 Player dying image 8 Player dying image 9 Player dying image 10 Player dying image 11 Player dying image 12

Coding the Dying Process

  • To start coding the dying process, we add the following variables to Player:
    private static final int DYING_TIME = 60;
    private static final int DIE_COUNT = 12;
    private static GreenfootImage[] dieRightImages;
    private static GreenfootImage[] dieLeftImages;
    private int dyingCount;
    
  • Then in initializeImages() we add code to cache the images like we did with our moving images
    if (dieRightImages == null)
    {
        dieRightImages = new GreenfootImage[DIE_COUNT];
        for (int i = 0; i < DIE_COUNT; i++)
        {
            String fileName = "dying" + (i + 1) + ".png";
            dieRightImages[i] = new GreenfootImage(fileName);
        }
        dieLeftImages = flipImages(dieRightImages);
    }
    
  • To start the dying process we update our player's act() method:
    public void act()
    {
        if (getState() == STATE_DYING)
        {
            updateDyingState();
        }
        else
        {
            checkKeys();
            checkCollisionHorizontal();
            checkVertical();
        }
        move();
    }
    
  • In addition, we add a method to handle the dying process as shown below

Method to Handle the Process of Dying

private void updateDyingState()
{
    dyingCount++;
    if (dyingCount >= DYING_TIME)
    {
        setState(STATE_DEAD);
        getWorld().removeObject(this);
        return;
    }
    int imgNumber = dyingCount / (DYING_TIME / DIE_COUNT);
    if (direction == LEFT)
    {
        setImage(dieLeftImages[imgNumber]);
    }
    else
    {
        setImage(dieRightImages[imgNumber]);
    }
}

Try It: Adding Collisions (5m)

  1. Start Greenfoot and open the scenario from the last Try It! exercise.

    If you did not keep the scenario, then complete Try It: Adding a Gorilla now and then continue with these instructions.

  2. Open the editor for the Player class and add the following variables:
    private static final int DYING_TIME = 60;
    private static final int DIE_COUNT = 12;
    private static GreenfootImage[] dieRightImages;
    private static GreenfootImage[] dieLeftImages;
    private int dyingCount;
    
  3. At the end of initializeImages(), add the following code to cache the dying images
    if (dieRightImages == null)
    {
        dieRightImages = new GreenfootImage[DIE_COUNT];
        for (int i = 0; i < DIE_COUNT; i++)
        {
            String fileName = "dying" + (i + 1) + ".png";
            dieRightImages[i] = new GreenfootImage(fileName);
        }
        dieLeftImages = flipImages(dieRightImages);
    }
    
  4. Verify the player's act() looks like the following code:
    public void act()
    {
        if (getState() == STATE_DYING)
        {
            updateDyingState();
        }
        else
        {
            checkKeys();
            checkCollisionHorizontal();
            checkVertical();
            move();
        }
    }
    
  5. Update the method updateDyingState() as shown below
    private void updateDyingState()
    {
        dyingCount++;
        if (dyingCount >= DYING_TIME)
        {
            setState(STATE_DEAD);
            getWorld().removeObject(this);
            return;
        }
        int imgNumber = dyingCount / (DYING_TIME / DIE_COUNT);
        if (direction == LEFT)
        {
            setImage(dieLeftImages[imgNumber]);
        }
        else
        {
            setImage(dieRightImages[imgNumber]);
        }
    }
    
  6. Compile the scenario to verify you added the code correctly.
  7. Test the dying updates by running into a gorilla.

    When the player runs into a gorilla, the player should fade away.

  8. Test that the player can kill the gorilla by jumping on it.
  9. Save your updated scenario as we will be adding to it as the lesson continues.
  10. When finished please help those around you.
  11. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. Why does our player have to (potentially) die?
  2. The method of Creature that checks for collisions with the player is ________.
  3. What condition must be true for the player to win a collision? (answer)
  4. Of the following steps, "________" does NOT occur when the player wins a collision with a creature.
    1. the player backs off in the up direction
    2. the player bounces off the top of the creature
    3. the creature starts dying
    4. the player automatically adds one to his "kill" count
  5. What happens when the creature wins a collision with the player? (answer)

Exercise 13.1: Adding an NPC (10m)

In this exercise, we write a new NPC. We will use the following images for the NPC which are included with the scenario.

Moving
Fly 1 Fly 2 Fly 3 Fly 4 Fly 5 Fly 6
Dead
Fly dead

Specifications

  1. Verify you have completed the Try It activities we explored throughout the section including:
    1. Try It: Getting the Player
    2. Try It: Adding State
    3. Try It: Adding Creature Features
    4. Try It: Adding a Gorilla NPC
    5. Try It: Adding Collisions

    If you have not already completed the exercises, or had problems with them, download the Platformer 5 scenario file and save it to a convenient location like the desktop. Then unzip and open the scenario.

  2. Scenario file: platformer5.gfar or platformer5.zip.

    This scenario includes all the updates from prior sections.

  3. Create a new subclass of Creature named Fly using the "fly1.png" image.

    For more information see lesson: 2.1.5: Creating an Actor.

  4. In the Fly class, add constants and image caching variables as follows:
    // Default values
    private static final double MOVE_SPEED = 2.5;
    private static final int DYING_TIME = 60;
    private static final int MOVE_COUNT = 6;
    private static final int MOVE_COUNT_PER_FRAME = 4;
    
    // Cache images for multiple instances.
    private static GreenfootImage[] moveLeftImgs;
    private static GreenfootImage[] moveRightImgs;
    private static GreenfootImage dieLeftImg;
    private static GreenfootImage dieRightImg;
    
  5. Also in the Fly class, add an intializeImages() method, using class Gorilla as an example.
    public static void initializeImages()
    {
        // Add code here
    }
    

    For more information see section 13.1.4: Creating an NPC. You will need to add six (6) images to each animation rather than the three used to make gorillas. Notice that the scenario already includes the images, which start with the word, "fly".

  6. Add a default constructor to the new class, using class Gorilla as an example. Within the constructor, create left and right movement animations and dying animations.

    Compile the class and verify there are no errors. Resolve any errors you find, getting help from a guild mate or the instructor as needed.

  7. In Fly, remove the act() method so that the Creature superclass act() method will operate instead.
  8. Open the GameManager class and add a method named: makeFlies() that adds flies to the scenario.
    private void makeFlies()
    {
        // Add flies to world
    }
    

    Call the method from the GameManager constructor just after the makeGorillas() method.

  9. Add at least two flies to the world, using the makeGorillas() method as an example.

    Hint: run the player to the center of the world and pause the game. Position the flies and then use the Inspect utility to determine (x, y) coordinates. Add about 320 to each x-coordinate to determine the map position. If you still have difficulty, click here for an example: Click to show example.

  10. Compile and run your scenario to verify all the additions work well.

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

  11. Save your scenario files to submit to Canvas as part of lab 13.
  12. When finished please help those around you.

As time permits, read the following sections and be prepared to answer the Check Yourself questions in the section: 13.1.6: Review.

13.1.6: Review

  • In this section we discussed non-player characters (NPCs)
  • A non-player character is any character not controlled by a human player
  • In a video game, the NPC is usually controlled by the computer

Remembering State

  • To interact with NPCs, we added to the Sprite superclass a simple system for determining a character's state
  • Our system was a single integer variable and methods to set and get the state
    private int state;
    
    public void setState(int newState)
    {
        state = newState;
    }
    
    public int getState()
    {
        return state;
    }
    
  • Then in a character we define the possible states using constant variables like:
    public static final int STATE_NORMAL = 0;
    public static final int STATE_DYING = 1;
    public static final int STATE_DEAD = 2;
    
  • To change state we simply call the get and set state methods like:
    setState(STATE_DYING);
    if (getState() == STATE_DYING)
    {
        // do something
    }
    

Developing NPCs

  • To help us develop NPCs we added a Creature superclass

    Creature inheritance hierarchy

  • The Creature class contains helper methods to make it easier to develop NPCs
  • We then worked through an example of developing an NPC in section 13.1.4: Creating an NPC

Player Interaction

  • The role of NPCs is usually to interact with the player
  • We went through an interaction system appropriate for a platformer game in section 13.1.5: Collisions with the Player

Check Yourself

Answer these questions to check your understanding. You can find more information by following the links after the question.

  1. Which of the following is a non-player character? (13.1.1)
    1. A player character
    2. A sprite controlled by the game player
    3. A sprite controlled by the computer
    4. A background image like a sign
  2. True or false: To remember the state of a player we need to stoe a value in a variable. (13.1.2)
  3. What is the purpose of having a Creature superclass for Gorilla? (13.1.3)
  4. Which of the following superclass methods can you call from Gorilla? (13.1.3)
    1. The methods from Creature only.
    2. The methods of Creature and Player.
    3. The methods of Actor, Creature and Sprite.
    4. All of the methods of all classes can be called directly.
  5. True or false: The images of an animation should all be the same size to make animating the images easier. (13.1.3)
  6. True or false: By adding a number to the file names of the images, you can load all the images for an animation using a loop. (13.1.3)
  7. To code a new NPC, you should write ________ constructors minimum. (13.1.3)
  8. To change the behavior of an NPC, override the __________ method of Creature. (13.1.3)
  9. Which of the following steps does NOT occur when the player wins a collision with a creature? (13.1.4)
    1. The player backs off in the up direction
    2. The player bounces off the top of the creature
    3. The creature starts dying
    4. The player automatically adds one to his "kill" count
  10. What is the purpose of the following code in the processCollision() method? (13.1.4)
    player.setVelocityY(-player.getVelocityY());
  11. What is the purpose of a copy constructor? (13.1.5)
  12. Which of the following is a correct signature for a copy constructor? (13.1.5)
    1. public Creature()
    2. public Creature(Creature a)
    3. public Creature(Animation a, Animation b)
    4. public CopyCreature(Creature a)
  13. In general, all ______________ types should be constructed anew in a copy constructor. (13.1.5)
  14. When writing a new NPC, should you include a copy constructor? Why or why not? (13.1.5)

13.2: Reading and Writing Files

Learner Outcomes

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

  • Discuss the organization of computer files
  • Describe files and streams
  • Discuss the types of files and streams
  • Layer streams for desired functionality
  • Write text files
  • Read text files

13.2.1: Files, Folders and Directories

  • The file system is how the computer organizes, stores and locates files
  • When working with computers, it is important to understand how the file system works
  • Files store things like documents, photos, videos, music and Java code
  • Computer file information is retained after an application ends or the computer is shut down

Organizing Files

  • Most computers organize files into folders (directories, catalogs, drawers)
  • Folders can contain other folders as well as files
  • Together, the folders make up a hierarchy of storage locations
  • We can think of our hard drive as one big master folder where other folders and files are organized and accessed
  • We see file and folder organization in the example folder below
  • Notice how files and folders are nested inside folders

Example Folder

Folder example

Programs and Files

  • Many computer programs read and write files
  • We can do the same in our Greenfoot scenarios
  • For instances, we could store a high score list of players
  • Also, we can read information like tile maps stored in files
  • Reading a tile map from a file would let us change maps without recompiling
  • To store and retrieve data in a file, we need two items:
    • A file
    • A file stream object
  • We will start by exploring files

Note: A scenario only can read files when it runs in the online Greenfoot Gallery. To write to a file, a scenario must run as an application.

Check Yourself

  1. To store information, the computer saves the data in a __________.
  2. True or false: folders can contain files or other folders.
  3. The building block that creates the hierarchy of a file system is a __________.
    1. Document
    2. File
    3. Folder
    4. Record
  4. What use can you think of for reading and writing files in a Greenfoot scenario?

More Information

13.2.2: Computer Files

File: a collection of data stored under a common name on a storage medium.

  • Files provide long-term storage of potentially large amounts of data
  • Usually, files are stored on non-volatile storage using:
    • Magnetic memory, like hard drives
    • Optical memory, like DVDs
    • Flash memory, like USB memory sticks
    • Holographic memory, like HVD
    • Molecular memory (being researched)
  • Computer files are stored in binary
  • Each binary digit can have one of two values: 0 or 1
  • A bit is one binary digit
  • A byte is a group of eight bits

    8 bits to a byte

  • File are organized as a single sequence of bytes

    Byte 0 Byte 1 Byte 2 ... Byte n−1

  • The operating system keeps track of the number of bytes in a file
  • Files must have a name
    • Naming requirements depend on the underlying operating system (OS)
  • The file system organizes files into folders or directories

Understanding Binary -- or Not?

Only 10 types of people

Types of Files

  • All data in a file is ultimately just zeros and ones (bits)
  • However, we can classify the files based on their data into two broad categories: text and binary

Text Files

  • In text files, the bytes in the file represent printable characters
  • Text files usually store Latin based characters (like English) in one byte
  • The byte for each character is defined by a standard such as ASCII (ASCII table) or UTF-8
  • Every line of text is delimited by end-of-line characters:
    • Unix/OS-X: "\n"
    • Windows: "\r\n"
  • We can read text files because each byte is interpreted by a program as textual characters
  • Some of these programs, like TextPad, then display the textual data to our computer's screen
  • Since there are many programs that read and display text, text files are called human readable

Binary Files

  • Data other than text is usually referred to as binary data
  • Each bit represents some type of encoded information like program instructions or integer data
  • Binary files are easily read by the computer but not by humans
  • The following table compares binary and text values saved in a file
  • First we consider the value "1234" as ASCII codes and compare these bits to a binary value of 1234

Comparing Binary and Textual Data Formats

Description Byte 0 Byte 1 Byte 2 Byte 3
"1234" as char's '1' '2' '3' '4'
"1234" as ASCII codes (bytes) 49 50 51 52
"1234" as ASCII codes (bits) 00110001 00110010 00110011 00110100
(int) 1234 as binary bits 00000000 00000000 00000100 11010010

Try It: What's My File Type (4m)

  1. Download the following scenario file, save it to a convenient location like the Desktop, and unzip the file.

    Scenario file: fileio.gfar or fileio.zip.

  2. Double-click the project.greenfoot file in the unzipped folder to start Greenfoot and open the scenario.
  3. Compile the scenario.
  4. Start a text editor like TextPad.
  5. Open the FileWorld.java source code file in the text editor.
  6. Open the FileWorld.class compiled file in the text editor
  7. Notice the difference between the two files.

    Which file is a binary file and which is a text file?

  8. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. Program I/O is the term used for program I________ and O________.
  2. True or false: files can be used as both the input and output of a program.
  3. Of the following, the advantage of using files for program I/O is ________ .
    1. data still exists after the program ends
    2. input can be automated (rather than entered manually)
    3. output from one program can be input to another
    4. all of these
  4. A file resembles a(n) ________ of bytes.
  5. True or false: data in a file is restricted to characters only.
  6. Since text files can be displayed in any text editor, text files are known as ________ readable files.
  7. Files that store non-text data are known as ________ files.
  8. Of the following, the binary file is ________.
    1. Bug.class
    2. Bug.java
    3. BugWorld.java
    4. README.TXT

13.2.3: Streams

Stream: an ordered list of data delivered over time

  • To read and write files, we use a stream
  • A stream connects a program to data, such as that stored in a file
  • Input stream: an object that provides a sequence of bytes to a program over time

    Input stream

  • Output stream: an object that accepts a sequence of bytes from a program and delivers the data over time

    Output stream

File Streams

File stream: a data delivery path used to connect a program to a file.

  • File streams can be either input or output streams
  • File input streams receive data from a file
  • File output streams send data to a file
  • Each file our program uses will need a separate file stream object

Basic File Streams

  • Since there are two types of files, there are streams to support each type
  • We use character streams to read and write text files:
  • Similarly, we use binary streams to read and write binary files:
  • Our focus in this lesson is the character (text) streams

Text Streams

  • Streams are implemented using classes and objects
  • To read and write text, we use character streams
  • A character stream processes characters through a stream
  • There is a separate set of classes for writing and reading character streams
  • These classes are organized in an inheritance hierarchy as shown below

Some Classes from the Reader Hierarchy

Reader: Foundation class for reading character streams
  |
  +--BufferedReader: Add a buffer to the stream
  |
  +--InputStreamReader: Bridge character to binary streams
       |
       +--FileReader: Connects a stream to a file

Some Classes from the Writer Hierarchy

Writer: Foundation class for writing character streams
  |
  +--BufferedWriter: Add a buffer to the stream
  |
  +--PrintWriter: Convert binary data to text
  |
  +--OutputStreamWriter: Bridge character to binary streams
       |
       +--FileWriter: Connects a stream to a file

Check Yourself

  1. A ________ is an ordered list of data delivered over time.
  2. True or false: streams can be defined as input, output or bi-directional (input and output).
  3. The superclass for streams that read text is ________.
  4. The superclass for streams that write text is ________.

13.2.4: Layering Streams

  • Usually, any one stream does have not all the functionality we want
  • Instead, it is common to "layer" two or more streams

Writing to a Text Stream

  • To write text to a file, we use a FileWriter stream:
    FileWriter fw = new FileWriter("out.txt");
    
  • However, a FileWriter does not know how to write different types of data
  • That's why we combine the FileWriter with a PrintWriter:
    PrintWriter out = new PrintWriter(fw);
    
  • Now we can use the overloaded print() methods of a PrintWriter object to write various data types

Buffering

  • Every time a byte or sequence of bytes is written or read to a file, the OS must perform a series of operations
  • Buffering improves performance of I/O by reducing the number of calls to the OS
  • A program copies each output to a block of memory called a buffer
  • The entire buffer is output to disk at once
  • One long disk access takes less time than many smaller ones

Buffer

Adding a Buffered Layer

  • We use a buffered stream classes to improve I/O performance:
  • We can add a buffering layer to our previous stream example:
    FileWriter fw = new FileWriter("myfile.txt");
    BufferedWriter buf = new BufferedWriter(fw);
    PrintWriter out = new PrintWriter(buf);
    
  • Another way to write the same functionality:
    PrintWriter out = new PrintWriter(
                      new BufferedWriter(
                      new FileWriter("myfile.txt")));
    
  • The second way shows the layers of the streams more clearly
    • Top layer: convenience methods for converting data to characters
    • Middle layer: buffering for improved performance
    • Bottom layer: character output stream
  • After the layers are built we work with the top layer only

Check Yourself

  1. Buffering improves input and output performance because ________.
    1. it reduces the number of file read and write operations.
    2. it increases the number of file read and write operations.
    3. it increases the speed of file read and write operations.
    4. it stores file data in RAM, which is faster than storing it to a magnetic disc.
  2. Of the following, the "layer" that is not commonly used when writing a text file is ________.
    1. FileWriter
    2. BufferedWriter
    3. PrintWriter
    4. ProgramWriter
  3. When we want to write data to a file using print() and println(), we add the "layer" named ________.

13.2.5: Writing a Text File

  • Let us look at the steps for writing to a text file

Creating the Writer Stream

  • Our first step is to build the layers of the output stream
  • There are many ways to connect a character output stream to a file
  • We can "mix and match" Writer subclasses to get the functionality we need
  • Note that any class ending in the word "Writer" is a Writer subclass
  • This list of constructors should give you some idea how this is possible:
    FileWriter(String pathname)
    FileWriter(String pathname, boolean append)
    
    BufferedWriter(Writer out)
    
    PrintWriter(String fileName)
    PrintWriter(Writer out)
    
  • Usually we end up with layers like the following:
    PrintWriter out = new PrintWriter(
                      new BufferedWriter(
                      new FileWriter("scores.txt")));
    
  • The PrintWriter object lets us call the overloaded print() and println() methods for writing various types of data

Writing the Data

  • After we build the output stream, we write our data
  • We write using the print() and println() methods of PrintWriter, like:
    out.println("This is a string");
    out.println('c');
    out.println(1234);
    out.println(1.234);
    for (int i = 0; i <= 10; i++) {
        out.print(i + ",");
    }
    out.println();
    
  • Notice that print() and println() are the same methods we use for printing to a terminal window
    System.out.println("this is a string");

Closing the File

  • When finished writing, we call the close() method of out to flush the buffer and close the file:
    out.close();
    
  • If we forget to close the stream, we may lose the contents of the output buffer
  • The following is a step-by-step procedure for writing files followed by an example method

Step by Step Procedure for Writing Text Files

  1. Import the API libraries for file output.
    import java.io.*;
  2. Create the output stream.
    String fileName = "data.txt";
    PrintWriter out = new PrintWriter( // encode data as characters
                      new BufferedWriter( // buffer data for speed
                      new FileWriter(fileName))); // write bytes
    
  3. Write the data like printing to a terminal window.
    out.println("This is a string");
    out.println('c');
    out.println(1234);
    out.println(1.234);
    for (int i = 0; i <= 10; i++) {
        out.print(i + ",");
    }
    out.println();
    
  4. Close the file.
    out.close(); // flush buffer and free up resources
    

Example Method that Writes Data to a File

public void writeScores(String filename) throws IOException
{
    String[] scores = {"Ed      1000", "MstrChf  500"};
    PrintWriter out = new PrintWriter(
                      new BufferedWriter(
                      new FileWriter(filename)));
    for (String line: scores)
    {
        out.println(line);
    }
    out.close();
}

What is "throws IOException"?

  • The "throws IOException" clause is a way to handle errors (exceptions)
  • We will discuss exceptions later

Try It: Writing a File (3m)

  1. If you have not done so already, download the following scenario file, save it to a convenient location like the Desktop, and unzip the file.

    Scenario file: fileio.gfar or fileio.zip.

  2. Double-click the project.greenfoot file in the unzipped folder to start Greenfoot and open the scenario.
  3. Open the FileWorld class and verify the API libraries for file I/O are imported:
    import java.io.*;
    
  4. Add the following method to the FileWorld class:
    public void writeScores(String filename) throws IOException
    {
        String[] scores = {"Ed      1000", "MstrChf  500"};
        PrintWriter out = new PrintWriter(
                          new BufferedWriter(
                          new FileWriter(filename)));
        for (String line: scores)
        {
            out.println(line);
        }
        out.close();
    }
    

    Compile the class after copying in the code and verify there are no errors. Resolve any errors you find, getting help from a guild mate or the instructor as needed.

  5. Call the new method to verify it works by right-clicking on the background and selecting the method. Save a file with the name of "scores.txt".

    Remember to put double-quote marks (") around the name of the file.

  6. Verify the file was written to the main folder of your scenario and examine the contents of the file using a text editor like TextPad.

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

  7. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. Of the following, ________ is NOT a usual step for writing to a file.
    1. check if the file exists
    2. create an output stream
    3. write the data
    4. close the file
  2. True or false: there is only one way to create an output stream for writing text to a file.
  3. True or false: if an output stream is not closed then it is possible to lose data.

13.2.6: Reading a Text File

  • Once we have a text file we can read it with our program
  • The steps for reading are similar to the steps for writing

Creating the Reader Stream

  • To read from a text file, we need to create a character input stream
  • To do this, we layer classes from the Reader hierarchy:
  • Note that any class ending in the word "Reader" is a Reader subclass
  • This list of constructors should give you some idea how this is possible:
    FileReader(String pathname)
    
    BufferedReader(Reader in)
    
    Scanner(Readable source)
    
  • There is no "PrintReader" class, so we can use a Scanner object instead
  • Usually we end up with layers like the following:
    Scanner in = new Scanner(
                 new BufferedReader(
                 new FileReader("data.txt")));
    
  • The Scanner object lets us call various methods for converting text into other data types

Reading From a JAR File and on the Greenfoot Gallery

  • A JAR file is a ZIP-like file with some extra features
  • Greenfoot uses JAR files to package our scenario and sometimes we want to read text files included in our JAR file
  • However, a FileReader cannot connect to a file inside a JAR because of the compressed format
  • To load files from a JAR, we need to use a method named getClass()
  • Method getClass() gets the Class runtime class for the current object
  • The runtime class is the information Java keeps about each class that is running
  • We can extract information from Java about the runtime class using the class named Class
  • A Class object has two methods we can use to get resources:
  • We can use either of these methods to connect to a text file
  • So instead of creating layers like the above, we create layers with getResourceAsStream() like:
    InputStream istream = getClass().getResourceAsStream("data.txt");
    Scanner in = new Scanner(
                 new BufferedReader(
                 new InputStreamReader(istream)));
    
  • Since this technique is more generally useful, it is preferred for Greenfoot projects
  • Reading from a JAR file is the only file operation allowed on any web page, including the Greenfoot Gallery
  • Java runs on a web page in an applet, which is a small application container
  • We can automatically detect if our program is running in an applet by checking for a SecurityManager
    if (System.getSecurityManager() == null) {
        // perform file operations not allowed on a web page
    }
    
  • An applet contains a SecurityManager to reduce threats, like viruses, to the Java program
  • Thus if a SecurityManager is not present then we can write files

Reading the Data

  • After we build the input stream, we read our data
  • If our data is more than just lines of text, then we use a Scanner to convert the characters into other data types
  • Scanner is located in the java.util package, so we need to import the class using:
    import java.util.Scanner;
  • A Scanner reads tokens which are usually delimited by whitespace
  • A token is like a word in a sentence
  • Whitespace is a character which represents spaces between words, like space and tab characters
  • With our Scanner object we can use methods to read from the stream like:
    String str = in.nextLine();
    char ch = in.nextLine().charAt(0);
    int x = in.nextInt();
    double d = in.nextDouble();
    for (int i = 0; i <= 10; i++) {
        x = in.nextInt();
    }
    
  • Notice that we must know the type of data that is in the input stream to use these methods
  • Otherwise, the Scanner object will throw an exception

Some Commonly Used Methods of a Scanner Object for Tokenizing Data

Method Description
next() Returns the next token as a String object.
nextLine() Returns the rest of the current line as a String object.
nextDouble() Returns the next token as an double value.
nextInt() Returns the next token as an int value.

Closing the Stream

  • After our program finishes reading, it should call the close method:
    in.close();
  • Calling close() frees up computer system resources
  • The following is a step-by-step procedure for reading files followed by an example method

Step by Step Procedure for Reading Text Files

  1. Import the API libraries for file input.
    import java.io.*;
    import java.util.Scanner;
    
  2. Create the input stream.
    String fileName = "data.txt";
    Scanner in = new Scanner( // parse characters into data types
                 new BufferedReader( // buffer data for speed
                 new InputStreamReader( // read bytes as characters
                 getClass().getResourceAsStream(fileName)))); //JAR
    
  3. Read the data.
    String str = in.nextLine();
    char ch = in.nextLine().charAt(0);
    int x = in.nextInt();
    double d = in.nextDouble();
    for (int i = 0; i <= 10; i++) {
        x = in.nextInt();
    }
    
  4. Close the file.
    in.close(); // flush buffer and free up resources
    

Example Method Reading a Text File

public void readScores(String filename) throws IOException
{
    InputStream istr = getClass().getResourceAsStream(filename);
    Scanner in = new Scanner(
                 new BufferedReader(
                 new InputStreamReader(istr)));
    while (in.hasNext()) {
        String line = in.nextLine();
        System.out.println(line);
    }
    in.close();
}

Testing for End of File

  • Notice the while loop in the example method above
  • Sometimes we do not know how many lines of data are in a file
  • Using a loop like this is a typical way to solve the problem and let us read any amount of data
  • As an example, we could read a tile map for a game from a file
  • The Scanner object has methods like hasNext() to see if there is any more input in the stream
  • We can use these methods to test when our program reaches the end of a file

Some Test Methods of a Scanner Object

Method Description
hasNext() Returns true if this scanner has another token in its input.
hasNextLine() Returns true if there is another line in the input of this scanner.
hasNextDouble() Returns true if the next token can be interpreted as a double value.
hasNextInt() Returns true if the next token can be interpreted as an int value.

Check Yourself

  1. Of the following, ________ is not a usual step for reading from a file.
    1. scan the file for errors
    2. create an input stream
    3. read the data
    4. close the file
  2. True or false: if an input stream is not closed then it is possible to lose data.
  3. True or false: reading data from a JAR file is more difficult because the data is compressed.
  4. True or false: our program must always know the type of data being read from a file.
  5. To read from a file when we do not know how much data it contains, we can use a loop and test for the end of the file using the ________ method of the Scanner object.

Exercise 13.2: Writing and Reading Files (5m)

In this exercise, we write data to a file and then read the data back from a file.

Specifications

  1. If you have not already completed Try It: Writing a File, do so now.
  2. Open the FileWorld class and verify the API libraries for file reading are imported:
    import java.io.*;
    import java.util.Scanner;
    
  3. Add the following method to the FileWorld class:
    public void readScores(String filename) throws IOException
    {
        InputStream istr = getClass().getResourceAsStream(filename);
        Scanner in = new Scanner(
                     new BufferedReader(
                     new InputStreamReader(istr)));
        while (in.hasNext()) {
            String line = in.nextLine();
            System.out.println(line);
        }
        in.close();
    }
    

    Compile the class after copying in the code and verify there are no errors. Resolve any errors you find, getting help from a guild mate or the instructor as needed.

  4. Call the new method to verify it works by right-clicking on the background and selecting the method.

    Remember to put double-quote marks (") around the name of the file.

  5. Verify the read operation works by verifying the Terminal window shows the contents of the file.

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

  6. Save your scenario files to submit to Canvas as part of lab 13.

As time permits, read the following sections and be prepared to answer the Check Yourself questions in the section: 13.2.7: Review.

13.2.7: Review

Answer these questions to check your understanding. You can find more information by following the links after the question.

  1. How does a computer store information in secondary memory? (13.2.1)
  2. What is the technical name for the file system organizing technique that stores files and folders? (13.2.1)
    1. Files
    2. Folders
    3. Documents
    4. Records
  3. True or false: a file is just a container for data. (13.2.2)
  4. What standards are commonly used to define text file formats? (13.2.2)
  5. Which of the following is a commonly used text file format? (13.2.2)
    1. ASCII
    2. Textual
    3. Characterizer
    4. YOUTF-8
  6. What is the difference between a text file and a binary file? (13.2.2)
  7. What is an input stream? (13.2.3)
  8. What is an output stream? (13.2.3)
  9. True or false: streams can be defined as input, output or bi-directional (input and output). (13.2.3)
  10. To input or output text, use a ________________ stream. (13.2.3)
  11. What are three streams we typically layer for program output and what is the purpose of each layer? (13.2.4)
  12. How does buffering improve I/O performance? (13.2.4)
  13. What is the advantage of working with the top (PrintWriter) layer? (13.2.4)
  14. What are the three steps for writing files? (13.2.5)
  15. Write code to define an output stream for writing data to a file. (13.2.5)
  16. Why is it important to close the output stream after our program is finished writing to a file? (13.2.5)
  17. What are the three steps for reading files? (13.2.6)
  18. Write code to define an input stream for reading data from a file. (13.2.6)
  19. True or false: our program must always know the type of data being read from a file. (13.2.6)
  20. What technique can we use to read all the data from a file, if we do not know how much data is in the file? (13.2.6)

Wrap Up

Due Next:
Lab 13: Prototype Test (11/28/17)
Q13: User-Testable Prototype (11/30/17)
  • When class is over, please shut down your computer
  • You may complete unfinished lesson exercises at any time before the due date.
Home | Canvas | Schedule | Syllabus | Room Policies
Help | FAQ's | HowTo's | Links
Last Updated: December 04 2017 @16:23:35