7. Interacting Objects

What We Will Cover


Illuminations

Questions from last class or the Reading?

Midterm Questions

Homework Questions?

7.1: Reviewing Newton's Lab

Learner Outcomes

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

  • Describe vectors
  • Work with an abstract class
  • Discuss mixed mode arithmetic
  • Write overloaded constructors and methods
  • Prevent shadowing of variables
  • Use this() within a constructor

7.1.1: Interacting Objects and Abstraction

  • The book scenario is a simulation of bodies in a solar system
  • Lets download and install the second completed scenario:

    Scenario file: Newtons-Lab-2.zip.

  • Save the file inside the Greenfoot scenarios folder.
  • Start Greenfoot and open the scenario (Greenfoot unzips the file for us)
  • By right-clicking on the background, we can see a list of three simulations
  • Before we continue, lets review some key concepts from the chapter

Concept Review

  • Abstract class: a superclass that cannot be instantiated
  • Constant: a variable that you cannot change
  • Collection: a type of object that can hold many other objects
  • Generic type: a type that needs a second type name as a parameter
  • List: a type of collection where objects are stored in an order
  • null: a special word for "no object"
  • Overloading: same method name for two different methods or constructors
  • this(): used to call one constructor from another

Reviewing the Newton's Lab Scenario

  • The main types of bodies in the solar system include the sun, planets and moons
  • Each of these bodies vary in size, mass, composition and velocity
  • However, these bodies are similar in many ways
  • Because each body has a size, mass and velocity, we can use abstraction to program a Body class
  • The Body class, or its superclasses, has variables to store size, mass and velocity
  • To set each characteristics, we have a parameter in the Body class constructor

    public Body(int size, double mass, Vector movement, Color color)

Abstract Classes

  • The scenario uses two helper classes: SmoothMover and Vector
  • SmoothMover is the superclass of Body
  • If we right-click on SmoothMover, we notice that we cannot create an object
  • Examining SmoothMover, we see that it has a new keyword in the header: abstract
  • We declare classes abstract when we do NOT want to create objects from them
  • Abstract classes serve only as superclasses for other classes

Check Yourself

  1. When we simplify a set of real objects, like astronomical objects, to basic shared characteristics, like a Body class, we are using a process known as ________.
    1. abstraction
    2. an abstract class
    3. summarization
    4. deep thought
  2. True or false: we can use a parameter in a constructor to customize how an object operates.
  3. True or false: An abstract class can be created by right-clicking on the class in Greenfoot.
  4. True or false: All abstractions are composed in abstract classes.

7.1.2: Vectors

  • Objects that move (for example planets) have a velocity
  • Velocity is both a speed (such as 100 MPH) and a direction (such as up)
  • Because of these two aspects, velocity is often represented as a vector
  • A vector is a geometric object with both direction and length (magnitude)
  • Thus we often use vectors to represent velocity

    A vector with direction and length

  • The above representation is known as polar coordinates
  • Another way to represent a vector is as a pair of distances (dx, dy)
  • The d in (dx, dy) stands for delta, a Greek letter used in science and engineering to mean a change
  • Here is the same vector using (dx, dy):

    A vector with (dx, dy)

  • This second image is called the Cartesian representation
  • The book used a separate Vector class to work with vectors
  • The Vector class is used by the SmoothMover class to control movement

Check Yourself

  1. A geometric object with both direction and length is called a(n) ________.
  2. Specifying a vector using direction and length is known as the ________ representation.
  3. Specifying a vector as a pair of distances (dx, dy) is known as the ________ representation.

7.1.3: Smooth Moving and Type double

  • The purpose of SmoothMover is to position and smoothly move objects on the screen
  • It works by using floating-point (decimal) numbers rather than integers
  • For example, SmoothMover can have the x-coordinate 21.3
  • The important thing to notice is the decimal point
  • If we move an actor along the x-coordinate in increments of 0.7 we have:
    21.3, 22.0, 22.7, 23.4, 24.1, 24.8, ...
    
  • Since a screen only allows integer numbers, we have to convert the numbers to integers:
    21, 22, 23, 23, 24, 25, ...
    
  • Even though the numbers are rounded for display, the effect is smoother movement

