10. Collisions and Caching

What We Will Cover


Illuminations

Questions from last class or the Reading?

Homework Questions?

10.1: Collision Detection: Asteroids

Learner Outcomes

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

  • Paint background scenes in a world
  • Simulate firing bullets in a scenario
  • Test for collisions in Greenfoot

10.1.1: About Asteroids

  • Asteroids is a video arcade game released in 1979 by Atari
  • At that time, most games were produced for and played on large arcade boxes like this one:

    Asteroids arcade game

  • Asteroids was a very popular game and spawned three arcade sequels
  • In addition, several competitors produced Asteroids clones
  • Versions have since been released for PlayStation, Nintendo 64 and Windows, among others

Asteroids Scenario

  • The book scenario is a recreation of an Asteroids game
  • Lets download and install this scenario of the game:

    Scenario file: asteroids-2b.gfar.

  • Save the file to a convenient location like the Desktop
  • Double-click the file to start Greenfoot and open the scenario
  • Before we continue, lets review some key concepts from the chapter

Concept Review

  • Bounding box: the enclosing rectangle of an image
  • Collision detection: detecting the intersection of two or more objects
  • Superclass type: an object can be both its own type and the type of its superclasses
  • Casting: specifying a more precise type for an object than the one the compiler knows about

Core Game Mechanics

  • Core game mechanics are the actions in a game that the player performs repeatedly
  • Sometimes these are referred to as rules
  • In a video game, the rules are enforced by the allowed gameplay
  • Hopefully, the core game mechanics are enjoyable for the player

Check Yourself

  1. The invisible rectangle around an image used to detect collisions in known as a ________ box.
  2. True or false: a subclass of Actor, like Bug, can also be called an Actor because Actor is the superclass type.
  3. What are the core game mechanics of the Asteroids game? Click to show answer

More Information

10.1.2: Painting the Background

  • The Asteroids scenario is different from previous scenarios in that the world does not have a prepared background image
  • Instead, the scenario creates its own background image
  • When we do not specify a background image for a world, Greenfoot uses a default white background
  • We want a different color than white for outer space

Changing the Color

  • To change colors we use Java to paint the background:
    GreenfootImage background = getBackground();
    background.setColor(Color.BLACK);
    background.fill();
    
  • Notice that the background is actually a GreenfootImage
  • Thus we can use methods of the GreenfootImage class to work with the background

Painting Stars

  • After painting the background black, the constructor calls the method createStars()
  • Let us step through each line of the method which is shown below
  • Notice that stars are drawn using the methods we discussed in lesson 8.3.2: Drawing Shapes
  • However, we are drawing multiple shapes onto a larger image
  • Also note that we can draw a gray color by using equal amounts of red, green and blue

Method createStars()

private void createStars(int number)
{
    GreenfootImage background = getBackground();
    for (int i = 0; i < number; i++)
    {
         int x = Greenfoot.getRandomNumber(getWidth());
         int y = Greenfoot.getRandomNumber(getHeight());
         int color = 120 - Greenfoot.getRandomNumber(100);
         background.setColor(new Color(color,color,color));
         background.fillOval(x, y, 2, 2);
    }
}

Check Yourself

  1. The default background color of a Greenfoot world is ________.
  2. The purpose of the following lines of code from createStars() is to generate ________ (x, y) coordinates.
    int x = Greenfoot.getRandomNumber(getWidth());
    int y = Greenfoot.getRandomNumber(getHeight());
    
  3. The following lines of code generates random colors that are shades of ________.
    int color = 120 - Greenfoot.getRandomNumber(100);
    background.setColor(new Color(color,color,color));
    

More Information

10.1.3: Turning and Moving

  • Turning and moving uses techniques we have discussed in the past
  • The checkKeys() method of Rocket responds to key presses by the user
  • Turning occurs when the user presses the left or right arrow keys

Method checkKeys() of Rocket

private void checkKeys()
{
    ignite(Greenfoot.isKeyDown("up"));

    if (Greenfoot.isKeyDown("left"))
    {
        turn(-5);
    }
    if (Greenfoot.isKeyDown("right"))
    {
        turn(5);
    }
    if (Greenfoot.isKeyDown("space"))
    {
        fire();
    }
}

Moving Forward

  • The rocket accelerates forward when the user presses the up-arrow key
  • Method ignite() selects the rocket image and applies the acceleration as needed
  • The acceleration is applied with a Vector like we discussed in lesson 9.1.2

Method ignite() of Rocket

private void ignite(boolean boosterOn)
{
    if (boosterOn)
    {
        setImage(rocketWithThrust);
        addToVelocity(new Vector(getRotation(), 0.3));
    }
    else
    {
        setImage(rocket);
    }
}

Screen Wrap Around

  • One interesting feature of the rocket movement is how it wraps around the screen
  • Screen wrap around was a feature of the original Asteroids game
  • The move() method of SmoothMover has changed to support this feature
  • Can you spot the changes in the code shown below?

Method move() of SmoothMover

public void move()
{
    exactX = exactX + velocity.getX();
    exactY = exactY + velocity.getY();
    if (exactX >= getWorld().getWidth()) {
        exactX = 0;
    }
    if (exactX < 0) {
        exactX = getWorld().getWidth() - 1;
    }
    if (exactY >= getWorld().getHeight()) {
        exactY = 0;
    }
    if (exactY < 0) {
        exactY = getWorld().getHeight() - 1;
    }
    super.setLocation((int) exactX, (int) exactY);
}

Check Yourself

  1. When the user presses the left or right arrow keys, the rocket rotates ________ degrees.
  2. When the user presses the up-arrow key, the value ________ is passed to the ignite() method in the following code:
    ignite(Greenfoot.isKeyDown("up"));
  3. True or false: if the ignite() method is called from the checkKeys() method, which is in turn called from act(), then the ignite method() is called every game cycle.
  4. For the following vector created in the ignite() method, the direction is the same as the Actor and the length is ________.
    addToVelocity(new Vector(getRotation(), 0.3));
    
  5. Describe the screen wrap-around concept in English.

10.1.4: Firing Bullets

  • Method checkKeys() calls one other method:
    if (Greenfoot.isKeyDown("space"))
    {
        fire();
    }
    
  • The fire() method creates a new bullet and launches it from the rocket
  • Notice how bullets fire only after a delay and not continuously
  • The delay is controlled by the counting variable reloadDelayCount:
    1. Declare an instance variable to hold counting values and assign it a starting value
      private int reloadDelayCount;
    2. Change the value of the count in the act() method
      reloadDelayCount++;
    3. Use an if-statement to test if the count has reached its goal
      if (reloadDelayCount >= gunReloadTime)
  • This is a common pattern for controlling timing over multiple scenario cycles

Method fire() of Rocket

private void fire()
{
    if(reloadDelayCount >= gunReloadTime)
    {
        Bullet bullet = new Bullet(getVelocity(), getRotation());
        getWorld().addObject(bullet, getX(), getY());
        bullet.move();
        reloadDelayCount = 0;
    }
}

