CS 106 Winter 2018
Assignment 04: User Interfaces
Question 1 Tangram
The tangram is a classic puzzle/toy consisting of seven geometric tiles. A standard puzzle is to arrange the tiles into a single square, but it's also possible to use them to make a vast number of geometrical shapes, whimsical designs, animal forms, etc.
In this assignment you will write a sketch that lets you manipulate a set of tangram tiles using direct manipulation. The sketch will also include a few UI controls, created using ControlP5. The seven pieces have different shapes, but the provided code will deal with the complexity of managing all those shapes.
Download the starter code and open the Tangram sketch. There are two tabs, Tangram and Pieces. You will see that there isn't very much in Tangram, just the very start of a new sketch. But Pieces gives you everything you need to describe, control, and create a set of Tangram pieces. Look over the code, and read the comments to get a sense of how to use the class and function provided in this file.
Change the sketch to maintain a global array of Pieces. Declare a global variable of this type at the top of Tangram, and initialize it in setup(), using the function provided in Pieces.
Add a draw() function that clears the sketch window and asks every piece to draw itself. You can use any background, fill, and stroke colours you want. But we recommend that you give each piece a visible outline, which makes it easier to understand a drawing with overlapping pieces.
Add a mousePressed() function that performs hit testing on all the pieces. Declare a global integer variable that keeps track of (the array index of) the currently selected piece. When the sketch starts, set it to -1 (meaning "no currently selected piece"). In mousePressed(), hit test every piece. If any one reports a hit, it becomes the selected piece. If no piece was hit, set the variable back to -1. Remember to hit test the pieces in the opposite order that you draw them, so that the frontmost of overlapping objects will end up selected.
Add a mouseDragged() function that can be used to move pieces around. If there's a currently selected piece, tell it to move. Use the method shown in class, based on the difference between the current and previous mouse positions. At this point you should be able to move pieces around, leading to a sketch window that might look like this:
In some applications, it might make sense to add a mouseReleased() function now, which deselects the current piece when you let go of the mouse button. Don't do this. For Tangram, it will make more sense for the last piece the user touched to stay selected until they touch another one, or click on the background to deselect. (You don't actually have to do anything for this step.)
Modify your draw() function so that there's a visual indication of the currently selected piece. For example, change its outline or fill colour so that it's always clear which piece is active.
Begin adding a ControlP5 user interface. Import the library, declare a global variable to hold the UI factory, and initialize it in setup().
Add a button labeled "Quit" that, when pressed, closes the sketch window. Use the built-in function exit() to quit. You may want to add a controlEvent() hook to check for the button press.
Add a button labeled "Reset" that moves all the pieces back to their initial positions and rotations. Don't try to move each piece back one-by-one; instead, just make a whole new array of pieces and throw away the old one. Also reset the selected piece variable to -1.
Add a button labeled "Rotate". If there's a currently selected piece, this button should ask it to rotate itself. (Generally, make sure the buttons have a reasonable size and layout.) There's one small problem here: clicking on "Rotate" will also be treated as a click in the sketch window, which will deselect the current piece. There's a bit of non-obvious code that avoids this problem: add the following code to the very beginning of mousePressed():
if( !ui.getWindow().getMouseOverList().isEmpty() ) { return; }
(This if statement checks if the mouse press happened while the mouse was inside a ControlP5 element, in which case it stops doing anything. You don't need to understand why this works.)
In addition to the requirements above, there are many opportunities for optional enhancements. Here are some suggestions for things to try:
Make an interesting Tangram design. If you do, put a screenshot in your submitted sketch folder. If you're feeling more ambitious, add code to save your Tangram design as a PDF.
Give each piece a different colour. To implement this, you may want to modify the Piece class to include a colour field, so that every piece "knows" what colour it is.
You'll notice that even after implementing all the steps above, there are still some Tangram designs that you can't reproduce. The problem is that you can't flip over the parallelogram piece so that it points the other way. Add a "Reflect" button that flips a piece over. (There's some tricky math involved here.)
Add a bit of physics to the sketch. For example, have a piece "slide" a bit when you let go of it.
Have a way for pieces to "snap": when they get close to lining up, the sketch figures that out and makes then line up perfectly.
You can add whatever enhancements you want, as long as the core features above still work. Add a comment to the top of your sketch to say what you added. We will award bonus marks to creative or ambitious enhancements.
Submission
When you are ready to submit, please follow these steps.
Please ensure that any sketches you submit compile and run. It's better to submit a sketch that runs smoothly but implements fewer required features than one that has broken code for all features. If you get partway into a feature but can't make it work, comment it out so that the sketch works correctly without it.
If necessary, review the Code Style Guide and use Processing's built-in auto format tool. You do not need to use the precise coding style outlined in the guide, but whatever style you use, your code must be clear, concise, consistent, and commented.
If necessary, review the How To Submit document for a reminder on how to submit to LEARN.
Make sure to include a comment at the top of all source files containing your name and student ID number.
Create a zip file called A04.zip containing the entire A04 folder with its Tangram subfolder.
Upload A04.zip to LEARN. Remember that you can (and should!) submit as many times as you like. That way, if there's a catastrophe, you and the course staff will still have access to a recent version of your code.
If LEARN isn't working, and only if LEARN isn't working, please email your ZIP file to the course account (see the course home page for the address). In this case, you must mail your ZIP file before the deadline. Please use this only for emergencies, not "just in case". Submissions received after the deadline may receive feedback, but their marks will not count.