Floating-Point Data Types

  • Let us discuss more about floating-point numbers
  • In lesson 4.3.3, we learned that Java has two general types of numbers: integers and floating-point
  • Further, Java has two floating-point number data types: float and double
  • Type float uses 4 bytes of storage and type double uses twice as much (hence the name)
  • Since type double uses twice as much memory it is more precise that float
  • As with type int, you can declare variables of type float or double:
    double total;
    float away;
    
  • At this point in your programming career, you should always use type double for decimal numbers
  • The additional memory use is small and the extra precision is usually helpful

Mixed-Mode Arithmetic

  • Remember from lesson 4.3.3 that different data types are stored in different forms
    • An int is stored in 4 bytes in a binary format
    • A double is stored in 8 bytes using a complex format defined by IEEE 754
  • The computer needs both numbers in the same form before it can do arithmetic
  • If one operand is different than the other, the compiler converts it to the wider of the two types
  • For example:
    2 + 2.3
    • The first number (2) is an int
    • The second number (2.3) is a double
  • Java will automatically convert the int to a double (2.0)
  • Then the computer knows how to do the arithmetic to produce a result of 4.3
  • Remember that the result of arithmetic with an int and a double is always a double

Check Yourself

  1. The difference between an integer and a floating point data type is the ability to hold a ________ point.

  2. Example answer
  3. What is the data type of the result for the following arithmetic expressions?
    1. 1 + 2
    2. 1.2 + 3.4
    3. 1 + 2.3

7.1.4: Overloading Constructors and Methods

  • In the SmoothMover class, notice that there are two different constructors:
    public SmoothMover()
    public SmoothMover(Vector movement)
    
  • What is the same between these constructors? What is different?
  • These two constructors allow us to create a new SmoothMover object in two different ways
  • For example:
    SmoothMover s1 = new SmoothMover();
    SmoothMover s2 = new SmoothMover(new Vector(90, 2.2));
    
  • When there is more than one constructor in a class, the constructor is said to be overloaded

    Overloading: having the same method name for two different constructors or methods.

  • When constructors or methods are overloaded, they must have different parameter lists
  • The first constructor has no parameters and is sometimes called a default constructor
  • A default constructor sets instance variables to default values

Method Overloading

  • You can have multiple methods with the same name as well
  • The name of the method is overloaded because it refers to more than one method
  • We see an example of method overloading in the SmoothMover class:
    public void setLocation(double x, double y)
    public void setLocation(int x, int y)
    
  • The names are the same but the parameters are different -- how?

Check Yourself

  1. When two constructors or methods have the same name, this is known as ________.
    1. overridding
    2. overloading
    3. overwhelming
    4. not possible
  2. When different constructors or methods have the same name, they must have different ________.
  3. Of the following methods within a single class, ________ and ________ cannot exist at the same time.
    1. public int foo(int a)
    2. public int foo(int a, int b)
    3. public int foo(double a)
    4. public int foo(double a, double b)
    5. public int foo(int b)

7.1.5: More About this

  • Remember from lesson 5.2.5 that the keyword this means this current object
  • Sometimes the keyword this is used to avoid a problem known as shadowing

Shadowing

  • Shadowing is when a local variable or parameter has the same name as a member variable of a class
  • Local variables or parameters with same name as a member variable hide the member variable
  • Hiding means that the member variable is ignored and the local variable is used
  • One way to solve the hiding problem is to use the keyword this
  • For example, look at the following constructor from SmoothMover:
    private Vector movement;
    // ....
    public SmoothMover(Vector movement)
    {
        this.movement = movement;
    }
    
  • What happens if we remove the keyword this?
  • The problem is that movement is both the name of a member variable and parameter
  • You should avoid giving the same name to both member variables and parameters
  • If you feel they must be the same, then use this to clarify which variable is the instance variable

Another Use for this

  • Java uses the keyword this in yet another way
  • Notice the other constructor from SmoothMover:
    public SmoothMover()
    {
        this(new Vector());
    }
    
  • The body of the constructor has code that looks like a method call: this(new Vector())
  • However, the code uses the keyword this as the name of a method
  • What is happening is that this() calls another constructor in the class
  • Java matches the constructor based on the types of the parameters
  • Note that if this() is used, it must be the first statement within a constructor