The Flight of the Bullet

  • The Bullet constructor adds 15 to the speed of the bullet so it moves faster than the rocket
    addToVelocity(new Vector(rotation, 15));
    
  • The bullet disappears after 30 act() method calls with the counting technique describe above
  • If the bullet collides with an asteroid, the asteroid takes a hit
  • When hit, the asteroid breaks into two smaller pieces
  • If the asteroid was already small, it disappears instead

Check Yourself

  1. The three parts to controlling timing over multiple scenario cycles are:
    1. ________
    2. ________
    3. ________
  2. Find the lines numbers of each of the three steps for controlling timing in the Bullet class.

10.1.5: Collisions and Explosions

  • Oftentimes we want objects in a game to react when they collide
  • We saw this in the scenario when the rocket collides with an asteroid
  • The most commonly used technique is the idea of a bounding box
  • Bounding boxes are an invisible box around an image
  • The box is usually about the same size as the entire image as shown below:

    Bounding box from the textbook p. 110

  • As you can see, bounding boxes are not perfect
  • The transparent parts of an image may overlap before the collision takes place
  • Despite its problems, bounding boxes continue to be used because the computation is relatively fast and easy
  • Greenfoot has methods in the Actor class that check for intersection of bounding boxes
  • The following example from the asteroids scenario in the textbook shows how to use one of these methods

Methods of the Actor Class to Detect Intersections of Objects

Method Description
getIntersectingObjects() Returns a list of Actor objects that intersect this object.
getOneIntersectingObject() Returns a single Actor that intersects this object.
intersects(Actor other) Returns true if the specified Actor intersects, otherwise returns false.
isTouching(Class clss) Checks whether this actor is touching (intersecting) any other objects of the given class.

Example of Collision Detection in Rocket Class

private void checkCollision()
{
    Actor a = getOneIntersectingObject(Asteroid.class);
    if (a != null)
    {
        World world = getWorld();
        world.addObject(new Explosion(), getX(), getY());
        world.removeObject(this);
    }
}

Common Error: Removing Object Before Calling getworld()

  • What would happen if removeObject(this) was called before getWorld()? Click to show answer
    getWorld().removeObject(this);
    World world = getWorld();
    world.addObject(new Explosion(), getX(), getY());
    
  • Order is important! All Java statements execute in top-to-bottom order within a method
  • Game developers need to read and understand error messages

Realistic Collisions

  • To make collisions look realistic, we need to minimize the transparent pixels around the outside of an image
  • If a bounding box is not enough then we need other collision detection techniques
  • We will look at some other collision detection techniques in the future

Try It: Detect a Collision (4m)

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

    Scenario file: asteroids-2b.gfar.

  2. Double-click the file to open the scenario.
  3. Add a subclass of Actor named Alien using any image.
  4. Open the editor for the Alien class and add the following code to the act() method.
    if (isTouching(Rocket.class))
    {
        removeTouching(Rocket.class);
    }
    
  5. Test the Alien class by:
    1. adding an Alien object to the world in front of the rocket.
    2. pressing the Run button and observing what happens when the rocket touches the alien
  6. Add more excitement to the game by adding the following code inside the if-statement of the act() method.
    World w = getWorld();
    w.addObject(new Explosion(), getX(), getY());
    
  7. Retest the scenario (see step 5) and notice the difference.
  8. Save your updated scenario as we will be adding to it in the next exercise.
  9. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. True or false: When using bounding boxes, transparent pixels are ignored during collision detection.
  2. True or false: Bounding boxes are always accurate because all images are rectangles.
  3. True or false: To improve the accuracy of bounding box collision detection, leave transparent pixels around the image.
  4. Checking a bounding box for collisions is often used because it ________.
    1. is extremely accurate
    2. produces great results
    3. is a fast computation
    4. is a gaming tradition

10.1.6: Game Over and Casting

  • Lets take a look at keeping score
  • The scenario has a ScoreBoard class, of which we can create an object
  • As we can see, the score board should be shown when the game is over
  • To track the game over condition, the Space class has a gameOver() method:
    public void gameOver()
    {
        // TODO: show the score board here. Currently missing.
    }
    
  • We can do many things when the game is over, including showing the score
  • To show the score board when the game is over, we construct a new ScoreBoard object
    ScoreBoard sb = new ScoreBoard(999);
  • Then we add the new ScoreBoard object to the world
    addObject(sb, getWidth() / 2, getHeight() / 2);
    
  • For now we are using a dummy number, which we will fix later

Calling gameOver()

  • Now we need to call the gameOver() method at the right time
  • One possible time is when the rocket hits an asteroid and explodes
  • We can add this call to the checkCollision() method of Rocket like in the following code
  • However, we get an error if we do

    cannot find symbol - method gameOver()

Method checkCollision() calling gameOver()

private void checkCollision()
{
    Actor a = getOneIntersectingObject(Asteroid.class);
    if (a != null)
    {
        World world = getWorld();
        world.addObject(new Explosion(), getX(), getY());
        world.removeObject(this);
        world.gameOver(); // error: will not compile
    }
}

Casting Needed

  • The problem with the above code is that World does not have a gameOver() method
  • Our subclass Space has a gameOver() method and getWorld() does return Space
  • However, the compiler does not know that when we call getWorld() that we get Space
  • So we change World to Space and recompile:
    Space world = getWorld();
  • Now we get a different error:

    incompatible types - found greenfoot.World but expected Space

  • The problem in this case is that getWorld() returns a Space object but the compiler thinks it is only a World object
  • To solve the problem, we need to tell the compiler explicitly that we have a Space object
  • We tell the compiler by using a cast:
    Space world = (Space) getWorld();
  • Note that casting does not change the type of the object
  • Casting just provides the compiler with more information

Check Yourself

  1. True or false: getWorld() returns the current subclass of world as a World object.
  2. True or false: casting permanently changes one type of one object into another type
  3. The following code causes a compiler error:
    Space world = getWorld();
    Enter the code to correct the problem.

    answer

Exercise 10.1: Collision Detection (6m)

In this exercise, we implement collision detection for the rocket in Asteroids. Also, we implement a simple scoring system.

