Making Lemonade

Let me posit a new law of the land: actor classes should never contain movement logic. Over the years I've followed this as a rule of thumb, but much to my regret, in my python dungeon crawler -- since I didn't quite know where the code was heading nor exactly the implications of using python -- I quietly bowed to the tyranny of the actor that does everything.

Don't go there. It's the dark side....



Turn towards something different. Call it MVC, call it narrow encapsulation, call it one of the most important design choices you can make in your game's architecture: get movement out of your actor class, remove behavior of all kinds.

Your object-orientated instincts -- especially if, for some reason that I have yet to put my finger on, your background is in C++ -- might tell you: if an object can take an action, then that action should be a method on the object in question.

Take whatever book you read that in and burn it.

Lemons are objects; making lemonade is not an object.

Before I get into this too deeply, I should explain: by object here I don't mean class. Conceptually, by object here I mean: it has a real world physical analog. It's an object in the sense that your non-programming friends would understand.

Behavior may be a class, but is not an object.

Take the questionable lemon. You can't get away from this new law of the land by simply moving your "squeeze" function to the lemonade stand. Try it and the police are already at your door.

The lemonade stand is an object. The person making the lemonade? An object. The lemonade itself? You guessed it: an object.

Making lemonade? Not an object.

So what should an object contain then anyway if not the methods that give it character and life? Honestly: I'd suggest radicalism. Overcorrect, rather than under correct. Save yourself lengthy legal arguments. Head back towards C and Plain-Old-Data structures.

To be on the safe side: the essential properties and attributes of the conceptual object should go in your object class -- and nothing else. I'm not arguing for truly pure POD structures -- so I'm not saying only your essential member variables -- but rather those variables and the bare minimum number of methods necessary to expose those to the rest of your game.

As an example from a basketball game. Your actor might have the variables "height off the floor" and "current speed" and it might use those to expose the properties: "isRunning()" and "isJumping()". But, just because you can put the "jump()" method in your Actor class doesn't mean you should.

In order for your code to live a long and healthy life -- you really want to wind up in a situation where a single code base could possibly be reused multiple times. If your actor, for instance, gets a "shootHoop()" method -- you are not going to want to reuse that actor class for a hockey game. Now, if perhaps you aren't interested in that level of reusability, consider the following much more likely case.

You are two years into the development of a new first person shooter and suddenly your designer says to you: I really need the player to drive a car in this part of the game. If the only tool available to you is to add "steer()", "accelerate()", and "brake()" to your human actor object class -- I can guarantee you are going to have some long sleepless nights ahead of you. In this case, your actor class is probably already several thousand lines long, and to add even simplistic driving, its going to become several thousands more. Even if you can shunt most of the code of into a car class, your main human actor will be inextricably bound up to that car, and the number of dependencies between states within these two classes will start to give you nightmares once you can grab some shuteye.

As a programmer you might feel inclined to blame design for not letting you know 2 years ago you might have car driving as a one off in your game -- but the reality is: that's just game development. Your code has to be able to cope with radically shifting needs. Separating behavior and the objects behaviors operate upon will help get you to that point.

"Object-oriented" does mean the language orients -- focuses -- you on using objects... just don't let it imprison you there.

0 comments: