CSE 203 Closed Lab 15 Instructions

Table of Contents


1. Objectives


2. Set Up

  1. Two students should work together at one workstation.
  2. In one student's account, follow the instructions given below in section 3, Method.  Remember, trading roles (driver and non-driver) for each new session is a very good idea.

3. Method

  1. Start Phrogram, and open file Bounce_Among_Many_Circles_Incomplete.kpl from folder Week06 within folder OSU (i.e., folder OSU/Week06).
  2. I modified program Test_Bounces (also available in folder Week06), which you saw in a previous closed lab session, to create Bounce_Among_Many_Circles_Incomplete.  I removed the green diagonal line segment and the big static circle in the middle of the window.  I made other changes to help us move toward getting our moving circle to bounce off a number of circles randomly scattered about the window, this number of circles being specified by the user.  This program still uses the F1 and F2 keys in the user interface.  If you prefer, you can modify it to use mouse clicks instead.
  3. The part at the bottom of the main event loop in Method Main() that causes our moving circle to bounce off the window's borders is still there, but it has changed somewhat.  In program Test_Bounces, we used a Function, NV_Circ_Bounce_Line, to bounce a moving circle off a line segment.  The "NV" stood for "New Velocity" because a new velocity is what the function returned to the program.  In this program, that function is gone, replaced by Method CV_Circ_Bounce_Line.  The "CV" stands for "Change Velocity" because this Method changes the velocity that is given to it as its second parameter.  Hence, the call "CV_Circ_Bounce_Line( MC, MC_Velocity, TE )" changes (at least potentially, when it detects interaction) MC_Velocity.  I prefer using a Method here because we only have to write "MC_Velocity" once for each call.  When we used a Function, we had to write (and read!) MC_Velocity twice.
  4. A few more things to note about the call "CV_Circ_Bounce_Line( MC, MC_Velocity, TE )": MC is an object of type Circle, MC_Velocity is an object of type Vector, and TE is an object of type Line.  The property, Center, of object MC, MC.Center, is the center of the circle (obviously, I guess).  Anyhow, MC.Center is an object of type Point.
  5. Take a minute or so now to read the comment that describes Method CV_Circ_Bounce_Line.
  6. Let's get ready to complete this program.  Change the program name at the top of the program to "Bounce_Among_Many_Circles", and, from the File menu, choose Save As New Program to save this program with that name.
  7. Now run the program.  Notice that, at the bottom of the window, it's asking you a question.  Try answering the question with nonsense like "what?" or semi-nonsense like "three".  The program just sits there, not responding!  That's because we programmed it to be looking only for an integer, typed using digit keys only.  Maybe our question should have said so!  Anyhow, if you type "14", it will show up in the little window at the bottom of our program window.  Then, you can either click the Submit button or just tap the Enter key.
  8. Well, I don't see 14 bumpers.  That's because we still have more programming to do to make that happen.  Still, the moving "ball" has shown up (although it's not moving yet).  It's smaller now, and red, not blue.  Tap the F2 key to get it moving.  I'm hoping you'll see it bounce off an edge of the window at least once before it escapes past one of the window's edges.  If it hasn't escaped yet, wait a while, I think it will!  You can use the F1 key to bring it back.  Remember to close the running program's window.
  9. Why did it escape?  When I made the ball smaller, I made it more likely that, at this high speed, the ball would move in one iteration, in one jump, from not interacting with an edge to having its center just past the edge.  If that happens, the ball won't interact with any edges at all and will just keep moving out beyond the window somewhere.  What shall we do about this problem?  Reasonable solutions include making the ball larger and/or reducing its speed.  However, at least in the special case of the four window edges, we can make a correction to the ball's (MC's) position whenever it goes out of bounds.  The following sequence of two If statements makes this correction for the bottom and right-hand edges of the window.  Type them in after the comment that says "// bounce off window borders".  LR is the Point at the lower right-hand corner of the window.
    If LR.Y <= MC.Center.Y Then
    MC.Center.Y = LR.Y - 1
    End If

    If LR.X <= MC.Center.X Then
    MC.Center.X = LR.X - 1
    End If

  10. See if you can figure out why those two If statements keep MC from escaping past the window's bottom and right-hand edges.
  11. Now invent two more If statements to add to this sequence of statements, one to "guard" the window's top edge, the other to guard its left edge.
  12. OK, back to the issue of asking the user for information and gathering that information.  Find near line 39 of the program in Method Main() where Integer object Number_Of_Circles is defined.  There you see that we call Console.ShowConsole() to begin the process of prompting for and getting input from the user.  Calling Console.SetHeight() is optional, but doing so allows the rest of the program window to be visible above the Console portion of the window.  You can comment out this line to see how the behavior differs.  Console.ReadInt() is a Function that returns an Integer (in our case, into object Number_Of_Circles).  The Integer it returns is the one it gets from the user.  The question that the user sees is supplied as ReadInt()'s only parameter.  It is ReadInt() that doesn't allow non-digit characters to appear in the input window when the user attempts to type them.  When we're done getting user input, we Hide the Console.
  13. The next definition, with assignment statement and Function call, "Define CL As CircleList = List_Of_Scattered_Circles( Number_Of_Circles )", defines CL as an object of type CircleList and gives it a value that is a list of Number_Of_Circles circles.  The Function List_Of_Scattered_Circles() is defined at the bottom of this program.  Take a minute or so now to read the comment that describes it.
  14. What we've done so far is pretty amazing: the user has told us how many circles to have, and we have that many circles in our list, CL.  All we need to do now is display those circles and make sure that MC bounces off them.
  15. The circles in CL are numbered from 1 to Number_Of_Circles.  Circle 3 (if there is one!), has the name CL.Item( 3 ).  So, the call to draw that circle would be "CL.Item( 3 ).Draw()".  Similarly, the call to bounce MC against that circle would be "CV_Circ_Bounce_Circ( MC, MC_Velocity, CL.Item( 3 ) )".  What we want to do, at the bottom of the main event loop, before the call the RefreshScreen(), is repeat those two actions for each of the circles in the list.  We can do this by defining an Integer object, say "cn" for circle number, and having cn's value be 1, 2, 3, 4, and so on up to Number_Of_Circles, and making the two repeated actions on circle number cn.
  16. A "while" loop can help us make cn take on this sequence of values.  Type the following before the call to RefreshScreen():
    Define cn As Integer = 1 // circle number
    While cn <= Number_Of_Circles
    cn = cn + 1
    End While
  17. OK, left like that, this loop won't do anything for us but take up a little time.  But, now, you can insert, before the assignment to cn (order is especially important here), the two necessary actions, one to draw the circle and the other to bounce MC against it.
  18. Please note that you have used a "while" loop to good effect when it wasn't the main event loop of the program.  In fact, this "while" loop is inside the program's main event loop.
  19. Run the program to try it!
  20. You could also note that there is a "while" loop in the body that implements Function List_Of_Scattered_Circles().
  21. There is one important difference to note between a program that moves sprites, but doesn't draw things like circles, and this one, that draws circles (but could also move sprites).  The main difference is the call, near the beginning of the main event loop, to BeginFrame().  This call causes Phrogram to not display any changes in the program window until the next call to RefreshScreen().  Handling it this way keeps things from happening in the window one at a time and keeps the frame time lower by not slowing things down to draw one thing at a time.  For example, the very next statement, ClearBackground( Colors.White ), if BeginFrame() had not been called, would immediately cause the whole window to be white, then, later, the program would begin to draw on this white background.  This would cause us to see the static circles flicker, I think.  As it is, the call to ClearBackground() only logically makes the whole window white, and the subsequent drawings happen only logically.  Then, the whole new scene is repainted on top of the old scene by the call to RefreshScreen().
  22. If you have extra time, consider making MC large enough to contain a sprite, calculating where the upper left-hand corner of the sprite should be based on MC's center, showing the sprite, and always moving it to MC's new location.  Then, you could even comment out the call "MC.Draw()".
  23. If you think that using things that you've learned in this closed lab exercise might help you in your project, think about how you might change your course project to include one or more of these attractive things.  If you want to know more, just ask!

4. Proctor Help

If you have a question or get stuck, raise your hand and one of the proctors will come by to chat.