Comp 110 Emoji

DISCLAIMER: Due to the shortened time period of the semester from closures, the point value of this problem set is reduced to 30 points rather than the typical 100. This means across all problem sets this semester there are 630 possible points. This problem set is due on LDOC, but late submissions will be accepted through Friday 12/7 at 11:59pm. Office hours will not be open after LDOC so please plan accordingly.

In this problem set, you'll create an emoji using code. We encourage you to have fun with it and go beyond the minimum requirements! PS6 is all about getting your hands dirty with object-oriented programming while being creative. This is also the first problem set where you will rely on external documentation as part of a class library.

A few of last semester's best submissions are pictured above. Yours does not need to be this fancy - this is a high bar. However, if you're feeling ambitious, the UTAs and I love being impressed with technical artistry!

Tip #1: Before writing any code, sketch your emoji on graph paper. Aim to work in a coordinate system with x and y axes ranging from -100 to +100. Know that one requirement is to use at least one rectangle, one circle, and one path (series of lines) in your final emoji.

You will build a class for each part of your emoji's face and then assemble these parts together in your final Emoji class, kind of like piecing together parts into a Mr. Potato head "FaceShape". You will make an Eye class (and then construct two Eye objects from the same single class), a Mouth class, and so on.

Tip #2: When working on individual parts, try to center each part around the coordinate 0, 0. In the last step, you will place these parts at their correct coordinates, relative to one another. 

Tip #3: Your Eye class should only contain the shapes for a single eye. At the final step you will construct two Eye objects from your single Eye class. You will be able to position each eye independently of the other.

We are providing stencil code to help get you started with this assignment. You'll use the IntroCS Graphics library's built-in classes while writing your own classes with properties, a constructor, and methods.

Tip #4: Explore the library's documentation to familiarize yourself with what shape classes and capabilities are available for you to work with. In particular, look at:

  1. Circle
  2. Ellipse
  3. Rectangle
  4. Text
  5. Line
  6. Path

Tip #5: Can't decide what red, green, and blue values to fill your color with? Go to this site that helps you pick a color, and use the RGB Normalized Decimal values as the arguments for your Color object. For example, let lilac: Color = new Color(0.874, 0.207, 0.913).

Part 0. Starting the Dev Environment

To ensure you have the latest material, be sure your development environment is shut down, then pull the latest code and start it back up. Run the following commands in the VSCode Integrated Terminal:

  1. Visit: http://localhost:3000/close
    1. If there is an error about a timeout this is OK and means your development environment is already closed.
  2. npm run pull
  3. npm run start

Setting up the App

The starting files you'll need for this app are automatically added to the folder ps06-emoji upon running "npm run pull"

You'll be doing most of your work in the Emoji.ts file, as well as some work in emoji-script.ts.

Emoji.ts - The classes for each piece of your Emoji (FaceShape, Mouth, Eye) as well as the composed Emoji class itself, will be defined within this file.

emoji-script.ts - This is the "runner" for the application. From this file, you will import each piece from Emoji.ts and render them to the SVG artboard to display your whole emoji.

CoordinateGrid.ts - You will not need to modify this file, but you may find using it helping when designing your Emoji. Its shapes method will generate a coordinate grid with labels. It is enabled by default.

Honor Code Header

All problem sets begin with an Honor Code pledge. Notice this header is contained within the block comment tags discussed in Lecture 1. You can copy/paste the pledge below and fill in your name and ONYEN. Be sure that this pledge is in the file Emoji.ts for PS06.

/**    
 * Author:    
 * ONYEN:    
 * UNC Honor Pledge: I certify that no unauthorized assistance has been received   
 * or given in the completion of this work. I certify that I understand and 
 * could now rewrite on my own, without assistance from course staff,  
 * the problem set code I am submitting.
 */

Part A. Emoji's Components

There are a few requirements you must fulfill in order to receive full credit. Outside of these requirements you have complete creative control over your drawings and your program's design.

Requirement A.0 - You must use at least one Rectangle, one Circle, and one Path in your emoji. Where and how you choose to use these shapes in your emoji is up to you. For example, if your FaceShape uses a Rectangle and your Eye uses both a Path and a Circle, you have satisfied requirement A.0.

FaceShape

Your FaceShape class will generate the background that gets layered behind your other pieces (eyes, mouth, etc). Be as creative as you'd like with your FaceShape.

We are providing stencil code for this class to help get you started. It has a constructor with a Color parameter for the FaceShape's "tone". This parameter is assigned to the property tone.

You should start the code for this problem set by first understanding how our stencil code fulfills requirements A.1 and A.3.0 for you. Then you should complete requirements A.2 and A.3.1 on your own. After that, proceed on to the Eye class.

FaceShape Requirements:

  • Requirement A.1 - FaceShape must have a single parameter constructor which takes a Color parameter to initialize the FaceShape's tone. This requirement is already completed for you in the stencil code as long as you do not remove or modify it.
  • Requirement A.2 - At least one Shape in the Group returned by the shapes method (described below in A.3) must be filled with Color tone property.
  • Requirement A.3.0 - Complete the implementation of the shapes method. It should have the following characteristics:
