
Emoji Drawing
Learning goals
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.
Libraries
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.
The big idea: using objects, using abstractions
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? Remember that there can be many objects of a single class!)
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.)
The syntax and the terminology
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
-
declare
felix
“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
-
instantiate a
Cat
object
“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
-
assign … to
felix
“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
- declare and initialize a variable
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
-
call the
meow
method offelix
“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 namedfelix
, 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.
Let’s make emojis!
- Open and run the
Emojis
class. You will see three smiley faces — but they’re missing the eyes! (Creepy!)
-
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
andArc
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:
- Once you have that working, write some new methods that are similar to
createSmiley()
but draw different faces. Note thatcreateSmiley()
must continue to work; you are making new methods for new faces! That means that you should ensure your main method continues to testcreateSmiley()
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 |
---|---|---|
![]() |
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. |
![]() |
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: Look at the startAngle parameter.
|
![]() |
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: How does createSmileyFace do it? 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:
- Find an HTML color picker, such as this one
- Find a color you like
- Copy its 6-digit HTML hex code, e.g.
#2438CB
- Replace “
#
” with “0x
”, e.g.0x2438CB
- 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!