Specifications

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

    If you did not keep the scenario, then download asteroids-2b.gfar, save it to a convenient location like the Desktop and double-click the file to launch the scenario.

  2. Open the Rocket class and add the line shown in bold to following method:
    private void checkCollision()
    {
        Actor a = getOneIntersectingObject(Asteroid.class);
        if (a != null)
        {
            World world = getWorld();
            world.addObject(new Explosion(), getX(), getY());
            world.removeObject(this);
            world.gameOver(); // error: will not compile
        }
    }
    
  3. Refer to section 10.1.6 and change the code so that it compiles and runs correctly.

    When running correctly, the rocket explodes when it hits an asteroid. If you have problems, ask a classmate or instructor for help as needed.

  4. Open the Space class and locate the gameOver() method, and add the following code:
    int finalScore = scoreCounter.getValue();
    ScoreBoard sb = new ScoreBoard(finalScore);
    addObject(sb, getWidth() / 2, getHeight() / 2);
    removeObjects(getObjects(Bullet.class));
    

    Note that the last line removes bullets from the scenario so that no more asteroids are destroyed after the rocket explodes.

  5. Compile the class and run the scenario with your changes and verify it works correctly.

    When running correctly, the Game Over Screen appears after the rocket hits an asteroid. Resolve any problems you find, getting help from a classmate or the instructor as needed.

  6. Add a method to the Space class to add to the score, like:
    public void addToScore(int amount)
    {
        scoreCounter.add(amount);
    }
    
  7. In the Asteroid class, locate the hit() method and add a call to the addToScore() method at the start of the method, like:
    Space space = (Space) getWorld();
    space.addToScore(1);
    

    Note that if you call addToScore() at the end of the hit() method, you may get a NullPointerException error. Can you see why?

  8. Compile and run your scenario to verify the score changes when an asteroid is hit.

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

  9. Save your scenario as you may find it useful in completing the next programming project.

    Only submit the final scenario with all the lesson exercises completed, not the intermediate scenarios.

When finished please help those around you.

10.1.7: Review

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

  1. Asteroids is a video arcade game released in _______. (10.1.1)
  2. What are core game mechanics of Asteroids? (10.1.1)
  3. What is the default background color of a Greenfoot world? (10.1.2)
  4. What is the purpose of the following lines of code from createStars()? (10.1.2)
    int x = Greenfoot.getRandomNumber(getWidth());
    int y = Greenfoot.getRandomNumber(getHeight());
    
  5. What does the following lines of code do? (10.1.2)
    int color = 120 - Greenfoot.getRandomNumber(100);
    background.setColor(new Color(color,color,color));
    
  6. Fact or fiction: a boolean parameter accepts one of two values, either true or false. (10.1.3)
  7. True or false: screen wrap around moves the actor from one side of the screen to the other when the actor's location exceeds the screen boundaries. (10.1.3)
  8. Which of the following is NOT part of controlling timing of multiple scenario cycles? (10.1.4)
    1. Declare a counter instance variable.
    2. Change the value of the counter in the act() method.
    3. Use an if-statement to test if the counter has reached its goal.
    4. Call the move() method of the actor.
  9. What is a bounding box? (10.1.5)
    1. A collision between two objects.
    2. The box that is drawn around an object.
    3. A highlighted area of an image.
    4. An imaginary box around an image.
  10. True or false: When using bounding boxes, transparent pixels are ignored during collision detection. (10.1.5)
  11. True or false: Bounding boxes are always accurate because all images are rectangles. (10.1.5)
  12. True or false: To improve the accuracy of bounding box collision detection, leave transparent pixels around the image. (10.1.5)
  13. True or false: Checking a bounding box for collisions is a relatively fast computation. (10.1.5)
  14. For the following statements, what is the name of the technique for the code inside the parenthesis? (10.1.6)
    World world = /* reset of statement here */
    Space space = (Space) world;
    
    1. Altering
    2. Casting
    3. Changing
    4. Redefining
  15. True or false: getWorld() returns the current subclass of world as a World object. (10.1.6)
  16. True or false: casting changes one type of object into another type (10.1.6)

10.2: Proton Waves

Learner Outcomes

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

  • Write code to cache images and other data
  • Make use of static variables
  • Animate multiple images of many game cycles
  • Interact with objects in a range

10.2.1: More Firepower!

  • The Asteroids scenario has support for a second weapon: the proton wave
  • The proton wave, once fired, radiates outward from the rocket
  • When the wave touches an asteroid, it damages or destroys the asteroid
  • Since it works in all directions at once, it is a more powerful weapon
  • If you did not keep the previous scenario, then download asteroids-2b.gfar, save it to a convenient location like the Desktop and double-click the file to launch the scenario.
  • Then save the following files to the scenario, replacing the existing files:
  • We will construct the proton wave in this lesson

How the Proton Wave Works

  • Looking at the ProtonWave source code, we find three key methods
  • initializeImages() creates the images for the expanding wave
  • grow() manages the growing of the wave and removing it when it reaches full size
  • checkCollision() detects and explodes all the asteroids intersected by the wave
  • We will take a look at how the proton wave works in more detail in the following sections

Check Yourself

  1. The second weapon for the rocket in Asteroids is a ______ ______.
  2. True or false: the proton wave grows, destroying all asteroids in its path.
  3. The three key methods of the ProtonWave class are ________, ________ and ________.

10.2.2: Caching Images

  • The initializeImages() method creates 30 images of the wave from small to large
  • The images are stored in an array variable:
    private static GreenfootImage[] images;
    
  • The reason for creating and storing the images is so the program can change the images faster
  • Images are large blocks of data and image manipulation takes large amounts of computer power
  • Storing images, or other data, for faster retrieval later is known as caching
  • The array, or other container, that stores the data is known as a cache
  • We can see how the array stores images in the following figure from the textbook

Array of Images for the Proton Wave

Textbook figure 7.3

Method initializeImages()

public static void initializeImages()
{
    if (images == null)
    {
        GreenfootImage baseImage = new GreenfootImage("wave.png");
        images = new GreenfootImage[NUMBER_IMAGES];
        for (int i = 0; i < NUMBER_IMAGES; i++)
        {
            int size = (i + 1) * (baseImage.getWidth() / NUMBER_IMAGES);
            images[i] = new GreenfootImage(baseImage);
            images[i].scale(size, size);
        }
    }
}

Notes on the Code

  • Notice the test for the images array:
    if (images == null)
  • The body of the if-statement can execute only one time
  • Once the if-statement executes, images is assigned a non-null value:
    images = new GreenfootImage[NUMBER_IMAGES];
    
  • The 30 images are created by first loading a base image: wave.png
  • Then the for-loop uses the scale() method from GreenfootImage to change the size

    scale(width, height): changes this image to a new size.

  • The size is adjusted by multiplying the base size by (i + 1) / 30 each time the for loop iterates:
    index(index + 1) / 30
    01 / 30
    12 / 30
    23 / 30
    ......
    2930 / 30
  • Thus the image starts out 1/30 size and reaches full size by the end of the loop

Use of static Keyword

  • Notice that the images array is declared static
    private static GreenfootImage[] images;
    
  • We used the keyword static for constants in lesson 5.1.4
  • When used with a variable, such as an array variable, the keyword static makes a single copy of the variable available to all objects
  • Using static means that the array is part of the class and is shared by all ProtonWave objects, which saves memory space
  • If you want to share data between all objects of the class then declare the variable static
  • Since the images array is static, the initializeImages() method can be static as well
  • Methods declared static cannot access instance variables, only static member variables
  • Making the initializeImages() method static allows us to call the method before constructing any objects from the class
    ProtonWave.initializeImages();
    
  • To call static methods, we only need the name of the class instead of an object reference variable
  • Calling initializeImages() from the Space constructor makes sure the scenario does not pause when the player first fires the proton wave

Try It: Tracing a Loop (4m)

In this exercise, we will trace the execution of the following counting loop. Assume that the width of the image is 300 pixels.

private static final int NUMBER_IMAGES= 10;
for (int i = 0; i < NUMBER_IMAGES; i++)
{
    int size = (i + 1) * (baseImage.getWidth() / NUMBER_IMAGES);
    images[i] = new GreenfootImage(baseImage);
    images[i].scale(size, size);
}
  1. Open your README.TXT file from the last Exercise by clicking the menu Scenario → Scenario Information.
  2. At the end of the README.TXT file add the following headings:
    /*
    i   size
    -   ----
    */
    
  3. Type the value of the counter variable i followed by the value of size that would be present at the end of each iteration of the summing loop, like:
    /*
    i   size
    -   ----
    0   30
    (next pair of values)
    (next pair of values)
    ...
    */
    

    Place each pair of values on a new line. Use a calculator as needed.

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

Check Yourself

  1. Precomputing and storing data for future use is known as ________.
  2. True or false: the images array variable stores all the image data.
  3. True or false: the array of GreenfootImages referred to by the images variable stores all the image data.
  4. True or false: each image of the proton wave is stored at various locations in main computer memory.
  5. The GreenfootImage method that changes the size of an image is ________.
  6. True or false: static member variables can be accessed by static methods
  7. True or false: instance member variables can be accessed by static methods

10.2.3: Growing the Wave

  • Now that we have the images ready, we can animate the proton wave
  • The animation is an effect that happens over multiple scenario cycles
  • What are the three parts to controlling timing over multiple scenario cycles? Click to show answer
  • We add these parts to the ProtonWave class
  • Note that the grow() method is called from the act() method
  • As you can see, the grow() method follows the same pattern we discussed in lesson 10.1.4

Method grow() with Counting Variable

private int imageCount = 0; // 1
private void grow()
{
    if (imageCount >= NUMBER_IMAGES) // 3
    {
        getWorld().removeObject(this);
    }
    else
    {
        setImage(images[imageCount]);
        imageCount++; // 2
    }
}

Sequencing the Images

  • The images in the array are arranged from smallest to largest
  • For every act() call, the grow() method is called and increments the imageCount variable
  • After the wave shows its largest size, the ProtonWave object is removed from the world

Check Yourself

  1. The three parts to controlling timing over multiple scenario cycles are:
    1. ________
    2. ________
    3. ________
  2. The array images are arranged from ________ to ________.
  3. How often is the grow() method called? answer

10.2.4: Interacting with Objects in Range

  • We looked at how the proton wave grows
  • Now we need to look at how it detects and destroys the asteroids
  • To detect the asteroids, the code calls the method:

    getObjectsInRange(int radius, Class cls): Returns a list of objects within a given radius of the calling Actor.

  • The method will return a list of all the actors within a given radius, like with radar
  • As with other collision detection methods, you can restrict the type to a single class of actors such as Asteroid
  • Once we get the list of objects in range, we process the list with a loop
  • Each asteroid on the list gets its hit() method called to apply damage
  • We can see how the method is used in the following code

Detecting Asteroids in Range

Textbook figure 7.4

ProtonWave Method checkCollision() Called from act()

private void checkCollision()
{
    int range = getImage().getWidth() / 2;
    List<Asteroid> asteroids =
        getObjectsInRange(range, Asteroid.class);

    for (Asteroid a : asteroids) {
        a.hit(DAMAGE);
    }
}

Breaking Up

  • The hit() method calls the breakUp() method
  • If the size is not too small, the breakUp() method executes the following code
  • The code replaces the current asteroid with two smaller asteroids
  • First the code calculates a direction and speed for the new asteroids
    int r = getMovement().getDirection()
        + Greenfoot.getRandomNumber(45);
    double l = getMovement().getLength();
    Vector speed1 = new Vector(r + 60, l * 1.2); // s/b velocity1
    Vector speed2 = new Vector(r - 60, l * 1.2); // s/b velocity2
    
  • Then it constructs the new asteroids and adds them to the world
    Asteroid a1 = new Asteroid(size/2, speed1);
    Asteroid a2 = new Asteroid(size/2, speed2);
    getWorld().addObject(a1, getX(), getY());
    getWorld().addObject(a2, getX(), getY());
    
  • Finally, the code removes the current asteroid from the world
    getWorld().removeObject(this);
    

Asteroid Method breakUp()

private void breakUp()
{
    Greenfoot.playSound("Explosion.wav");

    if (size <= 16) {
        getWorld().removeObject(this);
    }
    else
    {
        int r = getVelocity().getDirection() + Greenfoot.getRandomNumber(45);
        double l = getVelocity().getLength();
        Vector speed1 = new Vector(r + 60, l * 1.2);
        Vector speed2 = new Vector(r - 60, l * 1.2);
        Asteroid a1 = new Asteroid(size/2, speed1);
        Asteroid a2 = new Asteroid(size/2, speed2);
        getWorld().addObject(a1, getX(), getY());
        getWorld().addObject(a2, getX(), getY());
        a1.move();
        a2.move();

        getWorld().removeObject(this);
    }
}

Check Yourself

  1. True or false: The method getObjectsInRange() returns a list of actors within a specified range
  2. In the checkCollision() method, the loop used to process the list of Asteroid objects is officially known as the ________ for loop, but most people call it the ________ loop.
  3. True or false: the breakUp() method will replace the current asteroid with two smaller asteroids as long as the asteroids have not gotten too small.

10.2.5: Adding Reload Delay

  • The proton wave could be fired at any time
  • However, the game would be boring if we could continuously use a proton wave
  • To improve the game play, Rocket adds a delay to the firing of the proton wave
  • The code involved in firing a proton wave is shown below
  • What do you notice about the pattern of the code? Click to show answer
  • Notice that the protonReloadTime variable is a constant (see lesson 5.1.4)

Rocket Code to Add a Reload Delay

private static final int protonReloadTime = 500;
private int protonDelayCount; // 1

public void act()
{
    // Other code omitted
    protonDelayCount++; // 2
}

private void startProtonWave()
{
    if (protonDelayCount >= protonReloadTime) // 3
    {
        ProtonWave wave = new ProtonWave();
        getWorld().addObject (wave, getX(), getY());
        protonDelayCount = 0;
    }
}

Check Yourself

  1. What are the three parts to controlling the reload delay over multiple scenario cycles? Click to show answer
  2. True or false: the protonReloadTime variable sets the number of game cycles before the proton wave can fire again.
  3. The variable protonReloadTime is hard to differentiate from other variables. A better coding style to make its purpose more clear would be to use all ________ letters in its name.

Exercise 10.2: Status Bar (12m)

In this exercise, we add a proton wave recharge indicator.

