Try   HackMD

Project 2: Movie Maze Craze

Deadlines

Design Checks: Sunday, October 30 to Wednesday, November 2

  • One group member must submit the design check to Gradescope at least 12 hours before meeting with your design check TA. Ensure both partners are added to the submission

Final Handin Deadline: Tuesday November 8, 11:59PM EST

Project Overview

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

You will be creating a maze game. The user will navigate an alien around the maze using key presses and mouse clicks. The maze will contain some special items (gadgets), such as tickets to completely restore the alien's strength, popcorn to give them a small strength boost, wet floor signs to deplete their strength, or wormholes to allow the alien to teleport. The strength is shown as the yellow bar on the right. The goal: help the alien safely make it back to her computer at the end of the maze.

Note: the video above shows the maze functionality with different special items. For this game, the item correspondence is: banana -> popcorn, apple -> tickets, tomato -> wet floor sign, blue circle -> wormhole, and exit -> computer

Specifically, you will make a) the code to "render" (draw) the maze, its items, and the alien, and b) the logic required to allow the (human) player to use the mouse and keyboard to navigate the alien around the maze.

To configure the maze, we will use tables in a new way: you'll use a Google Sheet to set up where the walls should be, as well as additional Google Sheets to give the coordinates where gadgets should initially be. Your program will read in these sheets, using them to create the actual background image and initial game state. The game play itself will be implemented with a reactor (as we did in lab 2 and have been doing in lecture).

The project also offers different levels of completion, roughly corresponding to whether your goal is to earn an A, a B, or a passing grade on the project. The grading section further down goes into the details.

Project Learning Goals

This project applies what we've been learning about lists, recursion, and datatypes. It exercises your ability to detect what information does and doesn't change over time in a program. It has the side benefit of showing you how animations can be built, and of showing how tables can be useful for more than just storing data. Here are the specific skills you will practice.

  • Creating and using your own datatypes.
  • Using recursion to process various types of lists.
  • Breaking down complex goals into discrete, solvable tasks.
  • Using tables for code configuration rather than as datasets.

What class material does this build on?

This project builds on the recent reactor lectures (as well as lab 2) and the recursion skills that you practice in homework 5 and lab 6.

Game Details

Maze

The entire maze should be surrounded by one layer of walls (except at the end location), so you don't have to deal with the alien moving outside of the maze. This also makes it clear to the human player where they need to navigate to in order to complete the game.

The wall and floor tiles are 30x30 pixels (you will need this information to convert coordinates in the grid to coordinates for place-image in Pyret). The alien, gadget, and portals are 24x24 pixels.

The Player and Character

The current position of the player in the maze is represented with an image of the alien. The human player moves the alien using the W (up), A (left), S (down), and D (right) keys. The alien cannot walk through walls of the maze, but can move through empty space.

Items

There are two kinds of items placed in the demo maze: gadgets and portals. Gadgets are things a player can pick up to increase stamina. Portals are places characters can jump (a.k.a. teleport) to if they are close by.

There can be an arbitrary number of these items placed on the maze. Items are picked up when the player moves into their cells (meaning they disappear subsequently); gadgets are immediately consumed, and portals are "held on to" until use. Multiple portals can be collected; only one is used each time the player teleports.

You will implement either gadgets or portals into the game. You only need to implement one of these to get full credit. You may do both if you want, but you will not get extra credit. Either option is challenging in its own way; we do not think either is significantly easier than the other.

Starting, Winning, and Losing

The alien will start at a location of your choosing. The information of where they start should be hardcoded through named constants in your code.

The player wins the game upon reaching the computer

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
at an exit location that you set. This information should also be hardcoded through constants.

The player loses the game if the alien run out of stamina. If you don't implement gadgets, the player doesn't have to worry about losing.

Upon winning or losing, the game can simply stop. You may also choose to somehow inform the player that they have won or lost, but this is not required.

Phase 1: Design Check and a Basic Reactor

For this project, you will write a bit more code than you did for the project 1 design check. Our goal with the design check is for you to (1) design your data structures, (2) make sure you have a basic reactor infrastructure working, and (3) have viable plans for building out the reactor to the full version you are implementing.

