views:

83

answers:

2

I have created my first SVG game, using Raphaël.js.

In Chrome the game feels fast, but in other browser like IE (understandable since it's using VML), Firefox, iPad safari and others, it feels slow at times.

I'm looking for some tips on how I can optimize my code to squeeze out the absolute best performance. I've tried the best I can to optimize it myself, but I'm just a JS beginner. Also feel free to mention if should be using any recommended best practices I'm not using. Where is it probable that the bottleneck is?

You can see the code and try the game on jsfiddle.

A: 

reduce method calls

var left1 = a.attr('x'),
left2 = b.attr('x'),
right1 = a.attr('x') + a.attr('width'),
right2 = b.attr('x') + b.attr('width'),
top1 = a.attr('y'),
top2 = b.attr('y'),
bottom1 = a.attr('y') + a.attr('height'),
bottom2 = b.attr('y') + b.attr('height');

Could be optimized like so:

var left1 = a.attr('x'),
left2 = b.attr('x'),
right1 = left1 + a.attr('width'),
right2 = left2 + b.attr('width'),
top1 = a.attr('y'),
top2 = b.attr('y'),
bottom1 = top1 + a.attr('height'),
bottom2 = top2 + b.attr('height');

This saves you 4 method calls per hitDetection call. Same applies to wallDetection and probably other functions as well. In fact, I also believe you width and height calls can be removed and just cached through a closure, since those are pretty static after creation, see next example.

Also with the next bit:

var animateEnemies = function(enemy) {
    var enemyWidth = enemy.attr('width'),
    enemyHeight = enemy.attr('height'),
...

You set the width and height of the enemies once, so they seem pretty constant, you could remove the .attr() lookup and pass the width and height from the createEnemies call as well.

var animateEnemies = function(enemy , enemyWidth , enemyHeight) {
    var animationDuration = getRandomInt(1000, 3000) / difficulty;
    enemy.animate({
        x: getRandomInt(0, gameWidth - enemyWidth),
        y: getRandomInt(0, gameHeight - enemyHeight)
    }, animationDuration, "ease-in-out");
    // use setTimout instead of onAnimation callback, since it gave "too much recursion" in Firefox 3.6
    this.timeOut = setTimeout(function() {
        animateEnemies(enemy , enemyWidth , enemyHeight);
    }, animationDuration);
};

Reducing function calls and caching variables can help a lot in legacy browsers, other then that, code looks pretty neat.

BGerrissen
Unfortunetely none of these micro optimizations will help.
galambalazs
@galambalaz When addressing legacy browsers such as IE, there's no such thing as micro optimisations... Reducing function calls within often invoked functions can actually offer a huge performance boost. If it solves the problem entirely however is unlikely, but it WILL HELP.
BGerrissen
If the performance gain is unnoticable, it's micro optimization. Things that yield somewhat better results in theory and have no effect in a particular situation. This is why optimization should always go hand in hand with testing.
galambalazs
A: 

I don't want to sound distressingly, but i doubt IE can do any better. As you can see I made a stripped down version consisting only the animations (no hit detection, game logic or mousemove handler) and the speed is still unacceptable.

For Firefox I think I found out how to avoid sluggishness:

var mouseMove = function(e) {

    // only do this if there's at least 20ms diff.
    var now = +new Date();
    if (now - mouseMove.last < 20)
        return;
    else 
       mouseMove.last = now;

    // ...
};

mouseMove.last = +new Date();   
galambalazs