Specifications

  1. Open your scenario from the last Try It.

    If you did not keep the scenario, then download asteroids-2b.gfar, save it to a convenient location like the Desktop and double-click the file to launch the scenario.

  2. Save the following files to the scenario, replacing the existing files:
  3. Create a new actor named StatusBar without an image.

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

  4. Add a constant for the default color.
    private static final Color DEFAULT_COLOR = new Color(0, 255, 0, 128);
    
  5. Add instance variables to store the data for the status bar.
    private Color barColor = DEFAULT_COLOR;
    private GreenfootImage image;
    private int width;
    private int height;
    private int percentFilled;
    
  6. Add a method named makeImage() that makes a rectangular image of size width by height containing a bar controlled by the percentFilled variable:
    private void makeImage()
    {
        image = new GreenfootImage(width, height);
        image.setColor(Color.WHITE);
        image.drawRect(0, 0, width - 1, height - 1);
        int barWidth = (int) (percentFilled / 100.0
            * (width - 2));
        image.setColor(barColor);
        image.fillRect(1, 1, barWidth , height - 2);
        setImage(image);
    }
    
  7. Add two constructors to the class that call the makeImage() method:
    public StatusBar()
    {
        this (100, 25);
    }
    
    public StatusBar(int newWidth, int newHeight)
    {
        width = newWidth;
        height = newHeight;
        makeImage();
    }
    
  8. Add a method named setPercentageFilled() to set the percentFilled variable:
    public void setPercentageFilled(int percentageFilled)
    {
        if (percentageFilled < 0)
        {
            percentageFilled = 0;
        }
        else if (percentageFilled > 100)
        {
            percentageFilled = 100;
        }
        if (percentFilled != percentageFilled)
        {
            percentFilled = percentageFilled;
            makeImage();
        }
    }
    
  9. Add a method named setBarColor() to set the color of the status bar:
    public void setBarColor(Color newBarColor)
    {
        if (newBarColor == null)
        {
            newBarColor = DEFAULT_COLOR;
        }
        if (!barColor.equals(newBarColor))
        {
            barColor = newBarColor;
            makeImage();
        }
    }
    
  10. Add two get-methods for accessing the width and height:
    public int getWidth()
    {
        return width;
    }
    
    public int getHeight()
    {
        return height;
    }
    
  11. Compile the class and verify there are no errors.

    If you have problems, compare your work to the StatusBar.java file or ask a classmate or the instructor for help as needed.

  12. Open the editor for the Rocket class and add the following variable:
    private StatusBar protonLoad;
    
  13. Also in the Rocket class and add the following method:
    public void addedToWorld(World world)
    {
        protonLoad = new StatusBar(80, 20);
        protonLoad.setPercentageFilled(100);
        protonLoad.setBarColor(new Color(0, 255, 255, 128));
        int x = world.getWidth()
            - protonLoad.getWidth() / 2 - 10;
        int y = world.getHeight()
            - protonLoad.getHeight() / 2 - 10;
        world.addObject(protonLoad, x, y);
    }
    
  14. Finally, in the Rocket class, add the following statement to the act() method:
    protonLoad.setPercentageFilled(protonDelayCount / 5);
    
  15. Compile and run your updated scenario and verify there are no errors.

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

  16. Save a copy of your scenario as we will be adding to it in the next exercise.

    Only submit the final scenario with all the lesson exercises completed, not the intermediate scenarios.

When finished please help those around you.

10.2.6: Review

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

  1. Storing data so that future requests for the data can be served faster is known as __________. (10.2.2)
  2. True or false: a GreenfootImage array stores all the image data in the reference variable. (10.2.2)
  3. True or false: the array of GreenfootImages referred to by the reference variable stores all the image data. (10.2.2)
  4. True or false: each image of an array of images is stored at various locations in main computer memory. (10.2.2)
  5. The GreenfootImage method that changes the size of an image is __________. (10.2.2)
  6. True or false: static member variables can be accessed by static methods. (10.2.2)
  7. True or false: instance member variables can be accessed by static methods. (10.2.2)
  8. The three parts to controlling timing over multiple scenario cycles are: (10.2.3)
    1. _____________________________
    2. _____________________________
    3. _____________________________
  9. True or false: The method getObjectsInRange() returns a list of actors within a specified range. (10.2.4)
  10. Rewrite the following for-loop as an enhanced for loop: (10.2.4)
    for (int i = 0; i < rocks.size(); i++)
    {
        Asteroid rock = rocks.get(i);
        rock.hit(DAMAGE);
    }
    
  11. The variable protonReloadTime is hard to differentiate from other variables. What would be a better coding style to make its purpose more clear? (10.2.5)

10.3: Scoring and Text

Learner Outcomes

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

  • Write code to keep track of game scores
  • Display text and numbers in a scenario

10.3.1: Counting the Score

  • In this section we continue with our Asteroids modifications
  • If you did not keep the scenario, then download asteroids-2b.gfar, save it to a convenient location like the Desktop and double-click the file to launch the scenario.
  • Then save the following files to the scenario, replacing the existing files:

Keeping Score

  • Asteroids has a "spinning" score keeping system implemented in the Counter class
  • The Counter class displays the text "Score: " followed by a number
  • As the score changes, the number displayed moves up or down to keep up
  • Let us look at the code for the Counter class

Constructing the Data

  • Starting at the top, we see one constant and 4 variables
    private static final Color transparent = new Color(0,0,0,0);
    
    private GreenfootImage background;
    private int value;
    private int target;
    private String prefix;
    
  • The value is the number displayed and target is the actual score
  • The variable prefix is the string displayed before the number

Constructors for Class Counter

public Counter()
{
    this(new String());
}

/**
 * Create a new counter, initialised to 0.
 */
public Counter(String prefix)
{
    background = getImage();  // get image from class
    value = 0;
    target = 0;
    this.prefix = prefix;
    updateImage();
}

Initializing a Counter

  • The job of the constructor is to initialize variables, which the default constructor accomplishes by chaining to the second constructor
    public Counter()
    {
        this(new String());
    }
    
  • Looking at the last line of the second constructor, we see it calls a method:
    updateImage();
  • The updateImage() method shows the key steps to displaying text in Greenfoot
  • Looking at this method, what steps do you see?

Method updateImage() Displays Text

private void updateImage()
{
    GreenfootImage image = new GreenfootImage(background);
    GreenfootImage text = new GreenfootImage(prefix + value, 22, Color.BLACK, transparent);

    if (text.getWidth() > image.getWidth() - 20)
    {
        image.scale(text.getWidth() + 20, image.getHeight());
    }

    image.drawImage(text, (image.getWidth()-text.getWidth())/2,
                    (image.getHeight()-text.getHeight())/2);
    setImage(image);
}

Spinning the Score

  • Recall the two numbers used for keeping score
    private int value = 0;
    private int target = 0;
    
  • The value is the number displayed and target is the actual score
  • The two score numbers allow the display to spin from the value to the target
  • Each game cycle brings the value one number closer to the target
  • The code to "spin" the score is in the act() method listed below

Code to "Spin" the Score

public void act()
{
    if (value < target) {
        value++;
        updateImage();
    }
    else if (value > target)
    {
        value--;
        updateImage();
    }
}

Testing the Spin

  • We can see the spinning effect if we add a method to Space like:
    public void addToScore(int amount)
    {
        scoreCounter.add(amount);
    }
    
  • Then we test the spin by right-clicking the world background and selecting addToScore(int amount)
  • We enter a number and press the OK button
  • When we press the Act or Run button, we will see the "spinning" effect

Check Yourself

  1. True or false: to display text in Greenfoot, we draw it on an image.

10.3.2: Drawing Text

  • Remember in lesson 8.3.2 we discussed how to draw shapes
  • To draw shapes, we called drawing and filling methods of the GreenfootImage class
  • One of the drawing methods is drawString():

    drawString(string, leftX, baselineY): draws the string on the image at the specified location.

  • Where:
    • string: the text to draw on the image
    • leftX is the x-coordinate from the left edge of the image
    • baselineY is y-coordinate of the baseline of the text
  • We can see these locations in the following image:

  • When we call drawString(), we are drawing text onto the image
    image.drawString(text + value, 1, 12);
  • In order to draw all the text, we must have an image that is of sufficient size
  • When providing space, we must allow room for the entire height including the descent
  • At the same time, we do not want an image that is overly large or we waste memory space
  • Leading ("ledding" and not "leeding") is the spacing between lines
  • If we are drawing a single line of text then leading is optional
  • Note that when we draw the string, it will be drawn in the current color and font setting of the image
  • The following example shows how to create a transparent label
  • The image must be set into an Actor subclass
  • Images can only be displayed in World or Actor subclasses.

Creating a Label

  • To create a label we use the following constructor of the GreenfootImage class:

    public GreenfootImage(string, fontSize, foregroundColor, backgroundColor)

  • Where:
    • string: the string to draw on the image
    • fontSize: the approximate size of the font in pixels
    • foregroundColor: the color of the text; null is black
    • backgroundColor: the color of the background behind the text; null is transparent
  • For example, we can construct a simple label with the code:
    GreenfootImage label = new GreenfootImage("test string",
        16, Color.WHITE, new Color(0, 0, 0, 0));
    setImage(label);
    
  • We must still set the image into an Actor subclass
  • Another variation exists that allows us to draw an outline around each character of the string
  • Note that we cannot control the placement of the text within the image

Try It: Create a Label (3m)

  1. Start Greenfoot and open the Asteroids scenario from the last exercise or asteroids-2b.gfar if you did not complete the last exercise.
  2. Add a subclass of Actor named Label using No image as we will make our own.
  3. Open the editor for the Label class and add the following constructor.
    public Label(String text)
    {
       GreenfootImage label;
       label = new GreenfootImage(text, 16, Color.CYAN, new Color(0, 0, 0, 0));
       setImage(label);
    }
    
  4. Test the Label class by:
    1. adding a Label object to the world.
    2. entering text in double quotes (like "Test") inside the popup box
  5. Save your updated scenario as we will be adding to it in the next exercise.
  6. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. The GreenfootImage method to draw a string on an image is ________.
  2. True or false: a zero value for the y-coordinate of the drawString() method would hide most of the string.
  3. The six letters of the alphabet that have a descent are ________
  4. True or false: to display a label (image with text) we must set the image into an Actor subclass.
  5. True or false: Starting with Greenfoot 2.0.1, we can create an image with text drawn on it in one statement.

10.3.3: Text and Fonts

  • A font is a set of text characters
  • We can control the font of the text we write onto an image using class Font
  • Class Font contains methods and constants for specifying fonts
  • The usual Font constructor takes three arguments:

    Font(fontName, fontStyle, fontSize)

  • Where:
    • fontName: name of the font like "Monospaced", "SansSerif", "Serif", etc.
    • fontStyle: Font.PLAIN, Font.ITALIC or Font.BOLD
    • fontSize: size of the font measured in points (1/72 of inch)
  • For example:
    int FONT_SIZE = 24;
    Font f = new Font("Serif",
                      Font.BOLD | Font.ITALIC,
                      FONT_SIZE);
    
  • Java guarantees that at least three font names will be available:
    • Monospaced
    • SanSerif
    • Serif
  • Any other font depends on the users system
  • Thus it is a good idea to use one of the guaranteed fonts in a scenario
  • Notice how we can combine multiple font styles by separating each style with a vertical bar "|"
  • The single vertical bar is known as the bitwise inclusive OR operator

Changing Fonts

  • The GreenfootImage class has methods to set and get fonts as shown below
  • Notice that the Counter class does not set a font
  • Instead, it uses the default font of GreenfootImage
  • However, the ScoreBoard class does get and set fonts in the makeImage() method
  • Here is an excerpt from the makeImage() method:
    Font font = image.getFont();
    font = font.deriveFont(FONT_SIZE);
    image.setFont(font);
    
  • Notice the calling of method deriveFont() in the above excerpt
  • This is another way to create a font: derive one font from another
  • The overloaded method deriveFont() creates a new font with a different style, size or other transformation

Some GreenfootImage Methods for Working with Fonts

Method Description
getFont() Returns the current font.
setFont(Font f) Set the current font for subsequent text operations.

Some Commonly Used Font Methods for Deriving fonts

Method Description
deriveFont(float size) Creates a new Font object by replicating the current Font object and applying a new size.

Check Yourself

  1. A font is a set of text ________.
  2. Of the following, font ________ is not a parameter of the Font constructor.
    1. font name
    2. font style
    3. font size
    4. font character
  3. Java guarantees three fonts will exist: ________, ________ and ________.
  4. The three styles available for a font are ________, ________ and ________.
  5. True or false: the only way to create a Font object is to call a Font constructor.

More Information

10.3.4: Making a Text Area

  • We have looked at how to make single lines of text
  • Now we look at how to make text areas with multiple lines of text
  • As an example, we look at the code for makeImage() in Scoreboard

Method makeImage() of ScoreBoard

private void makeImage(String title, String prefix, int score)
{
    GreenfootImage image = new GreenfootImage(WIDTH, HEIGHT);
    image.setColor(new Color(255, 255, 255, 128));
    image.fillRect(0, 0, WIDTH, HEIGHT);
    image.setColor(new Color(0, 0, 0, 128));
    image.fillRect(5, 5, WIDTH - 10, HEIGHT - 10);

    Font font = image.getFont();
    font = font.deriveFont(FONT_SIZE);
    image.setFont(font);
    image.setColor(Color.WHITE);
    image.drawString(title, 60, 100);
    image.drawString(prefix + score, 60, 200);
    setImage(image);
}

Preparing the Image

  • The first block of code prepares an image for drawing multiple lines of text
  • The following two lines make a translucent background used for the border:
    image.setColor(new Color(255, 255, 255, 128));
    image.fillRect(0, 0, WIDTH, HEIGHT);
    
  • Then the next two lines hollow out the inner area by overlaying a black translucent background:
    image.setColor(new Color(0, 0, 0, 128));
    image.fillRect(5, 5, WIDTH - 10, HEIGHT - 10);
    

Drawing the Text

  • The next block of code draws the text onto the prepared image
  • First the code creates and sets a new font:
    Font font = image.getFont();
    font = font.deriveFont(FONT_SIZE);
    image.setFont(font);
    
  • Then the code sets the color of the text:
    image.setColor(Color.WHITE);
    
  • After this the two lines of text are written onto the image:
    image.drawString(title, 60, 100);
    image.drawString(prefix + score, 60, 200);
    
  • Finally, the image is set for display:
    setImage(image);
    

