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:

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:

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.