Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm desiging an HTML5 2D game engine in Javascript, and currently, I use the singleton pattern.

There is only one global object in the namespace called simply Engine. All other objects are instantiated through this one, for example:

var scene = new Engine.Scene();
var renderer = new Engine.Renderer();

This works great, but I started expanding and actually adding methods to the Engine object, not just classes (on a conceptual level, I know that they're technically different).

Now, the Engine object has an update() method, which should be called by the user (game) each loop, and some other properties such as updates per second, etc. Different objects (scenes etc) register some of their own update methods to the Engine.update() method, which just serves to call them.

What are the dangers of a such design? I've heard many people badmouthing the singleton design pattern, does it apply here?

share|improve this question
3  
Would you use global scope variables all over your code? Because that's what singleton pattern introduces: global state within objects. Maybe watching this lecture would help. –  tereško Jul 16 '12 at 22:54
add comment

2 Answers

up vote 4 down vote accepted

Unless you plan on running two separate games in the same page then a singleton naturally makes sense.

With that being said, it does introduce the issue of constantly referencing global variables. For a minor course on why this is an issue you might check out this article but I would really suggest reading Nicholas C. Zakas's High Performance Javascript.

The basic rundown goes a little something like this: say you've got some arbitrary function

function RunGame() {
    var player = new Player();

    alert(player.position.x);

    for(var i = 0; i < 5; i++)
         document.write(Engine.ToString() + "<br />");
}

Obviously the function is nonsense but pay attention to the scoping here. Whenever JS is looking for a variable, it starts with the inner-most scope first before heading outward. So getting the player is no big deal, the JS engine just says Hey, the player is right here, I don't need to look any farther. But when you're referencing things out of scope, like the Engine or even document, it still has to see if those are local variables.

If you look at that horrible for loop that you should never consider doing ;) it references document five different times and each of those times it has to check the local scope, any outer scope (say if this function was a part of some larger object), so on and so forth until finally getting to the global scope. All of a sudden, referencing the same object takes a lot more operations. This effect can be lessened by making references in the local scope (which I suggest you always do if a variable is used more than once)

function RunGame() {
    var player = new Player(),
        doc = document;

    alert(player.position.x);

    for(var i = 0; i < 5; i++)
        doc.write(Engine.ToString() + "<br />");
}

But this still means you have to make that extra leap to global scope every time you generate your local variables. So it really depends on how intense you believe your game will be and how lazy you feel like being ;)

share|improve this answer
1  
Could that not be extended to include an engine variable in local scope too? –  Quasiperfect Jul 17 '12 at 4:45
    
Thanks, very informative! –  akled Jul 17 '12 at 4:51
    
@Quasiperfect Sure, you could start storing local references to the engine in all your game objects to reduce lookup time but then you start filling up the memory quicker. Just depends on what kind of trade-off you want to do. –  Mike C Jul 17 '12 at 5:21
    
@MikeC: (although it's entirely possible that I have no idea of what javascript is doing) Surely you're only creating another pointer to the engine, the size of an int (or rather, size_t)? It's true for python, (and I imagine it's true for JS too) that every dot in the identifier increases the time required to look it up. In optimizing big loops and oft-repeated functions, things more than three levels deep should probably be declared outside, either on a local or class level. –  Quasiperfect Jul 17 '12 at 13:56
1  
@Quasiperfect You're completely right that it's essentially a pointer (I imagine it's only the size of an int but I'm not sure) and that in the grand scheme of things, it's probably not a major difference. But it is something to consider and something I should address in my answer is how having multiple discrete objects modify a central core of data can cause strange, hard to track bugs. But the question seemed (in my mind) to be asking what performance problems can come from global scoping. –  Mike C Jul 17 '12 at 14:25
add comment

This answer provides many problems that are often a result of using global state, as well as some alternatives. Since a singleton has the same problems as global state, it applies here. The biggest issues caused are:

  • Bugs from mutable global state (It can be hard to track down who changed what, if everyone can change anything).
  • Poor testability (In your example, you have to rely on monkey-patching Engine in order to test that code).
  • Unmanageable code (Refactoring can be difficult when you have a hundred dependencies)

If you use a technique like Dependency Injection, making your singleton immutable, or passing dependencies by function parameter, you can reduce the dependency and make things easier to test, refactor, and manage.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.