Check Yourself

  1. The problem with the following code is ________.
    private int bar;
    public void foo(int bar)
    {
        bar = bar;
    }
    
  2. What are two ways to correct the above problem?
  3. In the following code, this() is used to ________.
    public Baz()
    {
        this(42);
    }
    

Exercise 7.1

In this exercise, we explore the new concepts in our scenario. As you do, you will need to record all the stated questions and their answers in a text file using a text editor.

Specifications

  1. Download the Newtons-Lab-2 scenario file and save it to a convenient location like the Desktop.

    Scenario file: Newtons-Lab-2.zip.

  2. Start Greenfoot and open the scenario.

    Greenfoot unzips the file for us.

  3. Run the scenario and remember how it operates by trying out the three initializing methods:
    • sunAndPlanet()
    • sunAndTwoPlanets()
    • sunPlanetMoon()
  4. Locate the SmoothMover class and try to create a new SmoothMover object.

    Q1: Were you able to construct an object?

  5. Open the editor for the SmoothMover class and remove the word abstract from the class signature:
    public abstract class SmoothMover extends Actor
    
  6. Try to compile the modified SmoothMover class.

    Q2: Were you able to construct an object after removing the abstract keyword?

    Q3: Why would you declare a class abstract?

  7. Restore the SmoothMover class to its original condition.

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

  8. Examine the code for the SmoothMover class and find all the overloaded constructors and methods.

    Q4: Which constructors and methods were overloaded (list their names)?

    For more information see lesson: 7.1.4: Overloading Constructors and Methods.

  9. In the SmoothMover class, find the following code in the first constructor:
    this.movement = movement;
    

    Change the code by removing the "this." so it looks like:

    movement = movement;
    
  10. Compile and run the scenario to see how it changed.

    Q5: What change did you see?

    Q6: Why did this change occur?

    For more information see lesson: 7.1.5: More About this.

  11. Restore the SmoothMover class to its original condition.

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

  12. Using a text editor, create a text file named questions.txt and copy all the highlighted questions into the file. Next, record answers to all the questions in the file under the question.
  13. Review your answers with another student in the class and correct any mistakes.
  14. Add a comment to the top of the file that contains the name of the person with whom you reviewed the questions, like:
    Reviewed with Jane Programmer
    
  15. Save the questions.txt file so you can submit it to Blackboard as part of assignment 6.

As time permits, be prepared to answer the Check Yourself questions in the section: 7.1.6: Review.

7.1.6: Review

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

  1. Reducing a concept or idea to the most simple or basic shared characteristics is known as ________________. (7.1.1)
  2. True or false: All abstractions are composed in abstract classes. (7.1.1)
  3. To make a class from which you cannot instantiate an object use the keyword _________. (7.1.1)
  4. A geometric object with both direction and length is called a(n) _________. (7.1.2)
  5. Specifying a vector using direction and length is known as __________ representation. (7.1.2)
  6. Specifying a vector as a pair of distances (dx, dy) is known as __________ representation. (7.1.2)
  7. Which of the following is a valid declaration of a floating-point variable: (7.1.3)
    1. double scoop;
    2. float boat;
    3. int double;
    4. totally double;
  8. True or false: Of the two floating point types, the type you should normally use is double. (7.1.3)
  9. When adding an int and a double together, the resulting number is of type: (7.1.3)
    1. double
    2. int
    3. float
    4. that depends on the number
  10. When different constructors or methods have the same name they are said to be __________________. (7.1.4)
  11. Within a single class, which of the following methods can exist at the same time? (7.1.4)
    1. public int foo(int a)
    2. public int foo(int a, int b)
    3. public int foo(double a)
    4. public int foo(double a, double b)
    5. public int foo(int b)
  12. Which is an example of overloading the method that follows? (7.1.4)
    public int calcValue(double number) {...}
    1. public double calcValue(double number) {...}
    2. int calcValue(double num) {...}
    3. int calcValue(double number, int value) {...}
    4. All of these
  13. True or false: Shadowing is when a local variable or parameter has the same name as a member variable of a class. (7.1.5)
  14. What are two ways to avoid shadowing? (7.1.5)
  15. True or false: the following code calls another constructor in the same class: (7.1.5)
    public SmoothMover()
    {
        this(new Vector());
    }
    

