In the world of game development, the concept of Object-Oriented Programming (OOP) is a fundamental pillar that shapes the structure and design of games. It’s like the architectural blueprint for a building, providing a clear and organized plan for construction. In GameMaker Language (GML), the concept of OOP is embodied in the use of objects, which are the building blocks of your game. This article will delve into the essence of OOP in GML, explaining it in a simple, relatable manner with analogies and code examples.
The Concept of Object-Oriented Programming (OOP)
Imagine you’re a chef, and you’re about to prepare a meal. You have a recipe in front of you, which is a set of instructions on how to prepare the meal. In OOP, a class (or in the case of GML, an object) is like that recipe. It’s a blueprint or a template that defines how a particular element in the program should behave. It contains a set of instructions (methods) that dictate what happens under specific circumstances.
Now, when you follow the recipe and prepare the meal, that meal is an instance of the recipe. Similarly, in OOP, when a class is instantiated, it becomes an object (or in GML, an instance). Each instance is a unique manifestation of the class, capable of having its own properties and behaviors.
Objects and Instances in GML
In GML, an object is a piece of code in your game world and may be programmed to do a variety of things, ranging from simply occupying space in order to prevent the player from advancing along a path to being as complex as a programmed enemy with hundreds of lines of code to give it a small amount of artificial intelligence. Objects are commonly represented with sprites, though they may be rendered invisibly by not selecting a sprite for them.
An instance, on the other hand, is an actual physical representation of an object within the game world. Whereas the object is the piece of code which provides the template for how a given instance acts, the instance is the actual thing with which a player interacts.
For example, in Super Mario Bros. there was only one Goomba programmed. It was programmed to walk left until it fell down a hole or got squished by the player. The actual Goombas that Mario is interacting with when he’s running through World 1-1 are instances of that original programmed object.
Object Inheritance in GML
In the world of OOP, inheritance is a mechanism that allows one class to acquire the properties and methods of another class. It’s like a child inheriting traits from their parents. In GML, this concept is embodied in the parent-child relationship between objects.
A parent object in GML is like a general recipe that can be used to create a variety of meals. For example, you might have a general recipe for a salad, which includes lettuce, tomatoes, and dressing. This is your parent object.
A child object, on the other hand, is like a specific variation of the general recipe. For example, you might have a specific recipe for a Caesar salad, which includes the general salad ingredients (lettuce, tomatoes, and dressing) plus Caesar-specific ingredients (croutons, Parmesan cheese, and Caesar dressing). This is your child object, which inherits the general salad ingredients from the parent object and adds its own specific ingredients.
In GML, you can set an object to be the parent of another object, which means that the child object will inherit all the events and actions of the parent object. This is useful for creating variations of a general object, such as different types of enemies or power-ups.
Here’s an example of setting a parent object in GML:
// Set obj_enemy as the parent of obj_boss
obj_boss.parent = obj_enemy;
In this example, obj_boss
is the child object, and obj_enemy
is the parent object. obj_boss
will inherit all the events and actions of obj_enemy
.
Overriding Events in GML
In OOP, overriding is a feature that allows a child class to provide a different implementation of a method that is already provided by its parent class. It’s like a child choosing to pursue a different career path than their parents, even though they’ve inherited the same basic traits.
In GML, this concept is embodied in the ability to override events in child objects. If a child object has the same event as its parent object, the child object’s event will override the parent object’s event. This means that when the event is triggered, the child object’s event will be executed instead of the parent object’s event.
Here’s an example of overriding an event in GML:
// In the parent object (obj_enemy), define a Step Event
if (health <= 0) {
instance_destroy();
}
// In the child object (obj_boss), override the Step Event
if (health <= 0) {
// Play a death animation before destroying the instance
sprite_index = spr_boss_death;
alarm[0] = sprite_get_number(spr_boss_death);
}
In this example, when the health of an instance of obj_boss
reaches 0, instead of immediately destroying the instance (as defined in the parent object obj_enemy
), it plays a death animation before destroying the instance.
Understanding the concept of OOP and how it’s implemented in GML is crucial for creating complex and interactive games. It allows you to create a hierarchy of objects, reuse code, and customize behaviors, making your game development process more efficient and your games more dynamic. In the next part of this series, we’ll delve deeper into the power of OOP in GML, exploring more advanced concepts and providing more complex code examples. Stay tuned!