0
\$\begingroup\$

I read this playfulJS post, about ray-casting: http://www.playfuljs.com/a-first-person-engine-in-265-lines/

It looks really interested, so I decided to look at his javascript. I am no expert in javascript, so I quickly got lost.

It's the game loop "object" that really gets me. I simply don't understand how it works. From the code:

function GameLoop() {
        this.frame = this.frame.bind(this);
        this.lastTime = 0;
        this.callback = function() {};
      }

      GameLoop.prototype.start = function(callback) {
        this.callback = callback;
        requestAnimationFrame(this.frame);
      };

      GameLoop.prototype.frame = function(time) {
        var seconds = (time - this.lastTime) / 1000;
        this.lastTime = time;
        if (seconds < 0.2) this.callback(seconds);
        requestAnimationFrame(this.frame);
      };

var loop = new GameLoop();

      loop.start(function frame(seconds) {
        map.update(seconds);
        player.update(controls.states, map, seconds);
        camera.render(player, map);
      });

Now, what really confuses me here, is this bind stuff and how this actually loops.

I am guessing, that if less than 0.2 seconds have passed, since the last time the loop was run, it simply goes back to re-check the time. If more than 0.2 seconds have passed, it leaves the frame function, and executes the 3 lines in the loop.

But, if this is true, then how does the loop.start() get called again? And what on earth is the meaning of this.frame = this.frame.bind(this);?

I've looked up prototypes bind() but I really don't understand it.

\$\endgroup\$
1
  • \$\begingroup\$ Are you familiar with prototype-based programming in general? \$\endgroup\$
    – user1430
    Jun 10, 2014 at 21:56

1 Answer 1

0
\$\begingroup\$

You're on the right track, but your guess is a bit backwards. The start prototype of GameLoop takes a callback function that represents the core update steps of the application; in this case, player and map updates, and drawing. The frame function will run this callback function if the time elapsed since the last frame is less than 0.2 seconds. I'm assuming that requestAnimationFrame is a higher level API call to refresh the window.

Now, requestAnimationFrame takes a callback which represents the function it should run as part of the window refresh. The writer of this code wanted this callback to be associated with a particular object, so that it could have access to internal variables such as this.callback and this.lastTime. In order to do that, the callback provided to requestAnimationFrame must be bound to a specific instance of GameLoop, and that is what this.frame.bind(this) accomplishes.

To put it another way, the call to bind establishes that the this object in the prototype frame function will refer to a specific instance of GameLoop; the one provided in the call to bind.

\$\endgroup\$

You must log in to answer this question.

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