A grid of emojis showing different facial expressions

Emoji Drawing

Today you are practicing :

  • Using objects by instantiating them, passing messages to them (a.k.a. calling their methods), and sharing them between different pieces of code
  • Breaking code into smaller pieces using method decomposition
  • Creating graphics with the Kilt Graphics library
  • Using local coordinate systems to organize graphical interfaces

Be sure to commit and push your work to share your code with your activity partner today. You will both need the emoji(s) you created for the next take-home exercise! Your partner can clone/pull after you push.

In programming, a library is reusable unit of code that is not a whole program in itself, but is instead designed for many different programs to use. Programmers share libraries with each other, and there are thousands of libraries available online to solve common (or uncommon!) problems. Each library focuses on some particular set of related problems or tasks. There are libraries, for example, for doing statistical analysis and creating animations in video games and generating music. One example of a library you are already using is JUnit, which focuses on automated testing of code. Including the JUnit library is what lets you write @Test in your test code.

We faculty at Macalester have created a graphics library for Java called “Kilt Graphics” (because Scots wear kilts, and kilts are cool). The Kilt Graphics library is focused on creating graphics and user interfaces in a teaching context. We designed it to be just robust enough to build cool things in Comp 127 and 128, but simple enough to be a good teaching tool. The libraries that people use for building full-scale apps are quite complex. They can be overwhelming and messy, and they do not always do a good job of illustrating fundamental programming concepts. Kilt Graphics is not a good way to build an app for releasing to the public, but it is a good training tool for building the cognitive foundations you’ll need to learn and use those more complex libraries well.

Kilt Graphics provides classes that you can use in your code. They have names like Rectangle and Ellipse. Each object of one of those Kilt Graphics classes represents some shape that you could put on the screen. (But wait! If there is only one Ellipse class, what if I want to draw two ellipses? )

Kilt Graphics also provides a CanvasWindow class. In Kilt Graphics terminology, CanvasWindow is a window that appears on the screen when the program runs, and which acts as a blank canvas on which you can draw shapes. To make a shape appear on the screen, you add it to a CanvasWindow:

// Create a window that is 800 pixels wide and 600 pixels high:
CanvasWindow canvas = new CanvasWindow("Happy Window", 800, 600);

// Create a rectangle whose upper left corner corner is at (50, 10),
// which is 100 pixels wide and 100 pixels tall:
Rectangle box = new Rectangle(50, 10, 100, 100);

// The rectangle is not visible yet! To make it show up,
// we have to add it to the window:
canvas.add(box);

How does Kilt Graphics make a window appear? How does the code know which pixels on the screen to change to black or white to make a rectangle?? What do all the pixels of a window look like: the border, the little button at the top??!? Guess what! You don’t know. You don’t have to know. That’s not your code’s job.

This is the beauty of abstraction: if you understand what a good abstraction provides to you, what it accomplishes, what promises it makes…then you don’t have to know the details of how it works. As you learned in the previous reading, this separation between how to use an abstraction and how the abstraction works is encapsulation. We have words for both sides of that split. The rules for how other code uses the abstraction are its interface or API (application programming interface). The details of how it works are its implementation.

Software development mostly consists of understanding abstractions that other people have created for you, and using those abstractions to solve your problem. (Software development also consists of creating your own abstractions as your code grows — but today we’re focusing on using other people’s abstractions.)

In this activity, the code you will read and write does a surprising number of different things with just a few basic building blocks, listed in the table below. Study this table carefully! This syntax and this terminology is ubiquitous, in this course and beyond.

Java syntax

What it’s called

What it means

Cat felix

  • variable declaration (n)
  • declare felix (v)

“Here is a new variable named felix. This variable could point to any object that is a Cat. It doesn’t point to any object yet, but it could!”

new Cat()

  • object instantiation (n)
  • instantiate a Cat object (v)

“Create a new object that is a Cat. The object didn’t exist before; now it does. No variable points to it…yet.”

felix = …;

  • assignment (n)
  • assign … to felix (v)

“Make the felix variable point to whatever the expression on the right-hand side gives us. The declaration of felix above says the variable can only reference Cat objects, so please make sure that expression is guaranteed to give us a Cat.”

Cat felix = new Cat();

  • variable declaration with an initializer (n)
  • declare and initialize a variable (v)

