2017-08-08 2 views
0

J'ai un problème. J'essaye de faire un jeu de tetris en javascript (pour apprendre). Cependant, je ne peux pas utiliser la fonction setInterval (ou setTimeout). Ce que je veux faire est de changer la couleur du prochain cas tous les 2000ms.Tetris dans Javascript: setInterval setTimeout comportement

HTML CODE:

<!DOCTYPE html> 
<html lang="fr"> 
<head> 
    <meta charset="UTF-8"> 
    <title>PROJET : PROGRAMMATION COTE CLIENT</title> 
    <link rel="stylesheet" type="text/css" href="index.css"> 
</head> 
<body> 
    <div class="all"> 
     <div id="A"> 
      <span id="pos1A"></span> 
      <span id="pos2A"></span> 
      <span id="pos3A"></span> 
      <span id="pos4A"></span> 
      <span id="pos5A"></span> 
      <span id="pos6A"></span> 
      <span id="pos7A"></span> 
      <span id="pos8A"></span> 
      <span id="pos9A"></span> 
      <span id="pos10A"></span> 
     </div> 
    </div> 
    <script src="classes.js"></script> 
    <script src="indexjs.js"></script> 
    </body> 
</html> 

CSS CODE:

.all { 
    display: flex; 
    flex-direction: column; 
} 
.all > div { 
    display: flex; 
    flex-direction: row; 
} 
.all > div > span { 
    width: 20px; 
    height: 20px; 
    border: 1px solid gray; 
} 

JS CODE:

var array = ['pos1A','pos2A','pos3A','pos4A','pos5A','pos6A','pos7A','pos8A','pos9A','pos10A ']; 
function downmove(i) { 
    var element = document.getElementById(array[i]); 
    element.style.backgroundColor = 'green'; 
    console.log(element); 
} 
var i; 
for(i=0;i<10;i++) { 
    setInterval(downmove(i),2000); 
} 

Je veux que chaque bloc pour changer la couleur, un par un, mais en réalité il colore tout la ligne d'affilée. C'est comme si mon intervalle ne fonctionnait pas.

enter image description here

+0

lecture [la documentation] (https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) est toujours utile. Vous devez également supprimer la boucle 'for', si vous utilisez' setInterval', ou utiliser 'setTimeout' à la place, auquel cas il y aura un problème de fermeture avec la valeur de' i' ... – Teemu

+0

Merci. Je n'ai pas encore lu à propos de la fermeture, je pensais que je n'en avais pas besoin pour ce petit projet. – WaLinke

Répondre

2

C'est parce que votre setInterval appel est erroné.

setInterval et setTimeout les deux prennent un Function comme premier paramètre, alors que (dans votre exemple), vous êtes en train de fonctionner, vous invoquez immédiatement (c'est la raison pour laquelle vous voyez les résultats tout de suite). Vous devriez jeter un oeil à la documentation, par exemple à MDN: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval.

Vous pouvez modifier votre fonction downmove(i) pour retourner une nouvelle fonction qui sera transmis à setInterval, ou vous pouvez utiliser une fonction anonyme pour vous envelopper downmove appel dans l'intervalle comme ceci:

for (i = 0; i<10; i++) { 
    setInterval(
     (function (idx) { downmove(idx); })(i), 
     2000 
    ); 
} 

(S'il vous plaît remarquez que j'utilise un IIFE pour traiter correctement la variable i, cela pourrait être évité en utilisant let i = 0 dans la boucle for, mais pourquoi cela est nécessaire est un autre sujet à couvrir, vous pouvez en lire plus à ce sujet ici: JavaScript closure inside loops – simple practical example).


Il y a un autre problème avec votre code - vous voulez changer les couleurs de manière séquentielle, mais vous la mise en œuvre (même avec le correctif) courrez chaque changement de couleur instantanément après ces 2 secondes de temps. Pour résoudre ce problème, vous devez d'une manière ou d'une autre garder la trace de la ligne précédemment colorée et l'incrémenter toutes les 2 secondes.

Voici un exemple simple de mise en œuvre fixe:

let idx = 0; 

const intervalID = setInterval(function() { 
    if (idx >= 10) { 
     // Maximum row reached, break the loop... 
     clearInterval(intervalID); 

     return; 
    } 

    downmove(idx); 

    idx++; 
}, 2000); 

(Pas besoin d'utiliser for-loop ici).

+0

Merci beaucoup pour votre réponse. Je viens du C++ et ce sont des concepts que je ne connais pas. Je dois travailler plus sur les bases avant de mettre la main sur ce projet.Merci beaucoup pour les liens utiles et passez une bonne journée. – WaLinke

1

Voici comment vous pouvez le faire, mais j'imagine que vous devrez le changer pour votre jeu plus tard.

var array = ['pos1A','pos2A','pos3A','pos4A','pos5A','pos6A','pos7A','pos8A','pos9A','pos10A ']; 

var i = 0, 
    interval; 
    max_i = 9; 

function downmove() { 
    var element = document.getElementById(array[i]); 
    element.style.backgroundColor = 'green'; 
    console.log(element); 
    i++; 

    if (i === max_i) clearInterval(interval); 
} 

interval = setInterval(downmove, 2000); 
+1

J'ai essayé ceci et cela fonctionne, mais je ne comprends pas pourquoi vous appelez setInterval (downmove, 2000) et non setInterval (downmove(), 2000) Il fonctionne avec le premier mais pas avec le second, il ne montre que le premier bloc en vert. BTW merci beaucoup pour votre réponse et votre temps. – WaLinke

+0

@WaLinke la seconde ne fonctionne pas, car avec "downmove()" vous appelez la fonction et passez le résultat (qui est "null") à setInterval. Par rapport à setInterval (downmove, ...) vous passez la fonction elle-même! –