Face, has two eyes, a nose, and a mouth. Also, the eyes probably each have a pupil.
How can I best represent the face? I might want it to be a circle. Well, GP doesn't have circles, but it does have ovals, so I can use one of those with the dimensions being equal. I can do the same things with the eyes, and maybe the pupils. The nose can be a square, which is a rectangle with equal dimensions. Finally the mouth can be an oval that is stretched along the horizontal axis.
Well, the face seems to be the thing that is most important, and the other stuff should stick with it, so I think that I'll have the face contain the eyes, nose, and mouth.
Well, this is pretty thought out, let's start coding. . .
I'm gonna start with the small stuff, so the first thing is gonna be my pupil class. That's just a GP.Graphics.FilledOval that's pretty small and black, so I'll set the color and size for now, and I'll let the eye take care of positioning it. I just realized that my GP.Graphics are gonna need a container, and I don't know what that's gonna be yet, so I'll just use a GP.Container and let polymorphism do its thing. Ok, so now I'm actually thinking that I'll let the eye decide the size of the pupil so that it can remain proportional, so if I change the size of the eye, I don't need to worry about changing the pupil as well. So I'm gonna comment out the SetSize call. It compiles, so now I'm ready for the eye class.
An eye is gonna contain the pupil, but other than that, it's pretty similar to the pupil. However, I am gonna set the size of the pupil to be the eye's size/5 so it is 1/5th the size of the eye. I'll use an int just to keep the numbers round. And I'll try to position it in a way that can move with the eye, being just slightly below the center of the eye. Here we go. . .
Now, I'm realizing that I'm gonna need a way to set the position of the eye. At the same time I'm gonna need to position the pupil, so I better have a method that takes care of both of them at once. GP.Graphics have a SetPosition method that takes a GP.Attributes.Position, but how about I use one that takes two ints, then I can simply call the normal SetPosition methods on myself and the pupil. Cool? Let's see what happens. Well, looks like it should work. Let's move on shall we?
How about the nose? A GP.Graphics.FilledRectangle of equal sides sounds good to me. We'll make it black too. (Oh, I made the eyes blue.) We'll have the size and position set by the face, so it's really going to be super straight-forward.
Ok, now it's time for the mouth. It can be a GP.Graphics.FilledOval that will be stretched by some amount. I think we'll let the Face decide this as well, so it can change expression pretty easily. Cool?
Now we're ready for the face. Like we said before, it's gonna contain two eyes, a nose, and a mouth. I'll also need to set the position of everything, I'm gonna do it here instead of the applet. I think that the positioning and sizing will take some experimentation, but nothing too special. It compiles, so let's finish with the applet.
All the applet has to do is new a Face, so we put that in and we are set. Let's try running it and see what we get. Hmm, the placing and sizing of everything is a lot of stuff. Maybe it'd be better if I broke that stuff into two methods. Ok, so now my face has a SizeEverything method so everything that I want to size is in the same method, and the same for a PlaceEverything method. Ok, now everything is placed right, but I'm missing the pupils for the eyes. Oh, I realized that I'm calling the SetPosition method on the eyes with a GP.Attributes.Position and I need to do it with two ints, because I creted that method. I think I'm gonna also have to do that with the Size method, because otherwise the pupils get sized at the wrong time and will have the wrong value. So that took a a whole lot out of the constructor of the eye, and moved it to the various methods. The eye is also no longer storing its size as an instance variable. This took a lot of code out of pupil as well, so now the eye is really controlling all of it. Let's see how this does.
Ok, I had to tweak some of the numbers to make it look right. But now it's done and I have the face of a snowperson. Pretty cool. The only compromise that I had to make is that the pupils are no longer positioned proportionally to the eyes, they are simply 10 pixels below the position passed in to the eye. This is bad and not extensible, but I have no way of knowing whether the size of the eye was done first or the position. So it's a chance I have to take. A nice exercise might be to think of ways that I can resolve this issue.
If you have any questions on this, mail me at firstname.lastname@example.org.