6.813/6.831 — User Interface Design & Implementation
Spring 2018

PS4: Input

Due at 11:59pm, Wednesday, April 4, 2018, by uploading submission to Gradebook.
You must complete the self-assessment form before you hand in the assignment.
You should make sure that your problem set works correctly in Chrome (which we'll be using for evaluating it) and in either Firefox or Safari. The problem set instructions are not meant to encompass everything that you should and should not do. When working on these problem sets, think of the future and what problems or user needs may come up and whether your code is ready for change (RFC). We will be grading on the proactiveness of your code.

This assignment explores the following topics related to GUI input:

  • event handling
  • hit detection
  • dragging
  • enabling/disabling commands based on view state

In this problem set, you will implement animations as well as input handling for the Candy Crush game you have been creating, so that the user can pick up candies with the mouse and drag them around.

Useful References

You will need to know about mouse input and event handling in Javascript, and these references may be helpful:

If you want to review HTML/CSS/Javascript, check out the links from the web development lab resources.

The UI

This assignment builds on top of the code you wrote for pset 2 and pset 3. You will implement a smooth candy flipping and crushing animation. You will then update your UI to appear as in Figure 1, ultimately replacing the direction buttons with mouse click and drag functionality.

Figure 1. Pset 4 Drag & Drop UI

Problem 1: Showing Hint On Delay (10%)

In this problem, you will remove the "Show Move" button and replace it's functionality with having a hint display automatically.

After each new game and crush, a hint should begin animating if the user has not made a move in 5 seconds. Like in pset 3, the hint should stop being displayed after the user moves a candy or clicks the "New Game" button.

Problem 2: Cascading Crushes (20%)

In pset 3, you implemented animations for candy flipping, moving, and crushing. In this problem, you will replace the "Crush Once" button and functionality by handling all crushes that happen as a result of flipping two candies.

In this problem, you will modify the candy crushing behavior to handle multiple crushes. If a candy crush produces more crush opportunities, the same smooth animation to remove and fall candies down should occur.

Shown below is an example of the cascading candy crushes.

Figure 2. Cascading Crushes

Be sure to remove the Crush Once button. Smooth crushing should occur automatically now, whenever a candy is flipped.

Problem 3: Dragging Candies (50%)

Add input handling to your Candy Crush board so that the user can drag candies to make them switch their positions. Remove the text box & arrow buttons. Below is a video showing this functionality:

Figure 3. Dragging Candies

Pressing and dragging a square containing a candy should pick up the candy from the board. The candy should not make any abrupt jumps when it is picked up — not when the user presses the mouse button, and not when the user starts moving the mouse. The candy should move smoothly with the mouse pointer, hovering over the other candies on the board (see Figure 3). Be aware of z-order, since you want the dragged component to hover on top.

Test your drag & drop functionality in various window sizes (by dragging the browser to resize it). Ensure that normal drag & drop behavior remains functioning, and the candies do not "jump" when clicked and/or dragged.

If the user releases the mouse button when the mouse pointer is over a square, the candy should be moved to that square using the board.flipCandies method. The motion to the square should be smooth (you should be able to use the same animation you implemented in pset 3 in the move event handler). The candy that was occupying this space should smoothly move to the previous position of the dragged candy (also animated in the move handler).

When you drag a candy into a valid square and release, it should move from wherever you released it to its final centered position inside that square. It should NOT move back to its original square and then be animated into the square where you originally dropped it.

If the mouse pointer leaves the Candy Crush board during the drag operation, the dragged candy may either follow it or stop wherever it is on Candy Crush board — the behavior is up to you. That said, behavior should remain consistent when you drag a candy outside the board - either candies should ALWAYS stop inside the board, or they should ALWAYS follow your mouse outside the board. This should be independent of the speed with which you move the mouse. If the mouse pointer moves back into the Candy Crush board, the candy should resume following the mouse (if it had stopped wherever it was on the Candy Crush board). If the mouse button is released when the mouse pointer is off the Candy Crush board, the candy should be put back where it was taken from. If the mouse button is released when the mouse pointer is outside the browser window entirely, the behavior is unspecified. That said, your UI should not freeze nor require the user to refresh the browser to resume interacting with the interface. Ideally, the candy should be returned to the board if the mouse leaves the screen while dragging.

Figure 4. Example of dragging candies outside of the board.

For now it is ok to ignore the rules of the candy crush game and switch any two candies on the board by dragging one over the other. You'll restrict dragging and dropping to valid moves in the next problem.

You must implement dragging by listening for mousedown, mouseup, mousemove events. Solutions that use HTML5 drag and drop or jQueryUI draggable or other drag-and-drop libraries will not receive credit. This requirement is in place for two reasons: these packages do not implement the behavior we're looking for, so you will have more headaches if you try to use them; and because you should learn how to handle low-level mouse events, just as you're learning how to use strokes as well as objects for output.

The mouse cursor symbol should remain constant during drag and drop and not change sporadically throughout interaction with the UI.

Be sure to remove the "ghost image" default dragging behavior on images such that when you drag candies, you only see the full-color image moving, not the "ghosted" image.

Problem 4: Following the Rules (20%)

Now, update your implementation to only permit flipping candies by drag and drop when the flip is a valid move, according to the rules of the game.

If a dragged candy is released over a non-valid square (i.e. one that is not a direct neighbor of the selected candy, or moving to that square would not result in crushed candies), then the dragged candy should be put back where it was taken from. This must be a smooth animation, the candy should not jump back to where it came from. Dragged candies that were released on an invalid move should remain above the other candies until they return to their original position.

You may find rules.isMoveTypeValid() helpful.

Figure 6. Invalid Move

Verify that all game functionality is as intended, including functionality from psets 2 & 3 (including "New Game", "Show Move", and updating the score). Candies should be draggable even if a hint is being animated, though the animation should stop once a candy is clicked. Candies should not be draggable while candy crushing animation is occuring.

Optional: Going Further

If you just LOVE Candy Crush and are up for a challenge, here are some ideas for optional improvements:

  • Improve your candy crushing animations - play the Candy Crush mobile app for inspiration!
  • Add sound effects when candies are crushed - the mobile app also has great examples of playful sound effects.
  • Investigate HTML Local Storage. LocalStorage is a key-value storage space for web applications to store information directly into the user's browser to persist beyond a single session. You may use local storage to save high scores, to restore the state of a game after closing and re-opening the browser, or keep track of how many times the game has been played. Local storage may come in handy for your projects - as you won't be implementing a backend, local storage is a good minimal substitute.
  • Do hit testing for the true area of a candy, so that clicking in the corner of a square (in the white region) doesn't pick up the candy.
  • Add functionality for "special" candies! We've provided some images in the graphics folder (blue-special.png, orange-special.png, etc). In the mobile app, these striped candies clear a whole row or column. But of course, you can make them do whatever you want.

What to Hand In

You must complete the self-assessment form before you hand in the assignment.We will be deducting points if you don't submit the self-assessment form.

We will be grading you based on your code as well as the functionality so your code should be well structured, formatted, and commented. Do not minify your files as it makes it impossible to grade for code style.

Package your completed assignment as a zip file that contains all of your 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, say, your /tmp directory, and then opening your page to see if it still works.)

We will be grading your pset on our local machines under the file:// protocol. If you worked on your pset through a local server, please make sure it also loads successfully under file://. For example, avoid root-relative URLs (/graphics/blue-candy.png). Plain relative URLs should work fine (e.g. graphics/blue-candy.png).

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 necessary assets (images, JS files, CSS files, etc.) used by your code are found in the fresh folder and load successfully.

Submit your zip file on Gradebook.