Centering the Text Area

  • The game adds the score board in the gameOver() method of Space
  • The code makes sure that the score board is centered no matter the size of the scenario screen
  • Can you see how the centering works?

Method gameOver() of Space

public void gameOver()
{
    int finalScore = scoreCounter.getValue();
    ScoreBoard sb = new ScoreBoard(finalScore);
    addObject(sb, getWidth() / 2, getHeight() / 2);
    removeObjects(getObjects(Bullet.class));
}

Simplified Text Areas

  • We can use the GreenfootImage class to make text areas as well
  • We can use the same constructor of the GreenfootImage class as we did with labels:

    public GreenfootImage(string, fontSize, foregroundColor, backgroundColor)

  • Where:
    • string: the string to draw on the image
    • fontSize: the approximate size of the font in pixels
    • foregroundColor: the color of the text; null is black
    • backgroundColor: the color of the background behind the text; null is transparent
  • The technique is to use a "\n" to split the list of text
  • For example, we can construct a simple text area using:
    String text = "first line\nsecond line";
    Color bg = new Color(0, 0, 0, 128);
    Color fg = new Color(0, 0, 0);
    setImage(new GreenfootImage(text, 16, fg, bg));
    
  • We must still set the image into an Actor subclass
  • Also, all of the text is the same font size and color

Try It: Add Directions (4m)

  1. Start Greenfoot and open the Asteroids scenario from the last Try It.
  2. Add a subclass of Actor named Directions using No image as we will make our own.
  3. Open the editor for the Directions class and add the following constructor.
    public Directions()
    {
        String text = "Directions\n\nUse the arrow keys to control ";
        text = text + "the rocket.\nUse the Space bar to fire bullets.\n";
        text = text + "Press the Z key to activate the Proton Wave.";
        Color bg = new Color(255, 255, 255, 128);
        Color fg = new Color(0, 0, 0);
        GreenfootImage img = new GreenfootImage(text, 24, fg, bg);
        setImage(img);
    }
    
  4. Next add the following line of code to the act() method:
    getWorld().removeObject(this);
    
  5. Test the Directions class by adding an Directions object to the world. Press the Act button to verify the directions remove themselves from the world.
  6. Open the editor for the Space class and add a Directions object to the world using addObject().
  7. Save your updated scenario as we will be adding to it in the next exercise.
  8. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. A text area contains multiple lines of ________.
  2. True or false: The (x, y) coordinates of an Actor are located at the Actor's center point when placed into a world
  3. To center an Instructions object in the world, use the code ________.
    1. addObject(new Directions(), getWidth() / 2, getHeight() / 2);
    2. addObject(new Directions(), getWidth(), getHeight());
    3. addObject(getWidth() / 2, getHeight() / 2, new Directions());
    4. addObject(new Directions(), getHeight() / 2, getWidth() / 2);
  4. A "\n" character causes the next character of text to ________.
    1. display "n"
    2. display on the next line
    3. display on the previous line
    4. start over

10.3.5: Restarting the Scenario

  • When the Asteroids game ends, we want to let players restart the game
  • To restart the game, we need to:
    • Remove the Asteroids from the world
    • Add a new set of asteroids to the world
    • Add a new rocket to the world
    • Set the score to 0
    • Remove the score board from the world
  • Most of the code belongs is in the Space class
  • However, we need to start the process in the ScoreBoard class

Starting the Restart

  • One way to restart the scenario is to have the user click the score board
  • In essence, we turn the ScoreBoard class into a simple button
  • To turn the class into a button we add code to the act() method as shown below

Method act() of ScoreBoard

public void act()
{
    if (Greenfoot.mousePressed(this))
    {
        Space space = (Space) getWorld();
        space.restartGame();
        space.removeObject(this);
    }
}
  • When the user clicks the score board, the method gets a reference to the Space world
  • With a reference to the Space world, we can call the restartGame() method
  • Method restartGame() is a new method that must be added to Space
  • We can see the method below

Method restartGame() Added to Space

public void restartGame()
{
    // Remove existing game elements
    removeObjects(getObjects(Asteroid.class));
    removeObjects(getObjects(StatusBar.class));
    removeObjects(getObjects(Rocket.class));
    // Add new game elements
    addAsteroids(startAsteroids);
    addObject(new Rocket(), getWidth()/2 + 100, getHeight()/2);
    // Reset score
    scoreCounter.add(-scoreCounter.getValue());
}
  • The first two lines get a list of all the Asteroid objects and removes them from the world
  • To remove the asteroids, the code calls the method:

    getObjects(Class cls): Returns a list of all the objects in the world.

  • We can restrict the type to a single class of actors like Asteroid
  • With the list we can call another method:

    removeObjects(Collection objects): Remove a list of objects from the world.

  • Using these two methods in sequence makes it easy to remove all the objects of a single type from a world
  • The next three lines create a new set of asteroids and add a rocket
  • Next, the scoreCounter is set to zero

Check Yourself

  1. To make a button out of an Actor, test for ________ in the act() method.
  2. The two methods of the World class do we call in sequence to remove all the objects of a single type from a world are ________.
    1. findObjects() and deleteObjects()
    2. gameOver() and stop()
    3. getObjects() and deleteObjects()
    4. getObjects() and removeObjects()

Exercise 10.3: (4m)

In this exercise, we modify the ScoreBoard and add code to restart the game.

Specifications

  1. Start Greenfoot and open your completed Asteroids scenario from Exercise 10.2 or the last Try It!.

    If you did not keep the scenario, then download asteroids-2b.gfar, save it to a convenient location like the Desktop and double-click the file to launch the scenario. Then save the following files to the scenario, replacing the existing files:


  2. Compile and run the scenario to verify it works well before you start.

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

  3. Complete the Try It activities we explored throughout the section including:
    1. Try It: Create a Label
    2. Try It: Add Directions
  4. Open the editor for the Space class and add the following method:
    public void restartGame()
    {
        // Remove existing game elements
        removeObjects(getObjects(Asteroid.class));
        removeObjects(getObjects(StatusBar.class));
        removeObjects(getObjects(Rocket.class));
        // Add new game elements
        addAsteroids(startAsteroids);
        addObject(new Rocket(), getWidth()/2 + 100, getHeight()/2);
        // Reset score
        scoreCounter.add(-scoreCounter.getValue());
    }
    
  5. Compile the class and then test the change by right-clicking on the world background and selecting the method restartGame().

    You should see the asteroids change position on every restart. Resolve any errors you find, getting help from a classmate or the instructor as needed.

  6. In the ScoreBoard class, add the following act() method:
    public void act()
    {
        if (Greenfoot.mousePressed(this))
        {
            Space space = (Space) getWorld();
            space.restartGame();
            space.removeObject(this);
        }
    }
    
  7. Compile and test your scenario to verify all the changes work well.

    The scenario should restart when the player clicks the score board. If you have problems, ask a classmate or the instructor for help as needed.

  8. Save a copy of your completed lesson scenario to upload to Canvas as part of lab 9.

