6.813/6.831 — User Interface Design & Implementation
Spring 2017

PS3: Input

Due at 10:00pm, Wednesday, April 5, 2017, by uploading submission to Stellar.
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.

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 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 HTML5 canvas, here are useful video tutorials picked by the course staff:

If you want to review HTML/CSS/Javascript/jQuery/jQueryUI, here are useful video tutorials picked by the course staff:

The UI

This assignment builds on top of the code you wrote for ps1 and ps2. You will implement a smooth candy flipping & crushing animation, if you have not already done so. 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 3 Drag & Drop UI

Problem 1: Flipping & Crushing Animation (40%)

(from pset 2) Read carefully as the specifications have been clarified.

In pset 1, you implemented a simple "animation" (based on a timeout) to visually indicate candy crushing with the "Crush Once" button. In this problem, you will replace the "Crush Once" functionality with a smooth animation to provide visual feedback of candies being moved and crushed.

In this problem, you will implement two smooth animations:

  • Candy Flipping: When two candies are moved (by the click of an arrow button), the two candies should be animated such that they smoothly swap locations.
  • Candy Crushing: After two candies have swapped, the candies to be crushed should be removed by fading out, and the candies from above should fall down smoothly to fill the holes. If this produces more crush opportunities, the same smooth animation to remove & fall candies down should occur.

Shown below is an example of these two animations, which smoothly drops the candies down.

Example Animation (note: you'll remove the arrow buttons in problem 2)

To accomplish this animation, you'll need to update your "move" event listener to smoothly flip candies and animate the candies falling down. You'll also need to update your "add" event for adding new candies to the board from above, in which case you'll want to drop them in smoothly. To do this, if info.fromRow and info.fromCol are not null, then you'll want to perform a smooth animation to drop the candies in. You'll also need to update your "remove" event, to fade out candies.

You may implement these animations a variety of ways. We recommend you look at jQuery animate. You can also check out CSS3 Animations. Ensure your animations are smooth, perhaps by checking out easing functions. Feel free to experiment, and find something that is cool, creative, and unique.

Clarification on Animation Requirements

The exact implementation/timing/sequencing of your animation is up to you. There are no specific requirements regarding how long to delay between the triggering of a candy move event and when the candies flip and fall down. Tune these paramaters to make your animation feel as smooth and natural as possible. It's also up to you if you want to have candies fall down and overlap eachother or fall down without overlap. However, a candy that is crushed should be completely removed before a new candy arrives in its cell to replace it.

Animation behavior is unspecified on page load and also after the user presses New Game. You may choose to eliminate the animation of crushes for a new game board, or keep them in. You may choose to suspend fade out for removed candies during the generation of a new game, or leave them in. You may choose to smoothly drop the candies in from above or have them appear. It's up to you.

Be sure to remove the Crush Once button. Smooth crushing should occur automatically now, whenever a candy is flipped. As crushing occurs, the arrow buttons should be disabled so that the user cannot interfere with the crushing. Also, disable the "New Game" and "Show Move" buttons during animations, and you also shouldn't populate the move text box when a candy is clicked if animations are occuring.

Problem 2: 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.

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 1). Be aware of z-order, since you want the dragged component to hover on top. Here is a useful video tutorial on z-order.

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 2 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).

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. But 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.

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. You can, of course, still use jQuery to add the event handlers, as long as what you're listening for is mousedown, mouseup, and mousemove.

Problem 3: Following the Rules (10%)

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.

You may find rules.isMoveTypeValid() helpful.

Verify that all game functionality functions as intended, including functionality from psets 1-2 (including "New Game", "Show Move", and updating the score). The arrow should appear ABOVE the candies but below any candy being dragged.

Drag and Drop CandyCrush

Optional: Going Further

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

  • 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.

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.)

List your collaborators in the comment at the top of index.html, or explicitly say that you discussed the assignment with nobody. Collaborators are any people you discussed this assignment with. This is an individual assignment, so be aware of the course's collaboration policy.

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

  1. Complete the self assessment.
  2. Make sure your collaborators are named in index.html.
  3. Make sure that the page renders correctly on Chrome (which we'll be using for evaluating your projects) and in either Firefox or Safari.
  4. Make a fresh folder and unpack your zip file into it.
  5. 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 Stellar.