3
\$\begingroup\$

I wanted to implement a game in javascript with an MVC design pattern, with each entity's state stored in a model.

So for example,

In an update loop we iterate over all models and apply the velocity attribute to the position attribute of the model. A view associated with each entity/model would then receive a position changed event, and update the representation of the entity. This would happen independently of the views render method being called in a requestAnimationFrame callback.

What I found though, through a possibly naive implementation, is that setting attributes of a model is simply too slow. As much as I prefer the architecture of this code, the framerate was significantly lower.

Should I give up on using MVC for frequently updated attributes like position?

Below, I've included some code to test aspects of setting attributes of an object. The most minimal model-like behaviour, in which an attribute is set only when the new value differs from the current, and a "changed" update event is triggered, is about 10x slower than just setting attributes directly.

Output:

> test(1000, 100, 10)

object[key]: 163 ms

object[key] if changed: 172 ms

object[key] if changed & emit backbone event: 953 ms

Backbone.Model: 4043 ms

eventsBackboneCount: 100000

var test = function(creations, iterations, keyCount){
  var eventsBackbone = _.extend({}, Backbone.Events);
  var eventsBackboneCount = 0;
  eventsBackbone.on('all', function(){
    eventsBackboneCount = eventsBackboneCount + 1;
  });

  var looper = function(label, create, set){
    var start = (new Date()).getTime();

    var data = {};

    for(var i = 0; i < creations; i++){
      data[i] = create(i);
    }

    for(var j = 0; j < iterations; j++){
      for(var i = 0; i < creations; i++){
        var key = ''+(j % keyCount);
        set(data[i], key, Math.random());
      }
    }

    var end = (new Date()).getTime();

    console.log(''+label+': '+(end - start)+' ms');

    return data;
  };

  looper(
    'object[key]',
    function(id){
      return {};
    },
    function(datum, key, value){
      datum[key] = value;
    }
    );

  looper(
    'object[key] if changed',
    function(id){
      return {};
    },
    function(datum, key, value){
      if(datum[key] !== value){
        datum[key] = value;
     }
    }
    );

  looper(
    'object[key] if changed & emit backbone event',
    function(id){
      return {id:id};
    },
    function(datum, key, value){
      if(datum[key] !== value){
        datum[key] = value;
        eventsBackbone.trigger('changed:'+datum.id, datum, key);
     }
    }
    );

  looper(
    'Backbone.Model',
    function(id){
      return new Backbone.Model({});
    },
    function(datum, key, value){
      datum.set(key, value);
    }
    );

  console.log('eventsBackboneCount: '+eventsBackboneCount);
};
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

TL;DR: Typically, yes. But maybe not.

Javascript MVC frameworks are primarily for making it simpler to cause an update in a model to trigger a UI refresh or a save call to the data store, or similar tasks.

From playing around with them, it looks like MVC architecutres (ie: Backbone and co.) are really just prebuild object prototypes with some informal protocols for updating data. The concepts and features are powerful when you're making basic GUI pages, but are less impressive when looking at them from a gamedev angle.

In a game, you generally want to go through as few significant layers of indirection as possible. Just give yourself a top level object-namespace type thing that contains all your game variables and access them directly. Getting some object to notify some bit of code that it has changed isn't terribly useful if you're polling the state of that object every update frame anyway. Those if(datum[key] !== value){ blocks aren't free.

Choose which specific properties of an object for which it's absolutely necessary that events happen (instead of just polling and keeping a "previousVal" var for each specific bit of code that needs it), and limit your events to only update on that set. You can even make a reusable mechanism like Backbone's attributes so long as you keep an eye on how often you're triggering events.

It's silly to send changed events and check if the value is already not equal for position changing, because you're going to redraw most of these things every frame anyway, so just keep writing it into memory, even if you write "position.x = 142" thousands of times (although maybe at that point you can have a collection of "static" objects ;) ).

Libs like underscoreJS are probably a good thing to take advantage of, since it's primarily about providing functions that make data manipulation easier and doesn't appear to make assumptions about your architecture.

And you may even be able to keep using Backbone as infrastructure for just exclusively emitting changed events for those properties that really need it or would really make your life simpler if you had them.

But don't go to the other extreme and refuse to ever abstract around an object property.

\$\endgroup\$
0
\$\begingroup\$

JS MVC frameworks was not designed for game development, they add a lot of syntatic sugar which leads to perfomance problems, that's why it's not the best solution to use them for this kind of application. But, actually, it depends on what kind of game are you developing, in some cases it's fine.

Sorry for my english.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .