CS 5010: Problem Set 03

Out: Monday, 30 January 2017
Due: Monday, 6 February 2017 at 6pm

This is an individual assignment. You are not allowed to discuss this problem set with any other person. You are also not allowed to search for or to view any solutions to similar problems that may be available on the World-Wide Web or in other resources that might otherwise have been available to you.

The main purpose of this problem set is to introduce you to functional reactive programming in DrRacket's Universe model, and to get you started with the Iterative Design Recipe.

You will also gain experience with the Core Bounce and Jerkless Dragging idioms we'll be using in several subsequent exercises.

You must use the HtDP Intermediate Student Language for this problem set.

For these problems, download a copy of extras.rkt and put it in the folder with your solutions. Then import this library by including the line

      (require "extras.rkt")
    

at the top of your file with the other require declarations. Then, for each problem, put in lines that say

      (provide function)
    

for each deliverable function, as you have done on previous problem sets. This will allow our testing framework to import your file and do automated testing on it. You can use check-location to double-check that your solutions are in the right place.

Remember that you must follow the design recipe, which is a process, not a list of deliverables. Your deliverables include the artifacts produced by the various steps of the design recipe: data definitions (including interpretation and templates, contracts, purpose statements, definitions, and tests). Be sure to follow our coding conventions. Doing so will make codewalks easier for everyone.

Be sure to fill out a work session report at the end of each work session. Tell git to add it to the files you will commit, and then commit and push (sync) that report in addition to committing and pushing your entire set03 directory. Do this at the end of every work session.

Remember to include a copy of extras.rkt racket in your set03 directory along with your q1.rkt and q2.rkt files.

Note: For all universe programs, you may assume the mouse is never dragged or moved outside the canvas. Once the mouse enters the canvas, if the mouse ever leaves the canvas, then the behavior of your system is unspecified.


  1. Your job is to build a simple animation, specified as follows:
    • The animation is a universe program that displays two doodads moving around in a rectangular enclosure.
    • The enclosure is 601 pixels wide and 449 pixels high. We are using graphics coordinates in which the top leftmost pixel has coordinates (0,0).
    • One doodad is displayed as a radial-star with 8 points, an inner radius of 10 pixels, and an outer radius of 50 pixels. The other doodad is displayed as a square whose sides are 71 pixels long.
    • Both doodads change color whenever they execute a Core Bounce (described below). The star-like doodad starts out Gold, but changes to Green on its first Core Bounce, then to Blue on its second Core Bounce, and then turns back to Gold on its third Core Bounce, cycling through those three colors endlessly. The square doodad cycles through five colors: Gray, OliveDrab, Khaki, Orange, Crimson.
    • Both doodads have a velocity with two components, vx and vy, which tell how many pixels the doodad moves on each tick in the x and y directions, respectively. (We are using graphics coordinates, so a positive value for vy means the doodad is moving downward.)
    • The star-like doodad starts out with its center at position (125,120) and velocity components vx=10 and vy=12. The square doodad starts out with its center at position (460,350) and (negative) velocity components vx=−13 and vy=−9.
    • The animation is active (not paused) at first, but can be frozen (paused) by pressing the space bar. Pressing the space bar a second time un-freezes the animation. The animation can be frozen and un-frozen as many times as desired, with the space bar acting as a toggle between the frozen and unfrozen states.
    • If the animation is frozen (using the space bar), then both doodads remain at their current positions.
    • If the animation is not frozen, then their new positions and velocities following a tick are calculated by adding the vx velocity component to the x position to obtain a tentative new x position, and by adding the vy velocity component to the y position to obtain a tentative new y position. If the tentative x position is greater than or equal to 0 and strictly less than 601, then it becomes the new x position and the vx component of the doodad's velocity does not change. If the tentative y position is greater than or equal to 0 and strictly less than 449, then it becomes the new y position and the vy component of the doodad's velocity does not change.
    • If either of the tentative x and y positions lies outside the range specified above, the doodad performs a core bounce. If a tentative x or y position is negative, its absolute value becomes the new x or y position and the doodad's corresponding velocity component (vx or vy) is negated. If a tentative x position tx is greater than or equal to 601 then the doodad's new x position becomes 600 - (tx - 600) and its vx velocity component is negated. If a tentative y position ty is greater than or equal to 449 then the doodad's new y position becomes 448 - (ty - 448) and its vy velocity component is negated.
    • Note that a core bounce can negate one or both of the velocity components. Even if both velocity components are negated following a tick, it counts as just one core bounce, so there is only one change of color.

    You are to deliver a file named q1.rkt that defines appropriate data types Doodad and World and provides all twelve of the following functions:

              ;;; animation : PosReal -> World
              ;;; GIVEN: the speed of the animation, in seconds per tick
              ;;;     (so larger numbers run slower)
              ;;; EFFECT: runs the animation, starting with the initial world as
              ;;;     specified in the problem set
              ;;; RETURNS: the final state of the world
              ;;; EXAMPLES:
              ;;;     (animation 1) runs the animation at normal speed
              ;;;     (animation 1/4) runs at a faster than normal speed
              
              ;;; initial-world : Any -> World
              ;;; GIVEN: any value (ignored)
              ;;; RETURNS: the initial world specified for the animation
              ;;; EXAMPLE: (initial-world -174)
              
              ;;; world-after-tick : World -> World
              ;;; GIVEN: any World that's possible for the animation
              ;;; RETURNS: the World that should follow the given World
              ;;;     after a tick
              
              ;;; world-after-key-event : World KeyEvent -> World
              ;;; GIVEN: a World and a KeyEvent
              ;;; RETURNS: the World that should follow the given World
              ;;;     after the given KeyEvent
              
              ;;; world-paused? : World -> Boolean
              ;;; GIVEN: a World
              ;;; RETURNS: true iff the World is paused
              
              ;;; world-doodad-star : World -> Doodad
              ;;; GIVEN: a World
              ;;; RETURNS: the star-like Doodad of the World
              
              ;;; world-doodad-square : World -> Doodad
              ;;; GIVEN: a World
              ;;; RETURNS: the square Doodad of the World
              
              ;;; doodad-x : Doodad -> Integer
              ;;; doodad-y : Doodad -> Integer
              ;;; GIVEN: a Doodad
              ;;; RETURNS: the x or y coordinate of the Doodad
              
              ;;; doodad-vx : Doodad -> Integer
              ;;; doodad-vy : Doodad -> Integer
              ;;; GIVEN: a Doodad
              ;;; RETURNS: the vx or vy velocity component of the Doodad
              
              ;;; doodad-color : Doodad -> Color
              ;;; GIVEN: a Doodad
              ;;; RETURNS: the color of the Doodad, in one of the forms recognized
              ;;;     as a color by DrRacket's image-color? predicate
            

    We will be doing automated testing of your solution, so be sure your solution is in the right place (set03/q1.rkt in your private cs5010sp17/pdp-YOURUSERNAME repository), and that it provides all the functions listed above. To see if your file is in the right place, insert the following line somewhere near the top of your file:

              (check-location "03" "q1.rkt")
            
  2. For this second problem, your job is to add jerkless dragging and a couple of other new features:
    • Both doodads are selectable and draggable. Depressing the mouse button when the mouse is positioned within a doodad's outline selects and grabs the doodad. The location within the doodad where it has been grabbed is indicated by a solid black circle of radius 3 pixels. Simply pressing the mouse button, without moving the mouse, should not move the doodad.
    • Once a doodad has been selected, you should be able to drag it around the enclosure using your mouse. As you drag it, the position of the mouse within the doodad (as indicated by the solid black circle) should not change relative to the doodad's center.
    • Note that selecting and dragging should work even if the animation is paused. Note also that, when the doodads overlap, it is possible to select both doodads at once and to drag both around the enclosure at the same time.
    • When the mouse button is released, all selected doodads become unselected, and the black circle showing where a selected doodad has been grabbed disappears.
    • Pressing the "c" key has no effect unless one or both doodads are selected. If any doodads are selected, however, pressing the "c" key causes all selected doodads to change to their next color just as though they had executed a core bounce, even though the velocity components of the doodads remain unchanged.

    You are to deliver a file named q2.rkt that defines appropriate data types Doodad and World, defines and provides all twelve of the functions specified for the first question of this problem set, and also defines and provides the following three functions:

              ;; world-after-mouse-event
              ;;     : World Int Int MouseEvent -> World
              ;; GIVEN: A world, the x- and y-coordinates of a mouse event, and the
              ;;     mouse event
              ;; RETURNS: the world that should follow the given world after the
              ;;     given mouse event
              
              ;; doodad-after-mouse-event :  Doodad Int Int MouseEvent -> Doodad
              ;; GIVEN: A doodad, the x- and y-coordinates of a mouse event, and
              ;;     the mouse event
              ;; RETURNS: the doodad as it should be after the given mouse event
              
              ;; doodad-selected? : Doodad -> Boolean
              ;; RETURNS: true iff the given doodad is selected
            

    Remember that we will be doing automated testing of your solution, so be sure your solution is in the right place (set03/q2.rkt in your private cs5010sp16/pdp-YOURUSERNAME repository), and that it provides all the functions listed above. To see if your file is in the right place, insert the following line somewhere near the top of your file:

              (check-location "03" "q2.rkt")
            

For debugging: Click here to validate.