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
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
namedmy-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
?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 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 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 (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:
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-plains
function so that it takes aposn
as input and returns an imagefind-baxter
, 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 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 theposn
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 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:
"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-lasso
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 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:
Next, congratulate your deputy for a successful capture by modifying
to-draw
so that if there is acollision
(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.