Lab 2: Animations
Doug has told you and your partner that a criminal’s fingerprint is somewhere in the crime scene! Your job is to use your handy-dandy magnifying glass to find the fingerprint. You have to find it as fast as possible to solve the case!
Setup
Include this at the top of your program:
include reactors
include image
data Posn:
| posn(x :: Number, y :: Number)
end
A posn
is a datatype that probably looks familiar: it is a way to represent coordinates on a grid by using x
and y
values.
Note: By defining a posn
datatype, you are telling the program, “This is something that will appear later in my program, and I want a way to build the same thing multiple times with different characteristics.” So, when you make a posn
in your program, you are building the same structure each time: a variable of type posn
! The difference between the posn
variables you make are the x, y
values entered as parameters (inputs).
To create a new posn
with an x-value of 3 and a y-value of 4:
my-posn = posn(3,4)
To access the x- and y-values of my-posn
:
>> my-posn.x
3
>> my-posn.y
4
Try this out in the interactions window! What kind of values can you use for x
and y
? What happens if you try to add a z
coordinate?
Note: If you get confused about posn
or reactor
, check out the help doc we made (listed under lab 2 on our course website).
Part 1
1.1: Building the view
The first thing you need in order to start sleuthing is a clean surface and your magnifying glass.
Write a function crime-scene
that creates a square white background, and place your magnifying glass and fingerprint somewhere on it. They should be on opposite ends of the screen.
You might notice that this function does not have any inputs (something that also came up on homework 2). When might it be useful to write a function without any inputs?
Pyret has a useful function image-url
for loading images when you don’t want to build an entire graphic from scratch (URL stands for “Universal Resource Locator”… a web address!). image-url
takes in the url of an picture from the web and outputs it as a Pyret Image. Once it’s loaded, you can manipulate it the way you would any other Image from the image
library.
We used these images:
MAGNIFYING-GLASS-URL = "https://cdn.pixabay.com/photo/2015/10/28/13/27/magnifying-glass-1010537_960_720.png"
FINGERPRINT-URL = "https://cdn.pixabay.com/photo/2013/07/12/15/36/fingerprint-150159_960_720.png"
magnifying-glass-image = image-url(MAGNIFYING-GLASS-URL)
fingerprint-image = image-url(FINGERPRINT-URL)
But you’re welcome to find (or build) your own!
Hint: You might find the function place-image
more useful than overlay-image
, as it allows you to fix one image (the fingerprint) and put another (the magnifying glass) somewhere on the background.
Note: You must use a posn
to store the positions of your magnifying glass and of your fingerprint.
1.2: Random placement
Your partner is pretty forgetful and keeps leaving the magnifying glass in random places all over the crime scene.
Use num-random(n)
to change your function so that your magnifying glass is placed at a random spot on your background.
CHECKPOINT:
Call over a TA once you reach this point.
Part 2
2.1: Adding movement
Now it’s time to actually search for the fingerprint! To do so, you will be using a Pyret reactor
, which we talked about in the presentation.
Here is a basic example for reference:
my-reactor =
reactor:
init: init-posn,
to-draw: crime-scene,
on-tick: solve-case
end
Change your code from Problem 1 so that your image is drawn as part of a reactor
. To do this, you must create two functions:
- Modify your
crime-scene
function so that it takes a posn
as input and returns an image
- Write a new function,
solve-case
, that takes a posn
as input and moves it up by 1.
To use your reactor, run your program and then type interact(my-reactor)
in the interactions window.
CHECKPOINT:
Call over a TA once you reach this point
2.2: Move your magnifying glass
If you can’t move the magnifying glass around, how will you find the fingerprint?
So far, our reactor uses solve-case
to move the magnifying glass every few milliseconds. In a game, however, we also want to move the magnifying glass as a player presses keys. Brainstorm which keys would you like to use and how the posn
of a magnifying glass change based on which key was pressed. Pick only two keys to start (you can add more later).
Write a function move-glass
that takes in a posn
and a string and returns a new posn
. The string represents a keypress, the input posn
represents the initial position of an object, and the output posn
represents the object’s new position after the keypress.
Below is a list of some string-to-key mappings:
- Enter key: “enter”
- Left arrow: “left”
- Up arrow: “up”
- Right arrow: “right”
- Down arrow: “down”
- Backspace key: “backspace”
You can also use each key’s literal character to represent that key. For example, “a” is the a key, “b” is the b key, etc.
Add the move-glass
function to your reactor like this:
my-reactor =
reactor:
init: init-posn,
to-draw: crime-scene,
on-tick: solve-case,
on-key: move-glass
end
CHECKPOINT:
Call over a TA once you reach this point
2.3: Additional features
Implement both of these additional features. If you still have time, come up with your own!
Wrap-around:
What happens if the magnifying glass misses the fingerprint and flies off the screen? (Try this out using your current reactor.)
Modify your on-tick
function so that if the magnifying glass flies off the screen, it wraps around on the other side.
Collisions:
Write a function found-it
that takes in the position of the magnifying glass and returns a Boolean indicating whether the magnifying glass has found (or collided with) the fingerprint.
Add it to your reactor like this:
my-reactor =
reactor:
init: init-posn,
to-draw: crime-scene,
on-tick: solve-case,
on-key: move-glass,
stop-when: found-it
end
Next, congratulate your partner for a successful solve by modifying to-draw
so that if there is a collision
(found-it
returns true), the image becomes a congratulatory image of your choice.
CHECKPOINT:
Call over a TA once you reach this point
Case closed!
Thanks to your excellent detective work, the criminal’s fingerprint has been found, Doug is happy, and your latest case is one step closer to being solved!
Lab 2: Animations
Doug has told you and your partner that a criminal’s fingerprint is somewhere in the crime scene! Your job is to use your handy-dandy magnifying glass to find the fingerprint. You have to find it as fast as possible to solve the case!
Setup
Include this at the top of your program:
A
posn
is a datatype that probably looks familiar: it is a way to represent coordinates on a grid by usingx
andy
values.Note: By defining a
posn
datatype, you are telling the program, “This is something that will appear later in my program, and I want a way to build the same thing multiple times with different characteristics.” So, when you make aposn
in your program, you are building the same structure each time: a variable of typeposn
! The difference between theposn
variables you make are thex, y
values entered as parameters (inputs).To create a new
posn
with an x-value of 3 and a y-value of 4:my-posn = posn(3,4)
To access the x- and y-values of
my-posn
:Try this out in the interactions window! What kind of values can you use for
x
andy
? What happens if you try to add az
coordinate?Note: If you get confused about
posn
orreactor
, check out the help doc we made (listed under lab 2 on our course website).Part 1
1.1: Building the view
The first thing you need in order to start sleuthing is a clean surface and your magnifying glass.
Write a function
crime-scene
that creates a square white background, and place your magnifying glass and fingerprint somewhere on it. They should be on opposite ends of the screen.You might notice that this function does not have any inputs (something that also came up on homework 2). When might it be useful to write a function without any inputs?
Pyret has a useful function
image-url
for loading images when you don’t want to build an entire graphic from scratch (URL stands for “Universal Resource Locator”… a web address!).image-url
takes in the url of an picture from the web and outputs it as a Pyret Image. Once it’s loaded, you can manipulate it the way you would any other Image from theimage
library.We used these images:
But you’re welcome to find (or build) your own!
Hint: You might find the function
place-image
more useful thanoverlay-image
, as it allows you to fix one image (the fingerprint) and put another (the magnifying glass) somewhere on the background.Note: You must use a
posn
to store the positions of your magnifying glass and of your fingerprint.1.2: Random placement
Your partner is pretty forgetful and keeps leaving the magnifying glass in random places all over the crime scene.
Use
num-random(n)
to change your function so that your magnifying glass is placed at a random spot on your background.CHECKPOINT:
Call over a TA once you reach this point.
Part 2
2.1: Adding movement
Now it’s time to actually search for the fingerprint! To do so, you will be using a Pyret
reactor
, which we talked about in the presentation.Here is a basic example for reference:
Change your code from Problem 1 so that your image is drawn as part of a
reactor
. To do this, you must create two functions:crime-scene
function so that it takes aposn
as input and returns an imagesolve-case
, that takes aposn
as input and moves it up by 1.To use your reactor, run your program and then type
interact(my-reactor)
in the interactions window.CHECKPOINT:
Call over a TA once you reach this point
2.2: Move your magnifying glass
If you can’t move the magnifying glass around, how will you find the fingerprint?
So far, our reactor uses
solve-case
to move the magnifying glass every few milliseconds. In a game, however, we also want to move the magnifying glass as a player presses keys. Brainstorm which keys would you like to use and how theposn
of a magnifying glass change based on which key was pressed. Pick only two keys to start (you can add more later).Write a function
move-glass
that takes in aposn
and a string and returns a newposn
. The string represents a keypress, the inputposn
represents the initial position of an object, and the outputposn
represents the object’s new position after the keypress.Below is a list of some string-to-key mappings:
You can also use each key’s literal character to represent that key. For example, “a” is the a key, “b” is the b key, etc.
Add the
move-glass
function to your reactor like this:CHECKPOINT:
Call over a TA once you reach this point
2.3: Additional features
Implement both of these additional features. If you still have time, come up with your own!
Wrap-around:
What happens if the magnifying glass misses the fingerprint and flies off the screen? (Try this out using your current reactor.)
Modify your
on-tick
function so that if the magnifying glass flies off the screen, it wraps around on the other side.Collisions:
Write a function
found-it
that takes in the position of the magnifying glass and returns a Boolean indicating whether the magnifying glass has found (or collided with) the fingerprint.Add it to your reactor like this:
Next, congratulate your partner for a successful solve by modifying
to-draw
so that if there is acollision
(found-it
returns true), the image becomes a congratulatory image of your choice.CHECKPOINT:
Call over a TA once you reach this point
Case closed!
Thanks to your excellent detective work, the criminal’s fingerprint has been found, Doug is happy, and your latest case is one step closer to being solved!