The Shoulders of Giants: LensManagers

This is part 1 in a hopefully-ongoing series about videogame programming techniques I’ve acquired over the past several years. Broadly, it’s intended to help you solve common problems you encounter in your daily game development life. Yet rather than merely throwing a github or Asset Store link at you, my goal is to present a comprehensive programming style: how to think about the problem, why to think about it this way, and ultimately how to attack similar problems with valour and grace.

I once read a Gamasutra post describing something called ‘The Curtain Problem’. Here’s the basic idea: you must program a big Broadway-style stage curtain for the videogame you’re creating. You’ll use this curtain firstly as a loading screen: closing it whenever it’s time to unload the previous scene, then reopening it once the new scene has loaded. Yet your level designer is musing about reusing this curtain for dramatic effect at various points during the middle of gameplay. (Your antagonist, it turns out, is an underground R&B idol called ‘The Bleaknd’ who changes outfits often; it would be cool if each outfit swap caused the curtain to close and reopen around him.)

Had you brought this problem to an entry-level programming class, you’d inevitably find yourself staring at a projector slide with the following text on it:

public class Stage
{
    public bool IsCurtainClosed = false;
}

The very first thing universities teach us about object-oriented programming is that this variety of public member access is, for some reason, sinful. Yet it’s difficult to explain to a novice programmer precisely why this is the case. In the land of C# and Unity3d, the first thing your professor would do is show you the ole’ getter & setter pattern:

public class Stage
{
    public bool IsCurtainClosed
    {
        get
        {
            return _IsCurtainClosed;
        }
        set
        {
            _IsCurtainClosed = value;
        }
    }

    bool _IsCurtainClosed = false;
}

It’s apparent to the student that this code snippet is functionally identical to the previous one, except that it’s many lines longer and, therefore, much harder to write correctly on the back of the handwritten exam Your professor is preparing to give you. They explain that this technique entitles you to a fresh and steamy mound of OOP shit™, which smells strongly of a thing called ‘encapsulation’ (best remember this one for your first job interview). The two of you soon arrive at something like:

public class Stage
{
    public bool IsCurtainClosed
    {
        get
        {
            return Controller.IsLeftCurtainClosed && Controller.IsRightCurtainClosed;
        }
        set
        {
            Controller.SetLeftCurtainClosed(value);
            Controller.SetRightCurtainClosed(value);
        }
    }

    CurtainController Controller = new CurtainController(true, 0.5f, false);
}

This snippet, unlike the previous one, rises above complete pointlessness. It’s sort of neat that you can tell ‘Stage’ to open or close the curtain without needing to know what CurtainController is or what it’s doing. It’s sort of helpful that CurtainController is inaccessible from outside the Stage, and therefore has only one thing feeding it commands. You could probably reuse CurtainController somewhere else—perhaps as part of some other class—though you’ll probably never need to.

Inevitably, the very next problem you’ll encounter shall concern the sharing of control. What if your antagonist is frenemies with a local rap superstar (notorious, it turns out, for ‘runnin through the Styx with his ghosts’)? What if both characters need to open and close the curtain at arbitrary intervals? What if there were four characters, or six, or twenty?

Read more…