Unit 6:   Key Events

imageUnit 6Key Events
Unit Overview

Students return to the subject of partial functions, this time defining a key-event handler that modifies their world when certain keys are pressed.

Product Outcomes:
    Standards and Evidence Statements:

    Standards with prefix BS are specific to Bootstrap; others are from the Common Core. Mouse over each standard to see its corresponding evidence statements. Our Standards Document shows which units cover each standard.

      Length: 90 minutes
      Glossary:
      • clause: a question and its corresponding answer in a conditional expression

      • conditional: a code expression made of questions and answers

      • piecewise function: a function that computes different expressions based on its input

      • variable: something that changes

      Materials:
      • Pens/pencils for the students, fresh whiteboard markers for teachers

      • Class poster (List of rules, design recipe, course calendar)

      • Editing environment (WeScheme or DrRacket with the bootstrap-teachpack installed)

      • Student workbooks

      • Language Table

      • Signs for kids, entitled "update-world", "draw-world" and "big-bang"

      • Cutout images of the dog and ruby

      Preparation:
      • Seating arrangements: ideally clusters of desks/tables

      • The Ninja World 3 file [NW3.rkt from source-files.zip | WeScheme projected onto the board

      Types

      Functions

      Number

      + - * / sq sqrt expt

      String

      string-append string-length

      Image

      rectangle circle triangle ellipse star text scale rotate put-image


      Introduction

      Overview

      Learning Objectives

        Evidence Statements

          Product Outcomes

            Materials

            • Pens/pencils for the students, fresh whiteboard markers for teachers

            • Class poster (List of rules, design recipe, course calendar)

            • Editing environment (WeScheme or DrRacket with the bootstrap-teachpack installed)

            • Student workbooks

            • Language Table

            • Signs for kids, entitled "update-world", "draw-world" and "big-bang"

            • Cutout images of the dog and ruby

            Preparation

            • Seating arrangements: ideally clusters of desks/tables

            • The Ninja World 3 file [NW3.rkt from source-files.zip | WeScheme projected onto the board

            Introduction (Time 15 minutes)

            • So far, we’ve been working with three main functions to make our game and animate our world: update-world, draw-world, and big-bang. At this point, your game might use a few more functions than these, but Ninja World is still as basic as you remember it.
              • Open the Ninja World 3 file and press "Run", to watch the dog and the ruby fly across the screen.

              • What is the contract for each of the functions in this game? What do they do?

              • Each time update-world is called, What changes about the dog? How does it change? What about the ruby?

              • Where on the screen does draw-world put the image of the dog? the ruby? The clouds?

              • If you were to call update-world on (make-world 0 640), What would you get back? What is the world that is produced? Where are the dog and ruby after that world is evaluated?

              In this version of Ninja World, both the dog and the ruby are moving as they should. But that’s old news: you’ve already made the characters in your game move on their own. Let’s add more.

              This lesson is another opportunity to have students"act out the three main functions in Ninja World. Draw a box on the board with (make-world 0 640) in it, labelled "world". Ask for a volunteer, and given them the update-world nametag to wear. Ask for update-world’s Contract and Purpose Statement. Go through a few iterations of having update-world evaluate the world on the board, and each subsequent world that they update.

              Make sure to call them by name, i.e. "(update-world (make-world 0 640))"

              (In the first example, the student should erase the 0 and write a 10, and erase the 640 and write a 635. If they are stuck, refer them back to the code.) Take another student, and give them the big-bang sign. They’ll start the whole animation, and will have a timer. Instruct the class to yell "tick!" every five seconds, and when they do, big-bang will give the current world to update-world, who will then update it and replace it with the new world. Let this go on for a few iterations, so the rest of the class can see the world structure being changed while they count down. Finally, give the draw-world sign to another volunteer, along with the cutouts of the dog and ruby. As before, ask for their name, domain, range. When they are called, they will be given a world structure and will place the image of the dog and the ruby at the appropriate spots on the board. Change the value of the world back to (make-world 0 640). Call on draw-world a few times with different worlds, so the class can see the dog and ruby moving accross the screen. When each volunteer has practiced, put all the functions together: On each "tick" the class makes, big-bang will call on update-world to update the current world, and then draw-world to draw that updated world. Again, go through a few iterations, so the class can see the world structure changing and characters moving in as a result.

            • The time is nigh: we need to get that ninja cat onto the screen so that our game is playable. She’ll be able to move up and down.
              • Do we need to change anything in the code to make this work?

              • What part of the game will we need to keep track of if Ninja Cat is moving up and down? What would be a good variable name for this?

              We need to keep track of the cat’s y-coordinate, so let’s add a catY to the world.
              • Where in the code is the world struct defined?

              • If the cat is in the center of the screen, what should the value of catY be?

              • Add another number to the world struct, representing the cat’s y-coordinate.

            • Right now, even though the cat’s y-coordinate has been added to the world struct, there’s no function to take in keypresses and make it move. This is what we’re going to write next. But before we figure out how to write the function to move the cat, we need to actually add her into the game.

              Which functions will need to change, now that the world structure is different?

              Since the world now contains three things, you’ll need to change every single make-world in the code.
              • Starting from the first line, go through the code and look for every instance of make-world, changing it to reflect the new world struct.

              • How do you get the catY out of the world?

              • We said that we’ll be writing another function to handle keypresses and moving the cat, so just add the catY to update-world. Don’t worry about changing its value.

              • Inside draw-world, use the put-image function to place the image of Ninja Cat on top of the other images in the game. If she starts in the center of the screen, on what x-coordinate will she be placed? What about her y-coordinate?

              After the catY is added to the world struct, but before any of the functions have changed, try running the simulation again, giving the ninja cat cutout to the draw-world volunteer. The world now has three things in it (dogX, rubyX, and catY), but the updating and drawing functions will change only the dog and ruby’s positions. When big-bang starts the animation, only the dogX and rubyX will be updated. After a few iterations, tell the volunteers that you’ve pressed the "up" key. If draw-world begins moving the ninja cat cutout, refer them back to the code. You haven’t programmed anything to change catY yet.

            Keypress

            Overview

            Learning Objectives

            • Students will extend their understanding of events to cover key-events

            • Students will deepen their knowledge of conditionals, by combining them with struct accessor and constructor functions.

            Evidence Statements

              Product Outcomes

                Materials

                  Preparation

                  Keypress (Time 35 minutes)

                  • Now that the world structure is consistant across all the functions in Ninja World, we’re ready to make the cat move.

                    Open your workbook to Page 28. Using the Design Recipe, write the function keypress for the Ninja World game.

                    The word problem tells us that the function’s name will be keypress. What about the Domain? Think about what the function needs to know in order to handle a keypress: it needs the World, otherwise it wouldn’t know what to update. But it also needs to know what key was pressed (either "up" or "down").
                    • What datatypes are "up" and "down"?

                    • What is the Domain of keypress? The Range?

                    • What is a good Purpose Statement for this function?

                     

                  • Write an example using the START world, when the user presses "up".

                    • (EXAMPLE (keypress START "up") ...)

                    • What should you get back? (HINT: Look at the Range)

                    • What function makes a world? What things are part of this world?

                    •  

                    • Does the dogX change when the user presses "up"? How do you get the old dogX out of the START world?

                    •  

                    • Does the rubyX change when the user presses "up"? How do you get the old rubyX out of the START world?

                    •  

                    • What about the catY? How much should it change if the user presses "up"? Let’s say 10 pixels.

                    • Should you add or subtract from the catY if the "up" key is pressed? Why?

                    Your first example should look like:  

                  • Write one more example for keypress using the START world and the "down" key. Think about how the catY will change this time

                     

                    Next, carefully go through your examples and circle everything that changes. Does this function behave like the functions you’ve been working with?

                  • What goes into the function header? What are some good variable names for the world and string (representing the key pressed) in the Domain?

                      What now? This is a test of your programming intuition: you have two different examples, where you add 10 to catY in one case but subtract 10 in another. How can a function behave so differently? It has multiple conditions, with a different response to each. You’ve already seen this before, back in Bootstrap:1 - cond. cond is a special function, which signals to the computer that the function will have multiple conditions: it behaves differently depending on what input(s) it gets. This is also known as a piecewise function.

                    Be sure to check students’ Contracts and EXAMPLEs during this exercise, especially when it’s time for them to circle and label what changes between examples. This is the crucial step in the Design Recipe where they should discover the need for cond.

                  • Each piecewise function has at least one clause. Each clause has a Boolean question and a result. In your keypress function, there is a clause for the "up" key, and another for the "down" key. If the question evaluates to true, the expression gets evaluated and returned. If the question is false, the computer will skip to the next clause. To write a function with multiple conditions, start with cond and use square brackets to add a branch. We know that every branch has a test and a result, making a clause.  

                  • Let’s start the first branch. It will test if the key pressed is equal to "up".

                    What function can we use to test if two strings are equal?

                     

                    Square brackets enclose the question (a statement returning a boolean) and answer for each clause. There can only be one expression in each answer.

                  • What is the result if the key is "up"? (HINT: Look back at your EXAMPLES for help.) You can copy in the example for "up", and change all instances of START to the variable, w:  

                    What is the second condition that needs to be considered? What expression will test that condition? Write the second branch of the keypress function.

                  • We also need to test whether the user pressed the "down" key:   Now the computer knows what to do when either "up" or "down" is pressed, but there are lots of other keys on your keyboard.

                    Type the above code into the Ninja Cat game and click "Run". Ninja Cat moves when you press the "up" and "down" arrow keys. What happens if you press a different key? You should get an error...can you guess why?

                  • Racket doesn’t know what to do if any other key is pressed, because we haven’t told it what to do.
                    • Should the world change if the user hits the spacebar, or the "r" key?

                    • Which world should be returned if any other key is pressed?

                    Instead of enumerating all the values of the original world, we can use the variable, w:  

                    The last clause in a conditional can be an else clause, which gets evaluated if all the previous clauses were false.

                    else clauses are best used as a catch-all for cases that you can’t otherwise enumerate. If you can state a precise question for a clause, write the precise question instead of else. For example, if you have a function that does different things depending on whether some variable x is larger than 5, it is better for beginners to write the two questions (> x 5) and (<= x 5) rather than have the second question be else. Explicit questions make it easier to read and maintain programs. When you use else, someone has to read all the previous questions to know what condition else corresponds to: they can’t just skim all the questions to find the one that matches their situation. This makes code more readable and understandable.

                  Keypresses in Your Game

                  Overview

                  Learning Objectives

                  • Using conditionals, students will write a function to handle different keypresses in their game.

                  Evidence Statements

                    Product Outcomes

                      Materials

                        Preparation

                        Keypresses in Your Game (Time 35 minutes)

                        • In Ninja World, the player can only press two keys: "up" or "down".
                          • What field in the World changes when the player presses "up"? How does it change?

                          • Think about the person playing your game. How will they control the game? What key will make YOUR player move up? Down? What else can they do? Move side-to-side? Jump? Teleport? Shoot a projectile?

                          • Turn to Page 27 in your workbooks. Write down the various keys that the user can hit to control the game. For each one, write down the field in your world struct that changes, and how it changes.

                          Review students’ workbook pages, and check for understanding: could they change multiple things in their game with one keypress?

                        • Turn to Page 30 in your workbooks. Choose 3 keys that control the game, and go through the design recipe: Write EXAMPLES for what should happen to your START world depending on which key was pressed. Then define your function. Once you’ve completed the Design Recipe, type your keypress function into your games.

                          Of course, keypresses can do a lot more in a videogame than just move a character up and down. By using what your learned about Boolean functions, you can add more advanced movement. Here are some ideas:

                          • Warping: instead of having the player’s y-coordinate change by adding or subtracting, replace it with a Number to have the player suddenly appear at that location. (For example, hitting the "c" key causes your player to warp back to the center of the screen, at y=240.)

                          • Boundary-detection: Change the condition for moving up so that the player only moves up if key = "up" AND the player’s y-coordinate is less than 480. Likewise, change the condition for "down" to also check that the player’s y-coordinate is greater than 0.

                          • Wrapping: Add a condition (before any of the keys) that checks to see if the player’s y-coordinate is above the screen (> y 480). If it is, have the player warp to the bottom. Add another condition so that the player warps back up to the top of the screen if it moves below the bottom.

                          • Challenge: Have a character hide when the "h" key is pressed, only to re-appear when it is pressed again.

                          Hint for the challenge: multiply by -1!

                        Closing

                        Overview

                        Learning Objectives

                          Evidence Statements

                            Product Outcomes

                              Materials

                                Preparation

                                Closing (Time 5 minutes)

                                • With conditionals and piecewise functions, you can make a lot of things happen in your game with just a few lines of code, like controlling the movement of characters. Speaking of controlling characters, what happens in Ninja World when the dog and ruby go off the screen? They keep going, but don’t come back - the same problem we had in Bootstrap:1, and if you need a refresher on how to fix it, that’s what we’ll be covering in the next unit.

                                  Have students show each other their (controllable games).