2010-06-02 7 views
3

J'ai un tableau qui fait partie d'un petit jeu JS sur lequel je travaille J'ai besoin de vérifier (aussi souvent que possible) que chacun des éléments du tableau n'a pas quitté la "scène" ou "aire de jeux", donc je peux les enlever et enregistrer le script chargerComparaison plus efficace des nombres

J'ai codé le ci-dessous et je me demandais si quelqu'un connaissait une manière plus rapide/plus efficace de le calculer. Ceci est exécuté toutes les 50ms (il s'agit du mouvement).

bots[i][1] est le mouvement dans X et bots[i][2] est le mouvement dans Y (s'excluant mutuellement).

for (var i in bots) { 
    var left = parseInt($("#" + i).css("left")); 
    var top = parseInt($("#" + i).css("top")); 
    var nextleft = left + bots[i][1]; 
    var nexttop = top + bots[i][2]; 
    if(bots[i][1]>0&&nextleft>=PLAYGROUND_WIDTH) { remove_bot(i); } 
    else if(bots[i][1]<0&&nextleft<=-GRID_SIZE) { remove_bot(i); } 
    else if(bots[i][2]>0&&nexttop>=PLAYGROUND_HEIGHT) { remove_bot(i); } 
    else if(bots[i][2]<0&&nexttop<=-GRID_SIZE) { remove_bot(i); } 
    else { 
     //alert(nextleft + ":" + nexttop); 
     $("#" + i).css("left", ""+(nextleft)+"px"); 
     $("#" + i).css("top", ""+(nexttop)+"px"); 
    } 
} 

Sur une note similaire, remove_bot (i); fonction est comme ci-dessous, est-ce correct (je ne peux pas épissure car il change tous les ID de des éléments du tableau.

function remove_bot(i) { 
    $("#" + i).remove(); 
    bots[i] = false; 
} 

Un grand merci pour tous les conseils donnés!

Répondre

8
  1. Cache $("#" + i) dans une variable, chaque fois que vous faites cela, un nouvel objet jQuery est créé

    var self = $('#' + i); 
    var left = parseInt(self.css("left")); 
    var top = parseInt(self.css("top")); 
    
  2. Cache bots[i] dans une variable:

    .
    var current = bots[i]; 
    var nextleft = left + current[1]; 
    var nexttop = top + current[2]; 
    
  3. Stockez (cache) l'objet jQuery de l'élément DOM dans la représentation du bot. Pour le moment, il a été créé toutes les 50ms. Je veux dire par là que pour chaque itération de la boucle, vous faites $('#' + i). Chaque fois que vous appelez ceci, jQuery construit un objet jQuery de l'élément DOM. C'est loin de trivial par rapport à d'autres aspects de JS. DOM traversal/manipulation est de loin le domaine le plus lent de JavaScript.

    Comme le résultat de $('#' + i) ne change jamais pour chaque bot, pourquoi ne pas stocker le résultat dans le bot? De cette façon, $('#' + i) est exécuté une fois, au lieu de toutes les 50ms.

    Dans mon exemple ci-dessous, j'ai stocké cette référence dans l'attribut element de mes objets Bot, mais vous pouvez l'ajouter votre bot (dans bots[i][3])

  4. Store (cache) la position du DOM élément représentant le bot dans la représentation du bot, donc la position CSS n'a pas besoin d'être calculée tout le temps.

Sur une note de côté, for (.. in ..) doit être strictement utilisé pour itérer sur des objets, pas de tableaux. Les tableaux doivent être itérés en utilisant for (..;..;..)

Les variables sont extrêmement pas cher en JavaScript; abuser d'eux.

est ici une implémentation je choisirais, qui intègre les suggestions que je l'ai fait:

function Bot (x, y, movementX, movementY, playground) { 
    this.x = x; 
    this.y = y; 
    this.element = $('<div class="bot"/>').appendTo(playground); 
    this.movementX = movementX; 
    this.movementY = movementY; 
}; 

Bot.prototype.update = function() { 
    this.x += this.movementX, 
    this.y += this.movementY; 

    if (this.movementX > 0 && this.x >= PLAYGROUP_WIDTH || 
     this.movementX < 0 && this.x <= -GRID_SIZE || 
     this.movementY > 0 && this.y >= PLAYGROUND_HEIGHT || 
     this.movementY < 0 && this.y <= -GRIDSIZE) { 
     this.remove(); 
    } else { 
     this.element.css({ 
      left: this.x, 
      right: this.y 
     }); 
    }; 
}; 

Bot.prototype.remove = function() { 
    this.element.remove(); 
    // other stuff? 
}; 

var playground = $('#playground'); 
var bots = [new Bot(0, 0, 1, 1, playground), new Bot(0, 0, 5, -5, playground), new Bot(10, 10, 10, -10, playground)]; 

setInterval(function() { 
    var i = bots.length; 

    while (i--) { 
     bots[i].update(); 
    }; 
}, 50); 
+0

Un conseil vraiment utile, je posterai le code mis à jour sous peu. Cependant, je ne comprends pas vraiment ce que vous entendez par # 3 pourriez-vous conseiller davantage? Un grand merci, –

+0

@PezCuckow: J'ai étendu mon explication pour # 3 – Matt

1

Vous utilisez parseInt.Pour autant que je sache, un OU bit à bit est plus rapide que parseInt. Donc, vous pouvez écrire

var left = $("#" + i).css("left") | 0; 

à la place. De plus, je n'utiliserais pas les fonctions de jQuery pour obtenir des valeurs comme celles-ci toutes les 50 ms, car il y a toujours un peu plus de surcharge quand on les utilise (la fonction $ doit analyser ses arguments, etc.). Utilisez simplement les fonctions JavaScript natives pour optimiser ces lignes. De plus, avec votre code, l'élément avec l'identifiant i doit être récupéré plusieurs fois. Conservez ces éléments dans une variable:

var item = document.getElementById(i); 
var iStyle = item.style; 
var left = iStyle.left; 
… 

(S'il vous plaît noter que je ne suis pas un expert jQuery, donc je ne suis pas 100% sûr que cela fait la même chose.)

De plus, décrémentation while boucles sont plus rapide que for boucles (reference). S'il n'y a pas de problème avec une boucle à travers les éléments dans l'ordre inverse, vous pouvez réécrire votre code pour

var i = bots.length; 
while (i--) { 
    … 
} 
+0

Re votre utilisation de tout, j'ai besoin d'utiliser l'ID réel de l'élément dans le tableau, comme je supprime/enlève certains, il ne peut pas être juste un boucle avec des valeurs croissantes ou décroissantes. Sinon, un conseil fantastique! –

0

Jetez un oeil here for a great comparison de différentes techniques de mise en boucle en javascript. L'utilisation de ... in a de mauvaises performances et n'est pas recommandée sur les baies. Une alternative à la boucle en arrière et en utilisant toujours une boucle for est de mettre en cache la longueur de sorte que vous ne le recherchiez pas à chaque itération. Quelque chose comme ceci:

for(var i, len = bots.length; i < len; i++) { ... } 

Mais il existe des moyens nombreux, comme le montre le lien ci-dessus et vous pouvez tester plusieurs avec votre application réelle pour voir ce qui fonctionne le mieux dans votre cas.

0

Utilisez offset() ou position() selon que vous avez besoin de coordonnées relatives au document ou au parent. position() est probablement plus rapide car les navigateurs sont efficaces pour trouver des décalages par rapport au parent. Il n'y a pas besoin d'analyser le CSS. Vous n'avez pas non plus besoin des variables left et top puisque vous ne les utilisez qu'une seule fois. Il peut ne pas être aussi lisible mais vous allez pour l'efficacité:

var left = $("#" + i).position().left + bots[i][1]; 
var top = $("#" + i).position().top + bots[i][2]; 
Questions connexes