All of the above at once: “Here is a new variable named felix. Create a new object that is a Cat, and make the felix variable point to it.”

felix.meow()

  • method call (n)
  • call the meow method of felix (v)

“Find whatever object felix currently is pointing to, and ask that object to meow / send it the meow message.”

Spot these building blocks in the code, and practice using the proper terminology to describe them out loud as you work with your partner:

❌ “Now type ‘Cat felix equals…’”

✅ “Let’s declare a Cat variable named felix, and initialize it to…”

The extra words are worth it: they will allow you to communicate better with other developers, construct better web searches for your programming questions, read documentation better, and more easily transfer your object-oriented programming knowledge to new languages.

  • Open and run the Emojis class. You will see three smiley faces — but they’re missing the eyes! (Creepy!)

Three yellow circles containing red arcs that represent smiles, but no eyes

  • Don’t add any code yet! Study the existing code in Emojis first, and try to understand how it works. Things to note:

    • There are several methods. Each one has a specific job. Some methods call other methods. Which call which? What is the method dependency structure?
    • This code uses the graphics classes Ellipse and Arc to make the shapes you see. What methods do those classes have? Where does the emoji code call the constructors for those classes, and what parameters do the constructors take?
    • This code also uses a class called GraphicsGroup. Where does the code use it? What does it do?
    • Here’s the tricky one: The main method creates three different smiley faces, with three different sizes and positions. How does the code make the sizes different? How does it make the positions different? Those two questions have very different answers! Once you’ve figured out that difference, then you are ready to add code of your own.

      • Hint: If you have a theory about how the code works, run an experiment! Change the code a little in a way that depends on your theory, and see if your theory holds. To make everything go back to the way it was in your most recent commit, go to GitHub Desktop, right-click a file, and choose “Discard Changes.”
  • Now that you understand how the code handles sizing and positioning parts of faces, add eyes to the emojis by writing a createEye(size) method. Note “eye” singular: your new method will only make one eye. You will call it twice (where?), putting the resulting eyes at different positions. The result should look something like this, but you’re free to use your own artistic judgment:

Three yellow circles with smiles as above, each now with two black dots for eyes

  • Once you have that working, write some new methods that are similar to createSmiley() but draw different faces. Note that createSmiley() must continue to work; you are making new methods for new faces! That means that you should ensure your main method continues to test createSmiley() even as you test your other new kinds of faces too.

You may also add enhancements to the existing faces, but please make sure you create at least one additional kind of face first. Here are some suggestions to get you started, but you are free to use your own imagination too:

Image Method Hints
A face similar to the smiles above, but with the right eye replaced with a horizontal line to resemble a winking eye createWinkingFace() Most of this method will look just like createSmileyFace(); only one of the eyes is different. For the parts that are the same, you can call the same methods that the smiley calls.
A similar face with the arc of the mouth vertically flipped to resemble a frown createFrownyFace() You can copy createSmile() to make a new createFrown() method, and change just a tiny bit of code. Finding that tiny bit of code may be tricky! Study how it creates the arc. Read the API documentation for Arc’s constructor to understand its parameters. Big hint:
A similar face with small white circles inside the block pupils, showing the reflection of light on the eyes Add irises and ocular highlights to createEye() The tricky part here is that eyes are no longer just one ellipse; instead, there’s an ellipse for the dark part and a second ellipse for the highlight. But you still want createEye() to return one object for the whole eye. How can you do that? Hint: Study how createHead() uses stroke color and width. You can use that for the iris color.

Hint: Want a different color? You will see a list of colors at the top of the class. You can add a new color of your own to those constants:

  1. Find an HTML color picker, such as this one
  2. Find a color you like
  3. Copy its 6-digit HTML hex code, e.g. #2438CB
  4. Replace “#” with “0x”, e.g. 0x2438CB
  5. Add a new constant and pass the code you copied as an argument to Color’s constructor, just as with the existing colors

Have more time? Create more elaborate faces! See top of this document for inspiration.

We don’t necessarily expect that you will finish every part of this activity during class time. Do as much as you can during class, and if you want more practice, do some more of the activity on your own time. It is always up to you how much of each activity you complete.

However, you will need at least two emojis for the next take-home exercise. We will give you some emoji code if you didn’t get a chance to finish during class today — but of course it’s more fun to use your own emojis!