For design check, you will hand in an initial game-f22.arr file. Submit this to Gradescope at least 12 hours before your design check starts.

We recommend doing the questions in order as much as possible, as each question will help you think about the next.

Task 0: Make a copy of the project starter file.

Task 1: Decide whether you want to implement gadgets or portals.

Task 2: Watch the video above and figure out what information changes over time as the game is played. Just write this down in prose (no code).

Task 3: Organize this information into a Pyret data block that captures the state of the game (call it GameState). You will end up using a combination of lists and other data blocks in your design. Include whichever of gadgets or portals you've chosen (you can skip the other).

Hint: Figuring out the datatype for this is one of the more challenging parts of this assignment. Look at the things you identified for Task 2: you'll end up making datatypes for objects in the animation (with their attributes), collections of similar objects, and datatypes that gather objects and collections into single "concepts" within the game. Expect to need some time here. If you aren't sure what makes the most sense, come up with a couple of different ideas and review them with a TA.

Note: your data block should contain ONLY information that changes about your animation over time. An element that doesn't change will go into the background in Task 5.

Task 4: In code, write a concrete example of GameState data for an initial configuration of your game. Don't worry about information that will eventually come from one of the Google Sheets just make SOME example for now.

Task 5: Build the BACKGROUND image for a maze (the part of the image that does NOT change over time). Don't worry about including the gadgets or wormholes.

Notes: A maze design will be given as a list of lists such as the following ("x" is a wall/blocked, "o" is open space):

small-maze = 
  [list: [list: "x", "x", "o", "x"],
         [list: "x", "o", "o", "x"]
         [list: "x", "o", "x", "x"]
         [list: "x", "o", "x", "x"]
         ] 

While later in the project you will read in such a list of lists from a Google Sheet, for a first pass just build a maze background image from a small example like small-maze.

How can you do this? Notice that the list of lists is a form of grid; the maze image will also be a grid, just made from images (with a "wall" icon in place of "x" and a "floor" icon in place of "o").

In lab, you practiced aggregating a list into a single image. For the pulsing star example in lecture, we aggregated multiple images into one image. This question has you apply and combine these ideas; if you come to hours or post on Ed, talk through your proposals for doing this, rather than simply ask us how to get started. (You'll have to decide whether place-image or above/besides/etc are more useful for aggregating images, but these give you the concept).

Task 6: Set up a simple reactor that moves the alien across the background image when the human player presses a key, though not paying attention to the maze grid cells or walls (just get a basic reactor running). Use the concrete example from step 3 as the initial GameState configuration.

Task 7: Make sure you can load the configuration data from Google Sheets. Make a copy of a configuration spreadsheet. In Google Sheets, you can do this by clicking File > Make a Copy...

  • share the spreadsheet with your partner
  • give "Anyone with the link" the ability to view the spreadsheet (you have to go into the Advanced sharing menu to do this).
  • insert the ID of your spreadsheet into the name ssid in your file
  • take the comment marks off the definitions of maze-grid and items-table and make sure your file runs.

Then look at maze-data and item-data to get an idea of what they look like.

From here, we want you to plan key parts of the rest of the solution, so you can review them with your design-check TA.

Task 8: Write a plan for how you will add the gadgets or portal image to the maze.

Task 9: Write out a plan or general sketch of how the key-pressed function should work. Pick one of the four keys (W, A, S, D) and write out the tasks (3-5 one sentence bullet points) needed to compute the new GameState based on the current GameState. What are some edge cases that you'll need to consider? Write a single where test case on a small GameState for the key that you planned out.

Task 10: Plan how to implement gadgets or portals.

  • If you are implementing gadgets: write out a plan for what should happen to the GameState when the alien lands on a square with a specific gadget (pick whichever one you want to handle). Add a where example that corresponds to your plan.
  • If you are implementing portals: The reactor mouse-clicked function takes in the current GameState value, the x and y value of the position of the mouse event (in the reactor), and a String that represents the name of the mouse event. Write out the tasks needed to compute the new GameState based on the current GameState if the mouse has been clicked. Write a corresponding simple where example for mouse-clicked.

Phase 2: Implementation Details

Configuring the Maze (in Google Sheets)

The game will be populated based on your copy of one of the following spreadsheets (depending on whether you want to implement gadgets, portals, or both):

  • Gadgets spreadsheet: link
  • Portals spreadsheet: link
  • Both items spreadsheet: link

Each spreadsheet has two sheets: maze-layout and items.

  • The maze-layout sheet determines which parts of the maze are walls and which are blank and therefore where the player can walk. "x" corresponds to a wall, and "o" corresponds to a floor (tile).
  • The items sheet contains a list of items that will be placed on the maze. The
    x
    column is the distance from the left side of the screen, and the
    y
    column is the distance from the top of the screen. (These distances are in terms of the grid labels in the maze, not pixels for built-in Pyret image operations ) You will need to edit this sheet to put items in the appropriate places.

Note 1: Positions are zero-indexed; the row "Tickets", 1, 7, "tickets.png" corresponds to an

key being placed in the 2nd column and the 8th row.
Note 2: You do not need to do any error checking for items being placed in invalid locations (like on walls or off the maze).

The maze we provide in the Google Sheet is 35 squares per "row" and 19 squares per "column" (19x35), but you can add or remove rows, columns, and items as you please and make the maze your own! If you change the number of columns in your maze, replace the call to load-maze in the starter code with a call to load-maze-n. The latter is the same as load-maze except it has a second parameter which is the number of columns to load.

Do not adjust or rescale the sizes of the images that we provide. Parts of the support code will break if you do.

A video-based overview of the spreadsheets and how the gameplay works are in this video.

Reactor Documentation

You have seen the reactor properties init, to-draw, and on-key before. If you are implementing portals, you will also need to use the on-mouse function, which works similarly to the on-key function; check out the on-mouse documentation for more.

You can refresh yourself on reactor properties here. You may also want to look at your code or the code files from recent lectures with reactor examples.

Converting mouse clicks to maze coordinates (portals only)

The reactor on-mouse function takes in

x and
y
coordinates that do not directly correspond to which row and column in the maze the user clicked on. Because of this, get-maze-index is a function (provided in the source code) that takes in the coordinate that is input to on-mouse and converts it to a game grid coordinate. For example, if the x-coordinate clicked is 334, get-maze-index(334) returns 11 (for the 12th column).

Implementing Gadgets

If you implement gadgets, the alien needs to have stamina. Stamina is a measure of energy often used in video games. In this game, the alien's stamina depletes by moving. If the alien runs out of stamina, it's game over.

There are three things you can encounter in the maze: tickets, popcorn and wet floor signs.

  • Finding tickets
    tickets
    replenishes the alien's stamina to its original value.
  • Finding a popcorn
    popcorn
    heals the alien for some fixed amount of stamina.
  • Stepping on a wet floor sign
    wetfloorsign
    reduces the alien's stamina to some low, fixed amount.

For example, if the alien's stamina is 20 and they move onto a wet floor sign, they may move down to 7 stamina. Then moving onto a popcorn may heal them to 7 + 8 = 15 stamina, and finding tickets will heal them to their original stamina (say, 30). Normal movement reduces stamina by 1 per cell.

There should be a visual indication of the alien's stamina, via the yellow bar on the right.

Implementing Portals

The portals in this maze will be represented by the wormhole

wormhole image. The alien can carry one or more portals, but starts with no portals. When the alien has a portal and the user clicks some square on the screen, the alien will move there as long as the cell is within some reasonable range of the alien's current location. You can choose this range, but make sure it doesn't allow the player to easily teleport to the end of the maze!

Each portal can be used only once. Your game screen should have some visual indication of how many portals the alien has (simply a number using the Image library's text function is fine).

To compute how far the human player is trying to move the alien, you can use the standard formula for computing distance between two points (see the spoiler below if you need a refresher on computing distance). In your game, if a player with a portal clicks on a cell, and the distance between the current and clicked cells is within the threshold you choose, the alien moves to the new cell and uses up a portal. If the distance is larger than the threshold, nothing changes (the alien stays in the same place and keeps the portal for another try).

The Distance Formula

The distance formula is based on the differences in x-coordinates and differences in y-coordinates between two points. Call the change in the

x-coordinate
Δx
and the change in the
y
-coordinate
Δy
:
D=Δx2+Δy2

For example, if the player is at

(3,8) and wants to move to
(6,4)
,
D=(63)2+(48)2=9+16=5
. This is a "birds-eye view" of distance.

Approaching This: Work on One Feature at a Time

The key to tackling a larger assignment like this is to build the features up gradually. For example, get the game working on just basic functionality before adding more advanced features. What might that mean here?

  1. Implement a version with just the walls (no gadgets or portals), such that the player can move around the maze while respecting walls.
  2. Read in the items (popcorn, portals, etc) from the Google Sheet, store them in your data structure(s), and make them show up when you draw the GameState.
  3. Get the items to disappear after a player visits their cells.
  4. Make the game handle the items (modifying stamina or teleporting).

These phases correspond to the grading levels for the project (see the Grading section below). You can pass the project even if you don't get beyond phase 1.

We strongly recommend saving a copy of your file after you get each stage working, just in case you need to get back to your last stable version (practicing programmers do this all the time).

Grading

Testing

Since there are many functions that will be written for this project, we will only be requiring minimal testing for all functions that are not critical functions. In an ideal world, you would thoroughly test all functions; however, we would rather see you test one or two functions really well (to show you understand the concept) and others partially, rather than only doing partial testing or no testing at all for all functions, especially critical functions.

Because of this, we will grade (1) minimal testing (>= 2 test cases) for non-critical functions that output things other than an Image, and (2) your thorough testing (try to hit as many tests of edge cases as possible!) for the function that moves the character (the one you use as on-key, or on-mouse). Test this function thoroughly, covering as many cases as you can. Regarding your other functions, write as many tests as you think you need to be comfortable with it working - but include at least 2.

Your design, testing, and clarity grades will not be based on your functionality grade. Functionality will be weighted more heavily in your final grade for this project in particular. Here is what we're looking at when grading functionality:

Minimum Functionality:

  • A character that moves in response to key presses, moving full maze-cells at a time.
  • Player cannot pass through walls.
  • Game stops/ends when the character reaches a certain destination.

Mid-tier functionality:

  • All above.
  • Gadgets or portals are rendered on the maze.
  • If doing gadgets: your character must have stamina that depletes upon moving. The gadgets do not need to be functional for mid-tier functionality. Upon reaching 0 stamina, the game should end.
  • If doing portals: upon picking up a portal, your character can teleport. There does not need to be a limit of the portal range or the number of times the player can teleport for mid-tier functionality.

For full functionality:

  • All above.
  • If doing gadgets: tickets bring the character to full stamina; wet floor signs bring the character to a low stamina; popcorn heals for some amount; items disappear when walked over.
  • If doing portals: there is a limit to how far the character can teleport and how many times a portal can be used.

Reflection

This project was designed to give you practice with organizing and manipulating structured data. Answer the following questions about these topics in a block comment at the bottom of game.arr.

  1. Our support code represented the maze layout (walls vs floors) as a list-of-lists of strings, rather than a table. What were the advantages and disadvantages of this choice?
  2. In this project, you worked with the maze in three formats: the Google Sheet with the configuration of walls, the list-of-lists version, and the image itself. For each representation, briefly describe what it is good and bad for.
  3. Describe one key insight that each partner gained about programming or data organization from working on this project.
  4. Describe one or two misconceptions or mistakes that you had to work through while doing the project.
  5. State one or two followup questions that you have about programming or data organization after working on this project.

Block comments are written with #| and |#:

#|
  this is a block comment.
  with multiple lines!
  yay!!
|#

Handin

Hand in game.arr on Gradescope.

EdStem and Feedback

  • EdStem can be your friend for this Project!