CS 1101: Lab 2 - Using structs to build a flight simulator

Lab Motivation and Goals

This lab is designed to help you practice:

Programming Exercises: A Simple Flight Simulator

A flight simulator tracks the location and travel direction of an airplane. Assuming a 2-dimensional simulation, the location is just an x-y coordinate, and the travel direction is a vector giving the changes in the horizontal and vertical dimensions per unit of time.

DrRacket provides a built-in define-struct for coordinates:

                  (define-struct posn (x y))

Do not type this into your definitions window -- it is built in!

  1. Develop a data definition for planes that contains an image of the plane, a location (posn) and a direction (vector). Create your own data-definition for the vector.

  2. Create an example of a plane; use define to name it plane1. For the image, download the following gif and insert it into your DrRacket program using the "insert image" option under the "Insert" menu.

    plane image (image from www.free-clipart-pictures.net/airplane_clipart.html)

  3. Develop a function move-plane that consumes a plane and produces a plane. The produced plane has the same image and direction as the given plane, but the location coordinates are changed by the respective amounts indicated in the direction vector.

  4. Tell DrRacket that you want to use the functions in the universe and image libraries:

    (require 2htdp/universe)
    (require 2htdp/image)
    
    Put the following two definitions at the top of your file:
    (define WIDTH 500)
    (define HEIGHT 200)
    

    Develop a function draw-plane that consumes a plane and produces a scene showing the plane image at its coordinates. To produce a scene, use the place-image function as follows, replacing [plane-image], [at-x] and [at-y] with expressions that get these values from your plane structure:

      (place-image [plane image] [at-x] [at-y] (empty-scene WIDTH HEIGHT))
    The top-left corner is position 0,0. Larger coordinates move down and to the right.

  5. Put the following lines of code at the bottom of your file:

    (big-bang plane1                    ;; plane1 is the name used in problem 2
              (on-tick move-plane)
              (to-draw draw-plane))
    
    When you press Run, DrRacket will pop up a window containing your plane at its original location (make sure the location is within the WIDTH and HEIGHT boundaries defined by the constants above). You should see your plane move across the window. The code lines you copied are telling DrRacket to call move-plane every (/ 1 28) seconds, using draw-plane to display the result. After each call to move-plane, DrRacket stores the resulting plane and uses it as the input to move-plane at the next clock "tick".

    You can stop the animation by closing the animation window. If you leave it open, you will eventually get an error from DrRacket when the plane's coordinates are overly large. Ignore this error if you see it.

Everybody should be able to finish up to this point

Now, we want to let the user control the plane by pressing the arrow keys to increase or decrease the angle at which the plane is coming down.

  1. Develop a function change-plane-vec that consumes a plane and a string (the order of parameters is important) and produces a plane. The produced plane has the same image and location as the given plane, but possibly a new direction vector. If the input symbol is "down", increase the horizontal vector by .5. If the input symbol is "up", decrease the horizontal vector by .5. On any other symbol, just produce the original plane unchanged (DrRacket may pass in other symbols, so you do need the else case here).

    Add the following line to the bottom of your file:

    (on-key change-plane-vec)
    Now when you press Run to start the animation, your plane should move in response to presses of the up and down arrow keys.

Our current animation lets the plane fly right through the ground. Now, we want to (a) stop the animation when the plane touches the ground and (b) report either a crash or a safe landing depending on the rate of vertical descent at the time of landing.

  1. Write a function at-ground? that consumes a plane and produces a boolean indicating whether the bottom of the plane image is at the lower edge of the animation window. The built-in operator image-height produces the height of an image in pixels (the same units as the HEIGHT constant already in your file).

    Add the following line to the bottom of your file:

    (stop-when at-ground?)
    
    The function stop-when takes the name of a boolean function as an argument. Calling stop-when stops the animation when the value of the boolean function is true.

If you are doing very well, you will finish up to this point

The rest of these are here for those going extremely fast or who want to see how to finish the animation.

  1. Develop a function steep-slope? that consumes a plane and determines whether the plane is descending more than 3 times faster in the vertical direction than in the horizontal.

  2. Add a function last-picture that will create a large text message in the animation window when the plane touches the ground. last-picture consumes a plane struct and produces an image containing the text message. The message should be different depending on whether the plane landed steeply or not (such as "CRASH!" versus "Safe landing"). You can produce a scene with text using the following:

     (place-image (text [STRING] [font-size] [color])
                  [at-x] [at-y] (empty-scene WIDTH HEIGHT))

    Change your (stop-when...) argument to big-bang so that it looks like this:
    (stop-when at-ground? last-picture)
    

Obviously, there's much more you can do with this, such as stopping the animation when the plane flies out of the window, or wrapping the plane around the left/right edges, or giving the user more controls. More information about working with key and mouse events is in the documentation for universe (just look it up in the helpdesk).


Save your file under the name lab2-plane.rkt and use turnin to turn in your file.