6.813/6.831 — User Interface Design & Implementation
Spring 2018

PS2: Model/View and Event Handling

Due at 11:59pm, Wednesday, February 21, 2018, by uploading your submission to LMOD.
You must complete the self-assessment form before you hand in the assignment.
You should make sure that your problem set renders correctly on Chrome (which we'll be using for evaluating your projects) and in either Firefox or Safari. Small differences between browsers are normal, do not strive for pixel-level equivalency.

Candy Crush Pset Sequence

This, and the following two problem sets asks you to build the game Candy Crush.
You will be using the set of core technologies that drive most modern web applications, namely HTML, CSS, and Javascript.

In this second problem set, you will build a simple Candy Crush Game UI with standard HTML elements. In the third problem set, you will improve the UI using more sophisticated drawing elements. In the fourth problem set, you will implement animations and also enable users to drag candies across the board.

Candy Crush Gameplay

In case you haven't played Candy Crush before, take a moment to play Candy Crush to get a feel for the game. The rules are summarized as follows:

  • The game field consists of candies of different colors arranged in a grid view.
  • Whenever three or more candies of the same color form either a horizontal line or a vertical line, the following happens:
    • the player gains points
    • the candies are removed from the grid thereby creating holes in the game field
    • the candies on top of the removed candies move down thereby filling the holes
    • new random candies are added from the top to fill the open slots on the board.
  • The player can flip two candies if the move results in a valid horizontal or vertical row with three or more candies of the same color.

You don't have to implement the rules, since we provide an implemented model that includes the rules as methods you can call.

Useful References

To do this assignment, you'll need to know how to:

  • write HTML: create correct HTML pages that display in modern browsers
  • use HTML form elements (like <button>, <input>) to create a web application
  • use CSS to layout and style HTML elements
  • use Javascript to add event handlers and bindings to respond to user input

If you have experience with JQuery or Bootstrap, you can optionally use those in your code, as long as everything works properly. However, the world is moving away from these dependencies because Javascript and CSS are now powerful on their own. We recommend not using these frameworks. Native HTML/CSS/JS is the way to go!

You can find Web development resources on the labs page.

Provided Resources

We provide you with a repo containing the code you will be editing for this problem set. It contains the following files and folders:

  • index.html: a skeleton file for your user interface. Start coding here.
  • game.css: a skeleton stylesheet file for index.html
  • game.js: A skeleton file for your game code.
  • board.js: a Javascript file containing the Board class
  • rules.js: a Javascript file containing the Rules class
  • candy.js: a Javascript file containing the Candy class
  • util.js: Utility functions that you may find helpful
  • graphics: a folder containing all the graphics files

Feel free to change these files as you see fit. You will write most of your code into index.html, game.css, game.js. You will likely not need to edit board.js, rules.js, candy.js, util.js. You may use additional outside JavaScript libraries, but be sure to cite them directly in the code (include a link to the library's webpage). However, there is a random number generation seed at the top of game.js. Do not change this seed. Changing this random seed will result in a loss of points, because the grading of this assignment will be based on the original random seed.

If you fork the skeleton repo for your solution, make your fork private. Having your solution in a public fork will be considered equivalent to giving it to students to copy.

The UI

Figure 1. A simple Candy Crush UI using standard HTML elements

1- Basic Layout (25%)

First, build an interface that looks like Figure 1. Ensure your interface is as close as possible to the screenshot. Below are detailed specifications. In particular:

  • There should be spacing of at least 10px between the left column buttons, the candy crush grid, and the right column buttons.
  • There should be spacing of at least 10px between the top of the page and the candy crush grid.
  • A three-column layout should be used for all elements on the screen. A starting template of this is provided in index.html, using native CSS elements. Modify the template to display as columns, and make the middle column 50% of the page.
    • The first column should contain two elements:
      • The game title (bold and colored)
      • A New Game button
    • The second column should contain the game board:
      • The game board should have a fixed size of 400x400 pixels. It should have 8 rows and each row should have 8 squares.
      • The candies should be placed in an 8×8 grid. The exact HTML elements and CSS you use to construct this grid is up to you, but you will need to use at least one element per cell. You will likely want to write javascript code to automate the construction of this table.
      • The "candies" will be images provided in the "graphics" folder of the problem set download.
      • Each cell in the grid should have the same (square) dimensions.
      • There should be some sort of border/grid lines in the table, as seen in the screenshot.
      • To generate the candies, you should call the rules.prepareNewGame method, which is defined in rules.js. This function generates a new valid game board. To add a candy to the board, it generates calls to the add event listener, which you will need to implement in game.js
      • For the purposes of this assignment, we will develop a convention to name each candy by row (1-8) and column (a-h). Add a column and row as seen in the screenshot to indicate the coordinate system.
    • The third column should contain a panel to allow the user to move candies:
      • Include a text field in which the player can enter the candy that should be moved (e.g. a1 for the top left candy). You don't have to add the click events yet, you will do this in the next step. Initially, this text box should have focus.
      • Around the text box, include a grid of four arrow buttons, one for up, down, left, right. The buttons should be spaced as seen in the screenshot.
      • Below the grid, add a button called "Crush Once"
      • In PS4, you will implement functionality to drag candies to move them. In PS2 and PS3, however, you will only move candies with button triggers and a text box.
    No behavior is required to earn the points for this part, just a static layout.

    2- Adding Basic Behavior (25%)

    Now add basic user interaction:

    • When the New Game button is clicked, a new game board is generated.
    • When the user clicks on the up/down/left/right buttons, the text from the textfield should be read by your program and the corresponding candy moved, if the move is valid according to the rules.
    • To test if the move is valid, call the rules.isMoveTypeValid method (you might also find the board.getCandyAt method helpful). If the move is valid, call board.flipCandies which will actually flip the candies. The flipCandies method issues a move event, so you will also need to implement the "move" event listener. You may find the board.getCandyInDirection method useful. You should not crush the candies in this step. You will add candy crushing in step 4.
    • Assume valid user input for now, we will implement input checking in the next step.
    • After the user has clicked one of the buttons, the text field should be cleared and the focus should be automatically returned to the text field, so that the user can start typing as soon as the last move was executed.

    More Information on how Board.js and Rules.js interact:

    The Board is the "dumb" data object that just holds state, and Rules is the "smart" object that holds no state but knows how everything moves. Since all state changes go through the board, any code wishing to be aware of board changes can listen to Board events. The Rules object has all the complex methods. The Rules object holds a Board, and the Board does not know about Rules.

    3- Adding Basic Input Check (25%)

    In this step, you will add basic functionality to verify user input and improve usability by preventing invalid user input. To do so:

    • The up/down/left/right buttons should only be enabled once the user has typed something into the text field that is a valid entry (e.g. a5 is but ZZZ8 not, an empty text field also does not contain valid input). You may optionally consider uppercase letters (A-H) to be valid input characters, but this is not required. If the entry is not valid, the buttons should be disabled and cannot be clicked.
    • Only enable the buttons that represent a valid move based on the game rules: when flipping does not result in a row of three or more candies of the same color, the corresponding up/down/left/right buttons should be disabled as well. You will want to call the rules.isMoveTypeValid method in rules.js to determine the validity of each of the four potential move directions.
    • To make enabled buttons even more visible to the user, change their background color to something other than gray, and restore to default when disabled.
    • These checks are best performed once the user has entered at least two characters in the text field.

    You may find HTML5 Constraint Validation useful.

    4- Crush Once Button (25%)

    In this version of Candy Crush, candy crushing won't happen automatically. To crush candies (i.e. remove them) users may press the Crush Once button which causes a single round of crushing.

    • The Crush Once button should only crush immediately crushable candies. You need to click it multiple times to crush a chain of crushes.
    • When you press the Crush Once button, it should do two things that the user can see. First, it should remove the crushed candies (revealing just the white background of the page). Secondy, the board should be repopulated. These steps should be performed sequentially, and there should be 500ms from when the candies are removed, and when the candies are shifted down.
    • After the Crush Once button has been pressed, cursor focus should return to text box, which should be empty and ready for the user to enter a cell coordinate.
    • You'll likely find the following methods useful: rules.removeCrushes (which takes the output of rules.getCandyCrushes()), setTimeout, and rules.moveCandiesDown(). You'll need to implement the remove listener in game.js, which is called by these methods.
    • You DO NOT need to implement an animation to move the candies down smoothly in this step. You are simply removing them, waiting 0.5 seconds, and repopulating the board. You'll implement a smooth crush animation in pset 3.
    • The Crush Once button should be validated just like the arrows. When there is nothing to crush, it should be disabled. When there is something to crush, it should be enabled. As with the arrow buttons, the Crush Once button should change to some color other than gray when enabled, and be restored to default when disabled.
    • The arrow buttons and text box should be disabled if the Crush Once button is enabled.
    • Importantly, it should be impossible to enter an illegal move through the UI. In particular, during the 500ms delay, you should not allow users to move candies until after the crush has finished.

    Further (Optional) Improvements

    In pset 3 and 4, you will be implementing more functionality to the game including removing crushed candies and keeping track of score. If you'd like to learn more and go further now, here are some ideas for improvements:

    • Improve input checking by making the text field non-case sensitive (a1 and A1 both work) and ignores whitespace.
    • Implement keyboard functionality such that the up arrow on the keyboard presses the up arrow button on the interface, etc.
    • Let the player enter a name into a text field or let the player select a name from a dropdown menu of previous player. Display the player name in a label.
    • Trigger the New Game button and Crush Once button with keystrokes (perhaps n and spacebar).

    What to Hand In

    You must complete the self-assessment form before you hand in the assignment.

    Package your completed assignment as a zip file that contains all of your HTML, JS, and CSS files. Failure to include all necessary files for running your program will result in a loss of points from your final grade. (Please test by unzipping your zip file into a new directory, say, your /tmp directory and then opening your page to see if it still works.)

    Here's a checklist of things you should confirm before you hand in:

    1. Complete the self assessment.
    2. Make sure that the page renders correctly on Chrome (which we'll be using for evaluating your projects) and in either Firefox or Safari.
    3. Make a fresh folder and unpack your zip file into it.
    4. Make sure all assets (images, any libraries, JS files, CSS files, etc.) used by your code are found in the fresh folder and load successfully.

    Submit your zip file on Stellar.

Your task is to implement the user interface in Figure 1.You will complete a self-assessment after you complete the assignment.