Today we will be taking a little bit of a detour from the code we've built the last two lessons in order
to discuss some important considerations in the design of our Engine.
In my synopsis of the goals I had
hoped to achieve for this workshop, I mentioned phrases like polymorphism, inheritance, encapsulation, and
modularity but I didn't explain very much about them. Today I would like to focus on these key terms, discuss how they apply to us as programmers -
specifically game programmers - and how this will eventually effect our design choices for this engine.
What does Object Oriented mean exactly?
When we discuss Object Oriented programming, it is important to also note the other styles of programming
in order to really appreciate how this methodology helps us work on such vast projects such as games. Let
me describe other styles of programming before I come back to OOP (object oriented programming).
Unstructured Programming (UP) is how most people begin learning how to program. I know it's definitely
where I started! The best way to describe UP is by pointing out the very popular "Hello World" program, the
humble beginnings every programmer started at =].
In a UP there is only one function ( ie. the main( ) ) and
all the data in the program are exposed to this function (are global). All of the functionality of the program
is implemented directly into this single main function.
Procedural Programming (PP) is the next step in the evolution of languages. It introduces the idea
of encapsulating specific functionality into a separate block of code, and giving the ability of any
function to call another function.
As you can see, this gives rise to the idea of reusability, or
enabling a program, indeed multiple programs, the ability to reuse functions without rewriting them. The value
of this is self evident. It prevents dev teams from "reinventing the wheel" so to speak, and focus on the unique
aspects of their project.
The term
encapsulation means that we build an entire function that performs many operations but has a predefined result.
For example: I write a function for an object that draws it to the screen, and name it Render( ). Because I've
encapsulated this function, other members of the dev team shouldn't need to know what happens inside this function
in order to use it. At first this may seem obvious, but it becomes extremely important when you start designing
your engine.
You want to make sure to build it in such a way that you can encapsulate (effectively make a black
box) out of what you are coding, so other members of your team don't need to learn what you did. This allows
a dev team to effectively specialize, or, gives the ability for each of us to become masters of our particular
domain. In the game we develop, for example, I may be asked to encapsulate all of the graphics routine,
while Churroe is asked to develop the sneak system.
As you can see both of these features are unrelated to one
another, proper encapsulation would allow both Churroe and I to work on our respective parts of the engine
at the same time without causing conflicts, and being wholly unaware of what the other is doing. This is good engine design,
and it is also pretty much the textbook definition of modularity.
Object Oriented Programming is the next step in the progression, allowing the programmer all of the functionality
of the previous programming paradigms with some new advanced features: modularity, inheritance, and polymorphism.
Lemma 3.1 - Key Concepts of OOP
While I may touch upon and relate many of the concepts of Object Oriented Programming to the task at hand, it might be good to see
it in it's more pure form, one not specifically spoken in the context of video games. Also, because this workshop
is designed to be a quick introduction and by no means an all expansive tutorial, I would recommend the good students
to seek more information about object oriented programming and direct your browsers
here
Modularity
Modularity is one of the most basic tools in any OOP programmers toolkit. The concept of modularity builds off of
the programming paradigm of structured programming, where blocks of code are separated in order to both encapsulate
their functionality and provide a high level of reusability. Modularity adds to this by both pairing functions with
their own data set.
Example 3.1 - Modularity
Consider the following example: You have a game of pac man, and you want to have 5 ghosts on the screen. Without
modularity you would be forced to keep 5 sets of data available to the various functions. You can imagine having
all the images, positions of the ghosts, AI states all in one lump could get very confusing and error prone. What
modularity allows you to do is encapsulate each ghost into a single module, or object: