My HTML5 pong clone took about 200 lines of code, not too many bells and whistles but it worked :). And that lovely script had a function I happily stole from thoughtbot's pong tutorial (you should read their blog, really good stuff!):
Most modern browsers support the requestAnimationFrame function but it never hurts to cover your bases. Wanting to be able to have menus, settings and other stuff you find in games, I decided to encapsulate and expand my little pong clone. Part of that had me moving the animation function scope to the game engine's object scope. It seems simple enough, just put it in like this:
Done! Well, if you want to get this error (in Google Chrome): Uncaught TypeError: Illegal invocation. We can't just take native methods (console.log and the like) and assign them to an object's property. This is because of the function's context - the object within which the function is executed. The requestAnimationFrame needs to be executed in the context of the window object, the above code will execute the function in the context of the GameEngine's object. Luckily the solution is to simply bind the functions to the window object:
That way the window context will be used when calling any of them. In my
code I use
bind(this), which also works. Why? By default the bind function
will set 'this' to the window object for those native functions.
Fun fact - there is a global variable named FPS that's passed to the
GameEngine object, hence why this code will work if the last function is
called even though the scope of 'this' will be the window (I know that's
cheating!). Alternatively, we could keep the definition of GameEngine's
execute it. So instead of using the animate function like
engine.animate(step) we leave out bind and write
engine.animate.call(window, step). Can't say you don't got options!