7.2: Applying Forces

Learner Outcomes

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

  • Write psuedocode to describe algorithms.
  • Write method stubs.
  • Write code to work with lists in Java.
  • Write enhanced for loops to process items in a list.

7.2.1: How a Body Moves

  • The move() method of SmoothMover updates and sets location of the actor
    public void move()
    {
        exactX = exactX + movement.getX();
        exactY = exactY + movement.getY();
        super.setLocation((int) exactX, (int) exactY);
    }
    
  • The act() method in Body calls the move() method
    public void act()
    {
        applyForces();
        move();
    }
    
  • However, before the body moves we must apply the gravitational forces of all the other bodies in space

Algorithms and Psuedocode

  • When faced with a problem like this we develop a computer algorithm to solve it

    Computer algorithm: Precise instructions for a computer to follow to accomplish a task.

  • In other words, we must develop a procedure for the computer to follow in solving the problem
  • A common approach is to use psuedocode to describe the solution
  • Psuedocode is an informal description of the steps for solving a problem
  • Rather than worrying about details of syntax, we use a mixture of English and Java to write the solution
  • For example, here is a psuedocode description of the solution to the problem

Psuedocode Description of an Algorithm to Apply Gravity

Apply forces from other bodies:
   get all other bodies in space;
   for each of those bodies: {
      apply gravity from that body to our own;
   }

Check Yourself

  1. A sequence of precise instructions to accomplish a task is called a(n) ________.
  2. The advantage of using psuedocode, instead of Java code, to describe an algorithm is we can omit the ________ details.
  3. The line of the above pusedocode that describes a loop is ________.
  4. Use psuedocode to describe the algorithm for the move() method.
    public void move()
    {
        exactX = exactX + movement.getX();
        exactY = exactY + movement.getY();
        super.setLocation((int) exactX, (int) exactY);
    }
    

    One possible answer

7.2.2: Implementing the applyForces Algorithm

  • Once we have worked out the algorithm to solve the problem, we need to translate the psuedocode into computer code
  • We start by writing a method stub, like:
    private void applyForces()
    {
    
    }
    
  • A method stub is a syntactically correct method with few or no program statements inside the method
  • We add method stubs to our code as a placeholder until we write the method body
  • If a return value is required, a method stub just returns a "dummy" fixed value like 0 or null
  • Since our method stub has a void return type, we do not need a return statement
  • After implementing a method stub, the code should compile
  • Another thing to notice is that the method is private
  • Mark a method private when it is not intended for use outside the class
  • When a method is intended for use outside the class, mark it public

Finding All the Bodies

  • Our first task is to get all the bodies in Space
  • Since Space is a subclass of World, we look in the World documentation to see how to get access
  • The most promising method is getObjects(), which returns a list of all objects in the world (or space)
    java.util.List getObjects(java.lang.Class cls)
    
  • The parameter is of type Class, which allows us to restrict the output to a certain class of objects like Body
  • We saw this type of parameter before in lesson 2.4.3
  • To call the method, we add a ".class" to the name of the class, like:
    getObjects(Body.class)
    
  • If we want all types of objects, then we use the special keyword null as the parameter:
    getObjects(null)
    
  • Remember that null means "no object"
  • We can only call the getObjects() method with a World object
  • To obtain the World object, we call the getWorld() method of Actor:
    getWorld().getObjects(Body.class)
    
  • The return type of getObjects() is a List, which implies there is a List type in Java
  • We will look at List in the next section

Check Yourself

  1. A method ________ is just enough code to allow the method to compile.
  2. True or false: we add method stubs to our code as a placeholder until we write the method body.
  3. The keyword null means no ________.
  4. Rewrite the following code in one statement rather than two:
    World w = getWorld();
    List<Actor> bodies = w.getObjects(Body.class);
    

    answer

