Students codewalk through a piecewise function they used in Bootstrap:1, identifying the differences in Pyret syntax.
Students will use ask in their next-world function
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
boolean: a type of data with two values: true and false
piecewise function: a function that computes different expressions based on its input
Pens/pencils for the students, fresh whiteboard markers for teachers
Class poster (List of rules, design recipe, course calendar)
What should cost("cheese") evaluate to? cost("chicken")?
What do you think would happen if someone asked for a pizza not on the menu, like "sausage"?
This function is the same as the cost function you worked with in Bootstrap:1, except this one is written in Pyret! cost will still take in a String, representing a pizza topping, in its domain, and give back a number for its range, representing the price of that pizza. In Pyret, instead of using cond branches, we use a keyword called ask, which lets the computer know we’re going to have different situations and behavior in our code. Just like you learned in Bootstrap:1, this is known as a Piecewise function. Each ask statement starts with the ’|’ key, (known as ’pipe’) followed by a test, or an expression that produces a Boolean (either true or false). The other keyword to know here is then:. This tells the computer that whatever follows is what will be returned if the preceding expression is true. In the case of this function, if the string representing the topping (topping) is equal to the string "pepperoni" (string-equal(topping, "pepperoni")), then the function will return 10.50.
Have students practice adding their own pizza toppings to the menu, and asking the cost function for the price of those toppings.
string-equal is exactly the same as string=? in Racket. It takes two Strings in its domain and returns a Boolean, telling you whether or not the given strings are equal. Have students copy the contract for this function
into their contracts page.
In Racket we had an else clause, that would return true when all other tests had failed. In Pyret, we have the otherwise: keyword, which behaves the same way. If we didn’t have this line of code our program would crash if someone tried to order a pizza that was not on the menu, like "anchovies", or "mushroom". This way, if you order off the menu, the function returns 0. A free pizza!
otherwise 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 otherwise. 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 otherwise.
Explicit questions make it easier to read and maintain programs. When you use otherwise, 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.
One final syntax note: notice that there are two end statements at the bottom of this function. One to close the ask: branches and one to close the function itself. Whenever you write a piecewise function in Pyret, you will need to remember to add two end statements in order to finish the function.
Keypress in Ninja World
Students will extend their understanding of events to cover key-events
Students will deepen their knowledge of conditionals, by combining them with dot-accessor and constructor functions.
In the last unit, your Ninja Cat game was starting to take shape: You extended the world to include the dog’s x-coordinate, the coin’s x-coordinate, and the cat’s x and y-coordinates. You also learned about event-handlers, and used the draw-world and update-world functions to create a simple animation.
Open the Ninja World file. It should look similar to the simple game you had last time.
Scroll down to where it says # KEY EVENTS in the code.
What is the name of the function defined here? What is its Domain? Its Range?
How does keypress change the world it takes in? What happens on screen as a result of pressing certain keys?
Right now this function only checks whether the key pressed by the player is the ’up’ arrow key. But how can we get it to check if the ’down’ arrow key was pressed, and move the cat accordingly? Take a few minutes with your partner to write one more line of code inside the keypress function to make the player move down.
Remind students that this is similar to the update-player function they wrote in Bootstrap:1, give them a few minutes to work on it, and move on to debrief.
After adding a line to make Ninja Cat move down, your keypress function should look something like this:
At the end of the file, there’s one more bit of code that makes the game respond to key presses. Inside of big-bang,
the very last line reads on-key(keypress). on-key is a special function that detects when the user has pressed any key, and its argument tells it which function will handle the user input (in this case, keypress). Now big-bang has all the information it needs to manage the state of this game: on-tick, which tells the computer which function updates the game on every "tick" of a timer, to-draw, which tells it what function to use to draw the world, and finally, on-key, which handles user input.
(Time 15 minutes)
We’ve made Ninja Cat move up and down, but in the original version of the game she moved left and right as well. Now that you’re familiar with data structures, this is easy!
What changes about the cat if she moves to the left? To the right? What part of the world is that?
How would you change the keypress function so it also asks whether the player has pressed the "left" or "right" arrow keys?
What would you change about the world if the player presses the left arrow key? The right?
Change the keypress function so that the cat moves left and right based on the arrow keys.
When finished, your code should look like:
For reference and to check your work, you can see the completed Design Recipe for keypress in Ninja World on Page 18.
Asking the World
Students will turn update-world into a piecewise function in order to add jumping, falling, and gravity to their Ninja World game.
Students will use ask in their next-world function
Asking the World
(Time 30 minutes)
Now Ninja Cat can move up and down, but we can add some more interesting elements to this game as well- what about gravity?
If we want to make it seem like gravity is acting on Ninja Cat, she’ll need to appear to "fall" at any point when she is not on the ground.
What part of the world structure will change if the cat is moving down?
Since this "falling" will happen automatically, not as a result of user input, which function should control the gravity? draw-world, next-world, or keypress?
Right now, next-world takes in a world, and returns the next world by changing the dog’s x-coordinate and the coin’s x-coordinate. We want the cat’s y-coordinate to change as well, every time next-world runs. But we don’t want the cat to fall all the way below the screen and keep falling. Gravity should cause her to fall, but only when she is above the ground (if her y-coordinate is above 75 pixels). Sometimes we want our function to move the dog, coin and the cat, but if Ninja Cat is already on the ground only the dog and coin should move. We need next-world to become a piecewise function!
Write the Contract and Purpose statement for this updated version of next-world.
Now it’s time to think about examples.
Write one example using a World where Ninja Cat is above the ground, and one where she is on the ground. What should change about the world in each example? Does the dog’s x-coordinate change in both instances, or just one? Why?
Remind students that at this point, next-world will always change the x-coordinates of the dog and coin, because they move independantly. The only time the cat’s y-coordinate should change without user input is when it gets above 75 pixels.
Your exampes should look similar to:
Circle and label what changes. Did more things change than you entered in the Domain? Sometimes we subtract 5 from the cat’s y-coordinate, but sometimes her position stays the same.
What question should we ask to tell us if the cat is above 75 pixels? What dot-accessor will we need to use?
Our first condition must ask if the cat’s x-coordinate is greater than 75. What changes about the world if this is true?
Complete the design recipe for next-world and put the code into the Ninja World file.
The complete code for next-world should look like:
Ninja Cat is falling slowly in response to gravity, but it’s now pretty tough for her to move up quickly. She needs some way to jump!
Think about how you could implement jumping in this game.
How would the player make a character jump?
What part of the world needs to change if Ninja Cat jumps up?
How many pixels should Ninja Cat move up if she’s jumping?
What function controls the world in responce to key presses?
Scroll back down to the keypress function. Add one more condition that makes Ninja Cat’s y-coordinate increase if the player presses a key of your choice. Hint: The spacebar can be written as an empty string, like so: " "
(Time 5 minutes)
With piecewise functions, you can make a lot of things happen in a 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 coin go off the screen? They keep going, but don’t come back - the same problem we had in Bootstrap:1! If you need a refresher on how to fix it, that’s what we’ll be covering in the next unit.