Return type:  Group
Name:         shapes
Parameters:   none

The method definition of the shapes method has a few requirements:

  • Requirement A.3.1: The Group returned must have at least one Rectangle, Circle, Ellipse, or Path added to it.

Eye

Your Eye class should represent a single eye *NOT* both eyes. When you get to the final step of piecing together your complete Emoji class, you will create two instances of the Eye class and position them individually. You should try to center your Eye's shapes around the coordinate 0, 0 to make the final step more straightforward.

Begin by defining and exporting a class named Eye in Emoji.ts.

Eye requires an irisColor property, just like FaceShape's tone property. Refer back to your FaceShape for help here. By making the irisColor a property, we can easily generate eyes of different colors.

Eye Requirements

  • Requirement A.3 (same as above) - Eye's shapes method must also satisfy this requirement. 

Once your Eye class is defined and its shapes method is setup, you should update your emoji-script.ts to no longer show FaceShape and instead show your Eye as you're working on its graphics. To do this, be sure to import the Eye class from "./Emoji" and update your code. For example:

// TODO: Change the following code when you work on other pieces 
let piece: Eye = new Eye(new Color(0.3, 0.3, 1.0)); 
shapes.add(piece.shapes());
  • Requirement A.4 - Eye must have an irisColor Color property. Eye's shapes method (A.3) must fill one of the shapes returned with the iris Color. Additionally, Eye's constructor must take a Color parameter to initialize irisColor. Below are the specific requirements you'll need to satisfy.
Property:  
  Type:        Color  
  Name:        irisColor
Constructor:
  Parameter:      
    Type:    Color      
    Name:    irisColor  
    Requirement:
      The constructor must assign the irisColor parameter
      to the irisColor property.

Mouth

The shapes for your emoji's mouth will be setup in this class.

You will need to first declare and export a Mouth class to the Emoji.ts file.

You will need to declare a shapes method in the Mouth class. The method declaration has the exact same specifications as Requirement A.3's above.

To visualize your Mouth piece as you are working on it, instead of your Eye piece, update the code in emoji-script.ts like you did above in the Eye class.

Mouth Requirements

  • Requirement A.3 (same as above) - Mouth's shapes method must also satisfy requirement A.3 as described above.
  • Requirement A.4 - Unlike FaceShape and Eye, Mouth class does not require a constructor. However, if you are going above and beyond and give your Mouth class some properties that need to be initialized in a constructor, we do require Mouth to have a 0-parameter constructor. You are free to define as many optional parameters as you'd like in Mouth's constructor, but none are required.

Part B. Implement your Emoji

Now that you have all your Emoji's components built... it's time to compose them in the Emoji class!

Go ahead and declare and export a class named Emoji to the Emoji.ts file.

Requirement B.0 - Your Emoji class must have at least 4 properties: faceShape, mouth, leftEye, rightEye. (If you are building a one-eyed emoji, it still needs both leftEye and rightEye properties, however, you are free to position one eye directly over the other.) Their types should be FaceShape, Mouth, and Eye respectively.

Requirement B.1 - Your Emoji class should have a zero-parameter constructor. In the constructor, you should initialize each of your properties to a new instance of its respective class. (i.e. assign faceShape a new FaceShape object).

Requirement B.2 - Your Emoji class must have a shapes method, with the same requirements as in requirement A.3. Emoji's shapes method should return a Group containing all of the shapes of its components added to it.

To achieve this, you will need to call the shapes method of each of the Emoji's properties. Consider declaring local variables to hold each of the returned Groups from your components. A Group does not have an x, y position, however, a group does have a "transform" property. Once you have a component's Group of shapes, you can "translate" (move), "scale", and "rotate" a piece by assigning to its transform property. An example is given below:

let leftEyeShapes: Group = this.leftEye.shapes();
leftEyeShapes.transform = leftEyeShapes.transform.translate(10, -20);
// The above line of code causes the group to be shifted
// to the right by 10 units on the X axis and up by 20 units on the Y.

To visualize your emoji as you are adding its piece's shapes, update your code in emoji-script.ts to work with the Emoji class's shapes method rather than Mouth's.

Composition

Learning objective: experience building up a set of reusable classes that can be composed together. In this case, notice that the Emoji class' properties are made up of other classes that you've defined. This is an example of dividing up a problem into subcomponents. We could easily extend and swap out individual pieces of the Emoji to create additional variations. The idea of subdividing a problem into many different classes and functions that can then be brought together to solve the complete problem is called decomposition and composition. It is a valuable practice in computer science that leads to simplifying problems while at the same time producing small, reusable components.

Library Reference

Be sure to make use of the graphics library's documentation for additional information on properties available to you as you craft your Emoji.

Challenge Extensions

These challenges are not for credit but are fun if you're looking for an extra challenge.

Challenges

0. Add additional component classes to your emoji beyond the required FaceShape, Eye, and Mouth. For example: Nose, Hair, Hat, etc.

1. Declare your own helper methods in classes to clean up your code. Rather than do all the work of generating a component's shapes in a single method, break it down into multiple methods.

3. Draw some of your piece's shapes using loop or using recursion. This could allow you to make parametric Emoji.