7.2.3: Working with Lists

  • When we work with collections of items, a natural approach is to use a list
  • Java has several classes for working with lists of data

List Types

  • When working with the Java library classes, look first at the Java API
  • Since getObjects() returns a List, look at the API for List
  • When we examine the API, we see that List is an interface and not a class
    Interface List<E>
  • The List interface is a way for Java to specify a common set of methods for many different list classes
  • Which underlying list class the getObjects() method returns is not important
  • We just use the methods of the List interface as a common abstraction of the list classes
  • The following are some commonly used methods of List

Some Commonly Used Methods of List

Method Description
add(item) Adds the specified item to the end of the list.
add(index, item) Adds the specified item at the specified index of the list.
get(index) Retrieves the item at the specified index in the list.
remove(index) Removes the item at the specified index in the list.
set(int index, item) Replaces the item at the specified index in the list.
size() Returns the number of items in the list.

Generic Types

  • Let us look at the description of the list interface again:
    Interface List<E>
  • Notice the <E> after the word List
  • This is known as a generic type
  • When we use a generic type, we must include an additional type specified as a parameter
  • The second type specifies the type of the items stored within the list
  • For example, if we had a list of strings we would declare a list like:
    List<String> names;
    
  • Notice that the class name String replaced the E in the type name
  • In our case we have a list of actors and declare a list like:
    List<Actor> bodies;
    
  • Since we are getting a list from the getObjects() method we write:

    List<Body> bodies = getWorld().getObjects(Body.class);

Check Yourself

  1. To add an item to a List, use the method ________.
  2. To remove an item to a List, use the method ________.
  3. To find out how many items a List contains, use the method ________.
  4. Write an assignment statement that declares a variable names and calls the following method, saving the returned value in the variable.
    List<String> getNames() { /* ... */ }
    

    answer

7.2.4: Applying the Forces

  • We now have a list of all the bodies

    List<Body> bodies = getWorld().getObjects(Body.class);

  • We now need to apply gravity from each body to our current body
  • We do this by going through the list of bodies one by one and apply the force in turn
  • If the force is from our current body, we skip applying the force
  • We can step through each item in a list using a loop as shown below

Method applyForces()

private void applyForces()
{
    List<Body> bodies =
        getWorld().getObjects(Body.class);
    for (Body body : bodies)
    {
        if (body != this)
        {
            applyGravity (body);
        }
    }
}

Enhanced for Loop

  • Notice the for-loop in the above code
  • Officially this loop is known as the enhanced for loop
  • However, most people call this loop the for-each loop
  • The for-each loop is specially designed to work with lists of data, including arrays
  • It reads each item in a list and provides a variable of the list item to work with
  • Syntax:
    for (itemType variableName : listName) {
        // statements to execute
    }
    
  • Where:
    • itemType: the data type of all the list items
    • variableName: the name to use for each variable
    • listName: the name of the list
  • Note that you do not code initialization, test and increment statements
  • Instead, you declare a variable that refers to each array element
  • Within the loop, you use this variable to access each array element
  • For comparison we rewrite the applyForces() method using a standard for loop

Rewriting applyForces() Using a Standard for Loop

private void applyForces()
{
    List<Body> bodies =
        getWorld().getObjects(Body.class);
    for (int i = 0; i < bodies.size(); i++)
    {
        Body body = bodies.get(i);
        if (body != this)
        {
            applyGravity (body);
        }
    }
}

Check Yourself

  1. In the applyForces() method, this refers to the ________ object.
  2. True or false: The method applyForces() applies gravity from every object to the current object
  3. Rewrite the following loop using an enhanced for loop:
    int[] scores = {90, 95, 87, 89, 98};
    for (int i = 0; i < scores.length; i++)
    {
        System.out.println(scores[i]);
    }
    


    Example answer

  4. Which loop requires less code to write: standard or enhanced for loop?

7.2.5: Calculating Gravity

  • We have solved the problem of accessing each object in space
  • However, we still have not applied the actual gravitational force
  • We apply gravity in the applyGravity() method
    private void applyGravity(Body other)
    

