HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

GameLoop with requestAnimationFrame

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withgamelooprequestanimationframe

Problem

I am creating a HTML game where you fight monsters and stuff and this is part of the game loop for dealing damage:

var hp = 1000000000;
var speed = 10;
var power = 5;   

var lastCalledTime;
var fps;

var GameLoop = function() {
    if(!lastCalledTime) {
           lastCalledTime = new Date().getTime();
           fps = 0;
           return;
    }
    delta = (new Date().getTime() - lastCalledTime)/1000;
    lastCalledTime = new Date().getTime();
    fps = 1/delta;

    hp = hp - (5 * speed * 0.1) / fps;
};

var animFrame = window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame    ||
                window.oRequestAnimationFrame      ||
                window.msRequestAnimationFrame     ||
                null ;

if ( animFrame !== null ) {
    var recursiveAnim = function() {
        GameLoop();
        animFrame( recursiveAnim );
    };
    animFrame( recursiveAnim );
} else {
    setInterval( GameLoop, 33.33 );
}


http://jsfiddle.net/u0k7tbv4/2/

Power is how much you deal with each attack and each level of speed gives 0.1 attack / second. With 5 Power and 10 Speed it should deal 5 damage every second and that seems to be the case in the fiddle.

But I'm not sure, I only used requestAnimationFrame because I heard setInterval is unstable and so it would be nice if someone could validate the code.

Solution

Instead of var GameLoop = function() { ... };, you could just define a function the "natural" way. Calling it gameLoop() would respect capitalization conventions better.

You neglected to use the var keyword when defining delta, so it becomes a global variable.

The GameLoop() function sets fps as a side-effect. If you don't actually need fps anywhere else, then it should be local. Furthermore, if you don't need fps, then there is no point in setting it to the reciprocal of delta.

I don't see much harm in initializing lastCalledTime right away, to eliminate the one-time-use special case inside GameLoop() — even if you technically didn't call GameLoop() at the time.

Calling getTime() twice is ugly. If might also cause a tiny bit of clock skew.

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

function gameLoop() {
    var now = new Date().getTime();
    var delta = (now - lastCalledTime) / 1000;
    lastCalledTime = now;

    hp -= 0.5 * speed * delta;
};


Alternatively, if you would like lastCalledTime neatly tucked inside the gameLoop() function rather than dangling outside, you could write:

function gameLoop() {
    var now = new Date().getTime();
    if (!arguments.callee.lastCalledTime) {
        arguments.callee.lastCalledTime = now;
    }
    var delta = (now - arguments.callee.lastCalledTime) / 1000;
    arguments.callee.lastCalledTime = now;

    hp -= 0.5 * speed * delta;
};

Code Snippets

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

function gameLoop() {
    var now = new Date().getTime();
    var delta = (now - lastCalledTime) / 1000;
    lastCalledTime = now;

    hp -= 0.5 * speed * delta;
};
function gameLoop() {
    var now = new Date().getTime();
    if (!arguments.callee.lastCalledTime) {
        arguments.callee.lastCalledTime = now;
    }
    var delta = (now - arguments.callee.lastCalledTime) / 1000;
    arguments.callee.lastCalledTime = now;

    hp -= 0.5 * speed * delta;
};

Context

StackExchange Code Review Q#60216, answer score: 4

Revisions (0)

No revisions yet.