When finished please help those around you.

10.3.6: Review

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

  1. True or false: to display text in Greenfoot, we draw it on an image. (10.3.1)
  2. For the following code snippets, what is the value of stringLength? (10.3.1)
    scoreCounter = new Counter("Score: ");
    ...
    public Counter(String prefix)
    {
        text = prefix;
        stringLength = (text.length() + 2) * 10;
    // rest of class omitted
    
  3. Using the stringLength calculation from the previous question, what is the width of the image and what is the height in the following code? (10.3.1)
    new GreenfootImage(stringLength, 16)
  4. The GreenfootImage method to draw a string on an image is _______________. (10.3.2)
  5. The optimal image size when drawing text on a transparent image is (10.3.2)
    1. the size of the scenario's world.
    2. large enough for the text and no larger.
    3. WIDTH wide and HEIGHT high.
    4. as large as need be to make the image look good.
  6. Images can only be displayed in World or _____________ subclasses. (10.3.2)
  7. True or false: a zero value for the y-coordinate of the drawString() method would hide most of the string. (10.3.2)
  8. True or false: Starting with Greenfoot 2.0.1, we can create an image with text drawn on it in one statement. (10.3.2)
  9. What is a font? (10.3.3)
  10. Which of the following is not a parameter of the Font constructor?
    1. font name
    2. font style
    3. font size
    4. font alphabet
  11. What three font names are guaranteed by Java to exist on all computer systems? (10.3.3)
  12. What three styles are available for a font? (10.3.3)
  13. True or false: the only way to create a Font object is to use a Font constructor. (10.3.3)
  14. Which of the following is NOT one of the steps for making a multi-line text area? (10.3.4)
    1. Prepare an image
    2. Draw text on an image using drawString()
    3. Set the image to be displayed in an Actor
    4. Create a subclass of the Text class and calling its methods
  15. True or false: The (x, y) coordinates of an Actor are located at the Actor's center point. (10.3.4)
  16. To make a button out of an Actor, test for _____________ in the act() method. (10.3.5)
  17. What two methods do we call in sequence to remove all the objects of a single type from a world? (10.3.5)

10.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

10.4.1: About the Exam

Important Midterm Exam Information

Date: 4/13/2017
Location: Regular classroom
Start time: During the regular class time

  • 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
  • Blank scratch paper is allowed
  • You may use a computer from the classroom, but only to:
    1. take the exam in Canvas
    2. compile and run programs in Greenfoot
  • You may NOT use the computer to:
    1. view documents on the Internet
    2. look at the Greenfoot documentation
    3. look at pre-existing scenarios
  • You may NOT use a calculator, cell phone or any 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

  • Put your name on your card
  • 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

About Compiling

  • Code that does not compile contains an error
  • When given the tools to compile, your code must compile for a good score
  • Expect to lose points for every line that does not compile
  • If you are having problems compiling, comment out the lines that do not compile
  • Partial credit is available if you comment out your problem code

10.4.2: Test Preparation Recommendations

Top Rated Study Areas from Students

  1. Practice problems
  2. Reviewing notes
  3. Reviewing homework projects
  4. Student prepared study questions
  5. Reviewing CodeLab

Other Recommendations from Students

  • Review shadowing and "this"
  • Read the instructions and do not skip a part of the question
  • Add more to the index card
  • Study more

10.4.3: Exam Topics

  • To help you prepare for the exam, I am providing a list of exam topics
  • In return, I want each student to pick one topic and prepare 5 Jeopardy-style questions for their topic
  • Also, develop a short Jeopardy-style category name
  • At the next class meeting we will review the questions to help us prepare for the midterm
  • For reference, here are the topics for the prior midterm: Boss Basic Topics

New Exam Topics

  1. Abstraction and abstract classes (7.2.3, 9.1.1, Exercise 9.1)
  2. Actor movement with setLocation(), getX() and getY() (2.2.5, 5.1.1, 5.2.3)
  3. Alternation and if-statements (4.3.6, 4.3.7, 5.2.1, 9.2.4)
  4. Arrays (7.3.5, 7.3.6, 8.3.5, 10.2.2)
  5. Arithmetic and floating-point numbers (4.4.3, 4.4.4, 9.1.3, 9.2.5)
  6. Boolean values and variables (2.3.1, 7.2.1)
  7. Constructors, parameters and overloading (4.2.1, 4.3.5, 7.2.4, 7.4.5, 9.1.1, 9.1.4)
  8. Constant variables (5.1.4, 8.2.3, 9.1.1)
  9. Color and transparency (7.4.1, 7.4.2, 8.3.1, 8.3.6)
  10. Images and drawing shapes (7.4.3, 8.2.2, 8.3.2, 8.3.3, 10.3.2)
  11. Keeping time with game cycles (6.1.5, 10.1.4, 10.2.3, 10.2.5)
  12. Lists, generic types and the for-each loop (8.1.4, 8.1.5, 9.2.3, 9.2.4, 10.2.4)
  13. Loops, repetition and counting (5.1.5, 7.3.2, 7.3.3, 7.3.4, 9.3.1, 10.2.2)
  14. Logical operators (5.2.2, 5.2.3, 7.2.2, 9.3.4)
  15. Local variables, parameters and shadowing (7.2.5, 9.1.5)
  16. static variables and methods (5.1.4, 7.2.6, 10.2.2)
  17. Mouse presses, clicks and info (7.2.6, 8.1.5, Exercise 8.1, 10.3.5)
  18. Pair programming 7.5
  19. Referencing the world and casting (5.3.2, 6.2.3, 8.1.2, 9.3.4, 10.1.6, 10.3.5)
  20. Reference variables, null and communicating between actors, (4.3.5, 6.1.6, 8.1.3, 8.1.4, 8.3.5, 9.1.1, 9.2.2, 10.1.5)
  21. this and this() (5.3.3, 7.4.5, 9.1.1, 9.1.5)
  22. Strings and concatenation (3.5.1, 3.5.2, 6.1.4, 7.2.4, 7.3.4)

Exercise 10.4

Take a minute to review the above topics and select one of them to prepare 5 potential test questions for Lab B.

As a homework for the next class meeting, prepare a list of 5 Jeopardy-style questions/answers on your topic.

Jeopardy-style questions/answers have a twist. You provide the answer and the player states the question. For example, an answer is, "In the Java Programming language, this variable type only has a value of either true or false." The player would pose the question as, "What is boolean?"

Post the questions in the Discussions area of Canvas. For each answer, supply a question and a point value of 100, 200, 300, 400 or 500. Remember to write each question in the Jeopardy style.

10.4.4: More Test Preparation

  • To help you study, you can use this review game: Greenfoot Jeopardy
  • The question set for this exam is "l33t.tx" 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:
Q9: Gravitational Attraction (4/6/17)
Lab 10: Boss Questions (4/11/17)
Q10: Leet Arcane Studies (4/13/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: April 06 2017 @17:15:41