About Gravity

  • Gravity is a force of attraction between objects with mass
  • Newton's famous formula for gravity is shown in the following image from Wikipedia:

    F=G(m1 x m2)/r^2

  • Where:
    • F: the force between the masses
    • G: the gravitational constant
    • m1: mass of the first body
    • m2: mass of the second body
    • r: distance between the masses
  • The complete applyGravity() method follows

Method applyGravity()

private void applyGravity(Body other)
{
    double dx = other.getExactX() - this.getExactX();
    double dy = other.getExactY() - this.getExactY();
    Vector force = new Vector (dx, dy);
    double distance = Math.sqrt(dx * dx + dy * dy);
    double strength = GRAVITY * this.mass * other.mass
                      / (distance * distance);
    double acceleration = strength / this.mass;
    force.setLength (acceleration);
    addForce(force);
}

Notes on the Code

  • The first two lines calculate the x and y distances from each other
  • Then we create a new vector using these values
  • The vector has the correct direction but not the correct length
  • We calculate the correct length using the Pythagorean theorem:

    a2 + b2 = c2

  • The image below from the textbook (p. 94) shows the calculation
  • To calculate the square root, we use the Math.sqrt() method from the Java Math class
    double distance = Math.sqrt (dx * dx + dy * dy);
    
  • The next line calculates the strength of the force using Newton's formula
  • The last task is to calculate the acceleration given by Newton's second law of motion:
    F = ma  or  a = F / m
  • This acceleration is used to set the length of the vector force, which is added to the body

Distance in Relation to dx and dy

a^2 + b^2 = c^2

Check Yourself

  1. ________ is a force of attraction between objects with mass.
  2. True or false: the numbers in applyGravity() need to be type double so they are precise.
  3. The Math.sqrt() method has ________ parameter(s).

Exercise 7.2

In this exercise, we experiment with how changes in GRAVITY, mass and initial movement of the bodies affect the stability of the system.

