MIT 6.030: 
Introduction to Interactive Programming

Laboratory 1: Expressions, Statements, and Interactions 
Solutions

Contents

Pre-Lab

B. Finger exercises

Laboratory

Static Positioning
  1. Write Horizontal and Vertical rules that will place the ball in position (10, 20).

  2. Horiz rule:    return 10;
    Vert. rule:    return 20;
  3. Use the Horizontal rule for both rules.  What do you expect would happen?

  4. The ball will go to (10,10).
  5. Use the Horizontal and Vertical rules separately again. Use the mouse to manually move the ball to another position (see Advanced Environment Options).  Do this several times.  What happens?  Explain. [In lab: Can you "fix" this behavior?]

  6. The ball will stay at the position where you drop it briefly, and then quickly returns to position (10,20).  To "fix" the behavior (i.e., make it stay in place), simply use the rule return pos; for both rules.
Implementing Velocity
  1. Write a pair of rules to make the ball move horizontally from left to right.  Can you control how fast the ball moves (i.e., velocity) by changing your code?
  2. (Note: this question only asks you to move the ball from left to right, and not necessarily back from right to left.)

    To make the ball move to the right with a velocity of 1, we can use the following rules:

    Vert. Rule:     return 0;
    Horiz. Rule:    return pos + 1;

    This says that the new horizontal position will be 1 more than the current horizontal position -- i.e., the ball will move to the right 1 step every time the horizontal rule is called.  (Note that the Spirograph program takes care of periodically calling the rules -- you don't have to do that yourself.)  To make the ball move faster, we simply increase the amount we add to pos.  (Remember that velocity is the rate of change of position.)

    A slightly redundant, but sometimes more readable, way of writing this rule is as follows:

    double velocity = 5;   // change this number to change the velocity
    double newPos;       // the new position will be stored in newPos

    newPos = pos + velocity; // compute next position

    return newPos;

    (Note that the name velocity here is a new local variable we create, and is not the same as vel, which is a parameter supplied to the rule.)
     

  3. Use the horizontal rule for both rules.  What do you expect would happen?  Explain.

  4. The ball moves in a 45 deg. line.  This is because it moves the same distance horizontally as it does vertically.
  5. What happens if the horizontal and vertical rules have different effective velocities? (How do you make this happen?)

  6. You can make it happen by using a different value for velocity in the horizontal and vertical rules.  The angle of the line changes, depending on which axis the ball is moving faster.
  7. Use the mouse to move the dot to a different position.  What happens?  Explain.
  8. The answer to this depends on your implementation.  With the code above, moving the ball to a different position causes the ball to continue moving with the same velocity, but starting from the position you moved it to.  This is because the new position is computed relative to the current position, so it doesn't matter what the current position is.

Implementing Acceleration
 
    Now that you can implement velocity using position controls, implement acceleration.  Note that you cannot use vel and otherVel, since these are always 0 in position-control mode.  (Hint: use fields.)  Write your code so you can change the initial velocity and acceleration by changing the code.

    Just as velocity is the rate of change in position, acceleration is the rate of change in velocity.  Thus, to implement acceleration, we can start with the code for velocity above, and then just increment velocity each time the rule is called.  That is, the rule will now be:

    double velocity = 5;          // change this number to set the velocity
    double acceleration = 1; // change this number to set acceleration

    double newPos;       // the new position will be stored in newPos

    newPos = pos + velocity; // compute next position
    velocity = velocity + acceleration;

    return newPos;

    However, if you run this code as-is, you will find that the velocity will not change.  This is because right now, a new "shoebox" with the name velocity is created everytime the rule is called, and it loses its value after the rule returns.  To make velocity keep its value across calls to the rule, we must make it a field.  Thus, the correct(ed) code for acceleration is as follows:

    In the fields box:

    // Press "Load" to initialize these fields
    double velocity = 5; // change this to set *initial* velocity
    double acceleration = 1; // change this to set acceleration

    In the rule box:

    double newPos;       // the new position will be stored in newPos

    newPos = pos + velocity; // compute next position
    velocity = velocity + acceleration; // compute next velocity

    return newPos;
     
     

    Note that we don't really need to give the acceleration a name, since it is constant.  If we knew we would only be interested in doing accelerations of value 1, then we can just say velocity = velocity + 1; instead.   However, using a name (acceleration) makes the code much more readable.  It also makes it more flexible.  If we wanted to change the acceleration (and/or the velocity) during run-time, we only need to assign a new value to the fields acceleration and velocity; we don't need to recompile our code.

    Note that unlike velocity and acceleration, newPos is still a local variable. This is because newPos is essentially used only for temporary storage -- it is assigned a completely new value every time the rule is called, and there is no need or reason for us to keep its old value around.  Thus, although making newPos into a field will not change the behavior of this code, it is more appropriate to keep it as a local variable.
     
     

    Can you make the dot go in a parabolic path? (Hint: what accelerations does it need?)

    One way to do this is to use a constant horizontal velocity, a constant vertical acceleration, and an initial vertical velocity in the opposite directions as the vertical acceleration.  (Note that this is what happens when you shoot a cannonball into the air.)

    To do this, use the acceleration code above, with the different initial values for the fields:

    Horiz. fields:     double velocity = 5;
                double acceleration = 0;

    Vert. fields:       double velocity = 15;
                double acceleration = -1;

    (Note: In Spirograph, you need to press "Load" to initialize the fields.)

Wraparound and other boundary conditions
 
  1. Modify your code to make it emulate the behavior of wrap-around mode while using no-wrap-around mode.
  2. double newPos = pos + velocity;        // compute next position
    velocity = velocity + acceleration; // compute next velocity
    if (newPos > maxPos) {    // if new position is too high
       newPos = -maxPos;      // wrap-around to low end
    } else if (newPos < -maxPos) {    // if new position is too low
       newPos = maxPos;               // wrap-around to high end
    }
    // at this point, newPos can never be > maxPos or < maxPos
    // therefore, it is now safe to return newPos;
    return newPos;

    (This solution assumes that velocity and acceleration are still fields.)
     

  3. Can you make the dot bounce when it hits the end?
  4. One way to do it is as follows:

    double newPos = pos + velocity;        // compute next position
    velocity = velocity + acceleration; // compute next velocity
    if (newPos > maxPos) {    // if new position is too high
       newPos = maxPos;      // stay at maxPos
       velocity = -velocity;  // but turn around (negate velocity)
    } else if (newPos < -maxPos) {    // if new position is too low
       newPos = -maxPos;               // stay at -maxPos
       velocity = -velocity;  // but turn around (negate velocity)
    }
    // at this point, newPos can never be > maxPos or < maxPos
    // therefore, it is now safe to return newPos;

    return newPos;

    Again, this assumes velocity and acceleration fields.  There is no way to make the ball bounce without using some field, but there are many different ways to use a field to accomplish bouncing.

Other cool stuff Using Velocity and Acceleration Controls


This course is a part of Lynn Andrea Stein's Rethinking CS101 project at the MIT AI Lab and the Department of Electrical Engineering and Computer Science at the Massachusetts Institute of Technology.