CS 2135: Lab 4


Lab Motivation and Goals

This lab is designed to give you more experience writing interpreters by having you write one for a simple graphics animation language.


Languages such as Macromedia Flash provide programmers with constructs for expressing animations. The constructs in an animation language describe operations one might one to do on a graphic, such as move, slide, scale, or rotate it. In order to implement such a language, you need to provide an interpreter which consumes animation commands and a graphic, and moves the graphic around on the screen according to the commands.

The Data Definitions

In an animation language, a graphic consists of two pieces of information: a shape (the picture itself) and a vector that indicates the current direction that the shape is moving. We will use circles and rects for shapes. A vector is just a pair of numbers. This gives rise to the following data definitions to describe graphics:

;; A vector is a (make-vector x y)
;; this is built in to DrScheme, so don't include a define-struct for it!

;; A circle is a (make-circle posn number)
(define-struct circle (center radius))

;; A rect is a (make-rect posn number number)
(define-struct rect (top-left width height))

;; A shape is either
;;  - a circle, or
;;  - a rect

;; A graphic is a (make-graphic shape vector)
(define-struct graphic (shape vector))

An animation applies a sequence of commands to a graphic; animations are the programs in this language. For starters, we will implement a language with commands for moving, scaling, and redirecting (the paths/vectors of) graphics. We capture these commands with the following data definitions:

;; A command (cmd) is one of
;; - (make-move number) [where number says how many times to move the shape]
;; - (make-scale number) [where number is the scaling factor]
;; - (make-redirect number number) [where the numbers are multipliers for a graphic's vector]
(define-struct move (numtimes))
(define-struct scale (factor))
(define-struct redirect (delta-x delta-y))

Exercises:

  1. Write a program interp-cmd that takes a graphic and a command and returns a graphic. The program should clear the old graphic from the screen, execute the command on the graphic, draw the new graphic on the screen. and return the new graphic [note: you'll need begin to write down such a sequence of commands].

    Here are examples of the expected outputs from interp-cmd (minus drawing the new graphics on the screen -- you also need to draw the graphics):

       (interp-cmd (make-graphic (make-circle (make-posn 30 40) 10)
    	                     (make-vector -5 5))
    	       (make-move 1))
    
    -> (make-graphic (make-circle (make-posn 25 45) 10)
                     (make-vector -5 5))
    
    ------------------------------------------
    
       (interp-cmd (make-graphic (make-circle (make-posn 30 40) 10)
    			     (make-vector -5 5))
    	       (make-scale 3))
    
    -> (make-graphic (make-circle (make-posn 30 40) 30)
    		 (make-vector -5 5))
    
    ------------------------------------------
       (interp-cmd (make-graphic (make-circle (make-posn 30 40) 10)
    			     (make-vector -5 5))
    	       (make-redirect -1 2))
    
    -> (make-graphic (make-circle (make-posn 30 40) 10)
    		 (make-vector 5 10))
    

    Use DrScheme's basic graphics library for the visual aspect of your interpreter. Things to note about that library:

    Everyone should be able to finish up to this point

  2. interp-cmd processes one command on a graphic. An animation actually consists of several commands. Given the following data definition for animations, write a program interp-animation that takes an animation and executes the commands in the animation on the graphic in the animation. Each command should execute on the graphic that resulted from the previous command.

    ;; An animation is a (make-animation graphic list[cmd])
    (define-struct animation (graphic cmds))
    
  3. Add a new command repeat-until to your graphics language. This command takes a command and a function from graphics to boolean and returns a graphic. It executes the command repeatedly until the function returns true on the current graphic. Each iteration of the loop should execute the command on the graphic returned by the previous iteration. The return value of the entire repeat-until command is the value of the last graphic. For example:

       (interp-cmd (make-graphic (make-circle (make-posn 30 40) 10)
    			     (make-vector -5 5))
    	       (make-repeat-until (make-move 1)
    				  (lambda (agraphic)
    				    (>= (vector-x (graphic-vector agraphic))
    					50))))
    
    -> (make-graphic (make-circle (make-posn 50 20) 30)
    		 (make-vector -5 5))
    

    Use the structure (make-repeat-until cmd done?) for this new command.

    Many students should be able to finish up to this point

  4. Extend repeat-until commands to take list of commands rather than just single commands.

  5. Add a command bounce to your language that moves the graphic towards the top boundary of the canvas until it hits the canvas, then sends the shape back down until its y coordinate is equal to or larger than its original position. ie:

    --------------
          o
         o o
        o   o
       o     o
       ^     ^
     start   end
    

    [Hint: define bounce in terms of repeat-until]