# HtDP Exercise: A flight landing 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 pair of numbers giving the changes in the horizontal and vertical dimensions per unit of time.

DrScheme 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 (pair of numbers). Create your own data-definition for the pair of numbers.

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 file using the "insert image" option under the "special" menu.

(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. DrScheme includes a teachpack for creating interactive animations. Load the `world.ss` teachpack (under the Languages menu, then press Run). 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 defined in the world.ss teachpack 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 WIDTH HEIGHT (/ 1.0 28) plane1)  ;; plane1 is the name used in problem 2
(on-tick-event move-plane)
(on-redraw draw-plane)
```
When you press Run, DrScheme 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 DrScheme to call `move-plane` every (/ 1 28) seconds, using draw-plane to display the result. After each call to `move-plane`, DrScheme stores the resulting plane and uses it as the input to `move-plane` at the next time.

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

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 symbol (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 vertical vector by .5. If the input symbol is `'up`, decrease the vertical vector by .5. On any other symbol, just produce the original plane unchanged (DrScheme may pass in other symbols, so you do need the else case here).

`(on-key-event 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).

Edit your `move-plane` function to first check whether the plane is at the ground. If it is, call the teachpack function `end-of-time` which takes one string as an argument. Calling this function stops the animation and prints the given string in the interactions window. If the plane is not on the ground, `move-plane` should behave as it did before.

2. 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.

3. Edit your `draw-plane` function to put a large text message in the animation window when the plane touches the ground. 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))```

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 world.ss (just look up world.ss in the helpdesk).