A Classy Lesson on Objects

We talked about classes, objects, and instances in last week’s episode, but we thought it might be good to try a different analogy in case it helps the concept sink in for any budding programmers.

Unfortunately, GameMaker with GameMaker Language, the tool we use to make games, uses a terminology that differs from that of other programming languages, so don’t worry, we’re not going to frame anything in GameMaker language until the very, very end to avoid confusion.

We’ll go deeper and deeper into objects, so feel free to stop at whatever level you feel comfortable.
Maybe come back later and try to level up when you’ve got enough programming XP if that helps.

First, the motivation.


LEVEL 1

Why are objects worth studying?

Objects were an innovation that helped make code more modular (more “cut-and-pastable”) and more logical. If you use objects, you can group related things together, like functions, variables, definitions, etc. It also allows them to be self-contained – they aren’t linked to information in other places, so if you make a change elsewhere, it doesn’t affect the object.

So why is that a good thing?

When things can be grouped and kept self-contained, it means mistakes are limited to one area.

It’s like the difference between one giant, dry forest and several small dry forests separated by a lot of dirt. If a fire starts in the giant forest, the whole thing could burn down, and stopping the fire after it has begun is extremely difficult. With the small forests, you can focus your firefighting efforts, or, at worst, you could just let the little forest burn down and replant.

Another analogy is trying to build a tower of blocks. With objects, you can build 10 towers with 10 blocks rather than 1 giant tower with 100 blocks.
Which would you rather pick up after when the wind blows?


LEVEL 2

Alright, so what are objects?

Objects require an understanding of two things: classes and objects. Don’t worry, the concept itself isn’t high-tech; it actually goes back at least as far as ancient Greece and philosophy.

A class is an idea. An object is a thing. That’s it. Easy, right?

A class is a “table”. An object is the “table in your dining room with the warm Coke sitting on it that you keep banging our foot on”.
A class is a “gun”. An object is the “Eliminator 9000 you’re holding in your hand which is currently reloading and holds 2 rounds”.

Classes, or ideas, are useful. They give you some general information about the way something should work.
A gun should be able to shoot, at the very least. A gun class might look something like this in pseudocode:

Class Gun {
variable bullets
variable reloading

function shoot()
}

The gun class has variables, or data, that can describe how many bullets it has or whether or not it is reloading, and it has a function for shooting, but that doesn’t tell you anything about a real world “thing”.

Objects are those real-world “things”. The Eliminator 9000 we’re holding in our hands fills in the information.
It says: We now have 2 bullets, and reloading is true.


LEVEL 3

So what’s this parent and children stuff I keep hearing about?

We won’t let this get complicated yet, promise. The Greeks could figure it out, so can you.

Ideas can be vague or specific, and they can be related (like parents and children). That’s it in a nutshell.

A larch is a tree, a tree is a plant. A larch is also a plant.
A gun is one idea. A tree is another. They’re not related (unless you made a wooden gun…)
A gun is one idea. A shotgun is another. They ARE related. A shotgun is a kind of gun. Or, a shotgun is a more specific kind of gun. In other words, it’s like a child of Gun on the Gun family tree.

If you think about the family tree of guns, at the top is “Grandpa Gun”, who gave birth to “Shotgun Dad” and “Uncle Machinegun”. Shotgun Dad gave birth to little “Eliminator 9000”.
Eliminator 9000 is also a shotgun, and it’s also a gun.

Wait, wasn’t the Eliminator 9000 an object?

Nope. The Eliminator 9000 IN OUR HANDS, RELOADING, and HOLDING 2 ROUNDS is an object. But your opponent’s “ELIMINATOR 9000 in his hands, aimed at your face with one round chambered” is also an object. They’re both instances of an Eliminator 9000 class.

An Eliminator 9000 is a very specific idea, but it’s still just an idea, a class, until you pick one up at Wallmart.


LEVEL 4

Kind of get it, so how does this help with programming?

If you decide you want the Eliminator 9000 to shoot faster, you only have to change things in the Eliminator 9000 class (change things about the idea), and all of the specific Eliminator 9000 objects in the world are changed to compensate.

Say you wanted the Eliminator 9000 to have a super blast feature, you could do something like:

Class Eliminator 9000 son of Shotgun grandson of Gun {
variable bullets //courtesy of Grandpa Gun
variable reloading //courtesy of Grandpa Gun
variable bullets_per_shot //courtesy of Shotgun Dad
variable super_blast

function shoot() //courtesy of Grandpa Gun
function super_blast() //brand new
}


LEVEL 5

Why do I need a super_blast? Can’t “shoot” do that?

Yes it can. And this is where we get into something called overriding. Eliminator 9000 can overrule Shotgun Dad and Grandpa Gun like a proper teenager by doing this:

Class Eliminator 9000 son of Shotgun son of a Gun {
variable bullets //courtesy of Grandpa Gun
variable reloading //courtesy of Grandpa Gun
variable bullets_per_shot //courtesy of Shotgun Dad
variable super_blast

function shoot()
{
super_blast() //!!!
}
}

Every gun has a trigger that causes it to “shoot()”, but now the Eliminator 9000’s trigger causes it to fire a super blast.
Same trigger, different reactions.

The Eliminator 9000 child has overriden the parent, and all it had to do was hide what it wanted to in the same name: “shoot()”.
If the child doesn’t want to override shoot(), it behaves the same way as the parent’s shoot, but if the child decides to override it, its version takes priority.

Just in case, let’s throw in another analogy. All humans have a “dance” function, but the Eric human overrides the dance function with something pretty lame, while Michael Jackson overrode it with something great.


LEVEL 6

Drat, something went wrong with all of the Eliminator 9000s in the game, what do I do?

Well, if the gun is working and the shotgun is working, the blame falls at Eliminator 9000’s feet, so we only have to look at one place: the Eliminator 9000 class to fix the problem.
That beats scouring the entire program for the bug!

If we didn’t have a gun family, we might have to look everywhere for the source of the problem. (the way the player uses it? the way bullets are initialized? who knows)

Remember the whole not burning down the forest thing? This is it. This is why objects can make code easier to manage.


LEVEL 7

Is that all classes and objects are good for?

Nope, there’s another thing.

If we do get Eliminator 9000 working and want to use it in the sequel, or we want to give it to a friend to use, we know it works, so we just have to copy it over as-is.
The sequel, or your friend, can decide to change when the gun shoots, but when the gun shoots, it’ll do what it always does.
That beats making a new Eliminator 9000 every time…

And that’s the other thing that makes object-oriented programming so useful.


LEVEL 8

Hmm, but what if I don’t want to let my friend to change the number of bullets it has?

We’re going to go down the object-oriented rabbit hole from here. If you’re cool with what you’ve learned so far, stopping here for to grab XP might be good.
Otherwise, let’s press on.

So, you want to make sure nothing outside the Eliminator 9000 itself can change the number of bullets…
We have to get into the concept of scope, but there is a way. Once you understand how scope works, it’s easy.

In most object-oriented languages, and many scripting languages, there are ways to say “I want this to be publicly available for anyone to change,” or “I only want to protect this for children to be able to change this if they use it,” or “I don’t want anyone to touch this, it’s private.”

In fact, for a lot of languages, those are the keywords: public, protected, private.

If we say “private variable bullets”, then nothing but the stuff inside the Eliminator 9000 can change or even see the number of bullets. If the Eliminator 9000XYZ tries to see the number of bullets, it’ll fail. If we want the Eliminator 9000XYZ to also see bullets, we should say “protected variable bullets”, and if we want every Tom, Tree and Harry to see the number of bullets, we can make it “public variable bullets”.

All of the public, protected, and private stuff works for functions too.


LEVEL 9

That sounds like a hassle, why not just make everything public?

Sure, why not leave a gun with its bullets lying around so that anyone can grab it? Wait…

While you could theoretically do that, if you want to get into good object-oriented programming habits, you’ll want to keep the number of hands in the Eliminator 9000 cookie jar to a minimum because every one of those grubby little paws can cause problems. Most of our time debugging in GameMaker comes from those grubby little paws.

But we don’t have a choice in GameMaker Language, it isn’t really designed to be an object-oriented programming language like C++. If we had the options available in C++, we could keep the Eliminator 9000 nice and safe behind a fortress of locked doors that require anyone wanting information to knock first.

Those door knockers are accessor functions. If instead of leaving our “variable bullets” flapping in the breeze for anyone that wants to fiddle with them, we take control of the information with accessor functions, we can give everyone just the right amount of information they need to do their job without letting them break our gun.

For example, instead of this:
public variable bullets;

We do this:
private variable bullets;
public function getNumberofBullets() //return the number held in “bullets”
public function setNumberofBullets() //change the number held in “bullets”

Now, anyone who wants to fill our gun with bullets can’t just go adding to variable bullets, they have to do it through our function.
And in our function, we might have something that limits the maximum number to 6 if we never want the number of bullets to go higher.
Much, much safer. Much, much cleaner. The class has control (it can stay classy).


LEVEL 10

Okay, take me back to GameMaker. What gives?

What gives is that GameMaker confuses us by using different names for what are traditionally known as classes and objects, made worse by reusing one word to mean another.
In GameMaker, “objects” are classes, and “instances” are objects.

But there’s no need to blame GameMaker, they wanted to make things as clear as possible for anyone making games. At first glance, unless someone has dealt with programming before, they won’t know what a class is, but an object, well, that’s at least a word that conjures up an image. And in programming, an object is an instance of a class, so hey, instance.

In our game, Project Skyring, obj_enemy is an enemy class, while #100079 is the instance of obj_enemy that’s about to run into the player and do damage.


LEVEL 999

I want more! What else is there?

You want more? Well, if you really want to dive down into it, look up stuff on multiple inheritance.
Here’s a hint, the rabbit in Monty Python’s Holy Grail is both a “rabbit” and a “killer” with functions and behaviors of both.


 

We hope that helps get a few of you started having fun with objects.

Leave a Reply

Scroll to Top