Specifications

  1. Start Greenfoot and open the Newton's Lab 2 scenario from the last exercise.
  2. Run the scenario and remember how it operates by trying out the three initializing methods:
    • sunAndPlanet()
    • sunAndTwoPlanets()
    • sunPlanetMoon()
  3. Change the gravity constant at the top of the Body class and see what happens.
    private static final double GRAVITY = 5.8;
    

    Try changing GRAVITY by 1/2, doubling it, changing it by 1 and by 0.1.

  4. Choose your best value for GRAVITY. Then recompile and run the scenario to verify it works well.

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

  5. Open the Space class and experiment with changes to the mass or initial movement of the bodies.
    addObject(new Body (50, 0.8, new Vector(90, 3.25), ...);
    //                       |               |   |
    //                      mass      direction  movement
    

    When experimenting you should change only one variable at a time.

    Note that you may find it challenging to find a stable system. If so, you may want to read the Wikipedia article: Stability of the Solar System.

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

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

7.2.6: Review

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

  1. What is an algorithm? (7.2.1)
  2. Why do people use psuedocode to describe an algorithm? (7.2.1)
  3. Use psuedocode to describe the algorithm for the following method:
    public void move()
    {
        exactX = exactX + movement.getX();
        exactY = exactY + movement.getY();
        super.setLocation((int) exactX, (int) exactY);
    }
    
  4. Write a method stub for an algorithm that gets two numbers, adds them together and returns their sum. (7.2.2)
  5. What is the special word that stands for, "no object"? (7.2.2)
  6. What line or lines of code will get all the Body objects from within the Body class? (7.2.2)
  7. What methods of the List interface add items to a list? (7.2.3)
  8. What method of the List interface removes items from a list? (7.2.3)
  9. What methods of the List interface finds out how many items are in a list? (7.2.3)
  10. Write a statement that calls the following method and saves the returned value in the variable names: (7.2.3)
    List<String> getNames() { /* ... */ }
    
  11. What does this refer to in the following method? (7.2.4)
    private void applyForces()
    {
        List<Body> bodies =
            getWorld().getObjects(Body.class);
        for (Body body : bodies)
        {
            if (body != this)
            {
                applyGravity (body);
            }
        }
    }
    
  12. Rewrite the following loop using an enhanced for loop: (7.2.4)
    int[] scores = {90, 95, 87, 89, 98};
    for (int i = 0; i < scores.length; i++)
    {
        System.out.println(scores[i]);
    }
    
  13. Which loop requires less code to write: standard or enhanced for loop? (7.2.4)
  14. ____________ is a force of attraction between objects with mass. (7.2.5)
  15. Write a statement that computes the square root of 42. (7.2.5)

7.3: Gravity and Music

Learner Outcomes

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

  • Create a musical animation.
  • Write code to detect collisions between objects.
  • Write code to arrange objects in space.

7.3.1: Playing with Gravity

  • Now that we have a working simulation of planetary bodies, we can play with it
  • The book has an additional scenario that combines music with planetary motion due to gravity
  • Lets download and install the scenario to see what it is like:

    Scenario file: Newtons-Lab-3.zip.

  • Save the file inside the Greenfoot scenarios folder.
  • Start Greenfoot and open the scenario (Greenfoot unzips the file for us)
  • Notice how the scenario is like an inverse of the piano visualizer

The Scenario

  • We have a set of obstacles that play musical notes when struck
  • Several planetary bodies, represented by the circles, move around the screen
  • The movement of the bodies is affected by their gravitational attraction
  • When one of the bodies strikes an obstacle, the obstacle plays a note
  • Do you recognize the musical sounds?

Changes Made

  • New Obstacles class added that plays a note when struck
  • Body class modified so it bounces at the edge of the screen
  • Space class changed to create a fixed row of obstacles
  • We will examine the changes in more detail in the following sections

Check Yourself

  1. An obstacle plays a(n) ________ when struck by a body.
  2. True or false: the scenario bodies are affected by gravity.
  3. True or false: the planetary/obstacle system is stable.

7.3.2: Adding Obstacles

  • The purpose of the Obstacle class is to play a note when struck
  • As such, the obstacles are like the bars on a Xylophone or Glockenspiel

    xylophone picture

  • Looking at the code, each obstacle is assigned a sound in its constructor
  • The act() method checks if the obstacle was hit
  • If the obstacle was struck, it plays a sound

Collision Detection

  • The following code detects the collision of a body with an obstacle
    Actor body = getOneIntersectingObject(Body.class);
    if (body != null)
    {
        // react to collision
    }
    
  • The getOneIntersectingObject() method is from the Actor class
  • The method returns an actor that overlaps with this object
  • If no actor overlaps, then the method returns null
  • Thus we can test for collisions by calling the method and checking the returned value for null
  • Collision detection is an important part of most video games
  • We will see this method again in the next scenario from the book: Asteroids

Check Yourself

  1. An obstacle plays a sound when ________ by a body.
  2. A sound is assigned in the ________ of the Obstacle class.
  3. When one object intersects another it is known as a(n) ________.
  4. The getOneIntersectingObject() method returns ________ when no object intersects an actor.

7.3.3: Bouncing Bodies

  • The Body class is almost the same as the prior scenario
  • Bodies are attracted to each other through the gravitational force of their mass
  • However, bodies now bounce off the edge of the screen
  • The method bounceAtEdge() provides the bounce effect
  • The act() method calls the bounceAtEdge() method

Method bounceAtEdge()

private void bounceAtEdge()
{
    if (getX() == 0
        || getX() == getWorld().getWidth() - 1)
    {
        setLocation((double)getX(), (double)getY());
        getMovement().revertHorizontal();
        accelerate(0.9);
    }
    else if (getY() == 0
        || getY() == getWorld().getHeight() - 1)
    {
        setLocation((double)getX(), (double)getY());
        getMovement().revertVertical();
        accelerate(0.9);
    }
}

Another Change

  • To make the scenario more exciting, it has more bodies and the bodies start at a higher speed
  • With these changes, the bodies can start zipping around the screen
  • To ensure the bodies do not move too fast, they monitor their speed
  • If the speed is too fast, then the body decelerates
    if (getSpeed() > 7)
    {
        accelerate (0.9);
    }
    
  • Note that accelerating with a factor < 1 is actually decelerating

Check Yourself

  1. The code in bounceAtEdge() that provides the actual bounce effect is ________.
    1. setLocation((double)getX(), (double)getY());
    2. getMovement().revertHorizontal();
    3. accelerate(0.9);
    4. None of these
  2. True or false: an positive acceleration of < 1 is deceleration.
  3. One problem with the bounceAtEdge() method is that the body gets halfway off the screen before the bounce. What is a way to fix this issue?

7.3.4: Arranging Obstacles in Space

  • The Space class has two new methods:
    • createObstacles()
    • randomBodies()
  • The createObstacles() method creates the obstacles and assigns their sound files
  • The code in the method is like the initialization in the piano scenario
  • If we wanted to change the arrangement of obstacles, we would change this method

Random Bodies

  • The randomBodies() method creates a number of random Body objects
  • Looking at the code, we see the method assigns random values for:
    • size and mass
    • direction
    • speed
    • location
    • color
  • A loop makes sure the method constructs the specified number of bodies
    while (number > 0)
    {
        // construct a random body
        number--;
    }
    
  • As you can see, this is a counting loop
  • What is different about this counting loop?
  • What other type of loop statement have we seen for counting? (5.3.3: Using Loops to Count)

Check Yourself

  1. What other arrangement of obstacles would look good in the scenario?
  2. Rewrite the loop code using a for-loop rather than a while-loop.

Exercise 7.3

In this exercise, we experiment with obstacles, gravity and music.

Specifications

  1. Download the Newtons Lab 3 scenario file and save it in the scenario folder of Greenfoot.

    Scenario file: Newtons-Lab-3.zip.

  2. Start Greenfoot and open the scenario.

    Greenfoot unzips the file for us.

  3. Change the arrangement of obstacles so they are no longer in a straight horizontal line. For example, change the y-coordinate to a random value like:
    int y = Greenfoot.getRandomNumber(getHeight());
  4. In the Space class, add the following member variable:
    private int count;
  5. Also in the Space class, add an act() method with the following code to periodically create new bodies:
    public void act()
    {
        count++;
        if (count > 50)
        {
            count = 0;
            randomBodies(1);
        }
    }
    
  6. Compile and run your scenario to verify all the changes work well. Then let your simulation run for a minute and see how it evolves.

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

  7. We discussed image transparency in lesson 6.2.2. Add the following code to the act() method of Body which makes planets fade by making them more transparent:
    GreenfootImage img = getImage();
    img.setTransparency(img.getTransparency() - 1);
    if (img.getTransparency() < 1) {
        getWorld().removeObject(this);
    }
    
  8. Compile and run your scenario to verify the planets fade away over time.

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

  9. Save a copy of your completed lesson scenario to upload to Blackboard as part of assignment 6.

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

7.3.5: Review

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

  1. True or false: once a simulation works well, you can "play" with it to see how changes affect the system. (7.3.1)
  2. When one object intersects another it is known as a _________________. (7.3.2)
  3. The Greenfoot method that returns an actor when objects intersect is ______________________. (7.3.2)
  4. When no objects intersect the method in the previous question returns ________. (7.3.2)
  5. Which line of the code in bounceAtEdge() provides the actual bounce effect? (7.3.3)
    1. setLocation((double)getX(), (double)getY());
    2. getMovement().revertHorizontal();
    3. accelerate(0.9);
    4. None of these
  6. True of false: an positive acceleration of < 1 is deceleration. (7.3.3)
  7. Does the following loop count up or down? (7.3.4)
    int number = 5;
    while (number > 0)
    {
        System.out.println(number);
        number--;
    }
    
  8. What value does the above loop first print? (7.3.4)
  9. What value does the above loop last print? (7.3.4)

Wrap Up

Due Next:
A5: Visualize this! (3/21/12)
A6: Visualizer Redux (3/28/12)
  • When class is over, please shut down your computer
  • You may complete unfinished lesson exercises at any time before the due date.
Home | Blackboard | Schedule | Syllabus | Room Policies
Help | FAQ's | HowTo's | Links
Last Updated: April 21 2012 @23:23:51