Lab 2: Animations
An outlaw came into your ranch at the dead of night and released Baxter, your only bull and your favorite bovine! Your job is to use your trusty lasso to find Baxter and bring him back. He’s one of your best friends, so try to find him as quickly as you can!
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 named my-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?
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 to get started is a wide view of the plains where Baxter could be and your lasso.
Write a function western-plains that creates a square white background, and place your lasso and Baxter somewhere on it. They should be on opposite ends of the screen.
You might notice that this function does not have any inputs. 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 a 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:
LASSO-URL = "https://gamepedia.cursecdn.com/arksurvivalevolved_gamepedia/e/ea/Lasso.png"
BULL-URL = "https://365psd.com/images/istock/previews/8440/84408979-cartoon-illustration-of-angry-bull-character-isolated-on-white-background.jpg"
lasso = image-url(LASSO-URL)
bull = image-url(BULL-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 (Baxter) and put another (the lasso) somewhere on the background.
Note: You must use a posn to store the positions of your lasso and Baxter.
Note: The origin of the background grid (the point at (0,0)) is at the top left corner of the image. Therefore, increasing ‘y’ values is equivalent to moving down on the image.
1.2: Random placement
The plains are vast, so you enlisted the help of your deputy. Unfortunately, your deputy is pretty forgetful and keeps leaving your lasso in random places all over the plains.
Use num-random(n) to change your function so that your lasso 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 Baxter! 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: western-plains,
on-tick: find-baxter,
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
western-plains function so that it takes a posn as input and returns an image
- Write a new function,
find-baxter, 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 lasso
If you can’t move the lasso around, how will you catch Baxter?
So far, our reactor uses find-baxter to move the lasso every few milliseconds. In a game, however, we also want to move the lasso as a player presses keys. Brainstorm which keys would you like to use and how the posn of a lasso changes based on which key was pressed. Pick only two keys to start (you can add more later).
Write a function move-lasso 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-lasso function to your reactor like this:
my-reactor =
reactor:
init: init-posn,
to-draw: western-plains,
on-tick: find-baxter,
on-key: move-lasso
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 lasso misses Baxter and flies off your hands? (Try this out using your current reactor.)
Modify your on-tick function so that if the lasso goes off the screen, it wraps around on the other side.
Collisions:
Write a function found-baxter that takes in the position of the lasso and returns a Boolean indicating whether the lasso has captured (or collided with) Baxter.
Add it to your reactor like this:
my-reactor =
reactor:
init: init-posn,
to-draw: western-plains,
on-tick: find-baxter,
on-key: move-lasso,
stop-when: found-baxter
end
Next, congratulate your deputy for a successful capture by modifying to-draw so that if there is a collision (found-baxter 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 sheriff work, Baxter is chewing the cud gleefully in the ranch again, where he belongs! Time to get back in your sheepskin bed and take a long rest.
Lab 2: Animations
An outlaw came into your ranch at the dead of night and released Baxter, your only bull and your favorite bovine! Your job is to use your trusty lasso to find Baxter and bring him back. He’s one of your best friends, so try to find him as quickly as you can!
Setup
Include this at the top of your program:
A
posnis a datatype that probably looks familiar: it is a way to represent coordinates on a grid by usingxandyvalues.Note: By defining a
posndatatype, 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 aposnin your program, you are building the same structure each time: a variable of typeposn! The difference between theposnvariables you make are thex, yvalues entered as parameters (inputs).To create a new
posnnamedmy-posnwith 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
xandy?Note: If you get confused about
posnorreactor, 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 to get started is a wide view of the plains where Baxter could be and your lasso.
Write a function
western-plainsthat creates a square white background, and place your lasso and Baxter somewhere on it. They should be on opposite ends of the screen.You might notice that this function does not have any inputs. When might it be useful to write a function without any inputs?
Pyret has a useful function
image-urlfor loading images when you don’t want to build an entire graphic from scratch (URL stands for “Universal Resource Locator”… a web address!).image-urltakes in the url of a 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 theimagelibrary.We used these images:
But you’re welcome to find (or build) your own!
Hint: You might find the function
place-imagemore useful thanoverlay-image, as it allows you to fix one image (Baxter) and put another (the lasso) somewhere on the background.Note: You must use a
posnto store the positions of your lasso and Baxter.Note: The origin of the background grid (the point at (0,0)) is at the top left corner of the image. Therefore, increasing ‘y’ values is equivalent to moving down on the image.
1.2: Random placement
The plains are vast, so you enlisted the help of your deputy. Unfortunately, your deputy is pretty forgetful and keeps leaving your lasso in random places all over the plains.
Use
num-random(n)to change your function so that your lasso 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 Baxter! 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:western-plainsfunction so that it takes aposnas input and returns an imagefind-baxter, that takes aposnas 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 lasso
If you can’t move the lasso around, how will you catch Baxter?
So far, our reactor uses
find-baxterto move the lasso every few milliseconds. In a game, however, we also want to move the lasso as a player presses keys. Brainstorm which keys would you like to use and how theposnof a lasso changes based on which key was pressed. Pick only two keys to start (you can add more later).Write a function
move-lassothat takes in aposnand a string and returns a newposn. The string represents a keypress, the inputposnrepresents the initial position of an object, and the outputposnrepresents the object’s new position after the keypress.Below is a list of some string-to-key mappings:
"enter""left""up""right""down""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-lassofunction 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 lasso misses Baxter and flies off your hands? (Try this out using your current reactor.)
Modify your
on-tickfunction so that if the lasso goes off the screen, it wraps around on the other side.Collisions:
Write a function
found-baxterthat takes in the position of the lasso and returns a Boolean indicating whether the lasso has captured (or collided with) Baxter.Add it to your reactor like this:
Next, congratulate your deputy for a successful capture by modifying
to-drawso that if there is acollision(found-baxterreturns 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 sheriff work, Baxter is chewing the cud gleefully in the ranch again, where he belongs! Time to get back in your sheepskin bed and take a long rest.