2 votes

Comment empêcher qu'un bouton soit pressé deux fois ?

Le problème est que lorsque je clique plusieurs fois sur enter, je ne sais pas comment faire pour que les gens ne puissent pas cliquer plusieurs fois sur enter pour que le canon soit super rapide.

document.onkeydown = (e) => {
  e.preventDefault();

  if (e.repeat) return; // Do nothing

  const { key } = e;

  switch(key) {
    case 'ArrowUp':
      cannonball.dx++,
      cannonball.dy++
      break;
  }
};

Voici l'objet dans lequel je l'utilise

const c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
//variables
const cannon = {
w: 150,
h: 75,
x:0,
y:0
}

const cannonball = {
x: 77,
y: 565,
r:25,
dx:0,
dy:0
}

const cannonRotate = {
degree: -43.5
}

//running the whole function
function animate(){
c.clearRect(0,0,innerWidth,innerHeight);
//cannon
c.save();
c.translate(-25,600);
c.rotate(cannonRotate.degree * Math.PI / 180);
c.fillStyle = '#000';
c.fillRect(cannon.x,cannon.y,cannon.w,cannon.h);
c.restore();

//cannonball
c.beginPath();
c.arc(cannonball.x,cannonball.y, cannonball.r, 0, Math.PI * 2, false);
c.fillStyle = '#000';
c.fill();

cannonball.x += cannonball.dx;
cannonball.y -= cannonball.dy;

document.onkeydown = (e) => {
  e.preventDefault();

  if (e.repeat) return; // Do nothing

  const { key } = e;

  switch(key) {
    case 'ArrowUp':
      cannonball.dx += 5,
      cannonball.dy += 5
      break;
  }
};

requestAnimationFrame(animate)
}

1voto

Elias Soares Points 2808

Si j'ai bien compris votre question, vous souhaitez limiter l'intervalle entre les pressions sur les touches, n'est-ce pas ? Vous pouvez donc le faire en implémentant un timer qui ignore les prochaines pressions de touches jusqu'à ce qu'il se termine :

let ignoreKeyPress = false;

document.onkeydown = (e) => {
  e.preventDefault();

  if (e.repeat || ignoreKeyPress) return; // Do nothing

  ignoreKeyPress = true;
  setTimeout(() => ignoreKeyPress = false, 1000); // change the 1000 to the interval between keypresses that you want in miliseconds.

  const { key } = e;

  switch(key) {
    case 'ArrowUp':
      cannonball.dx++,
      cannonball.dy++
      break;
  }
};

1voto

ggorlen Points 5267

Il existe de nombreuses façons de procéder, mais voici un exemple d'étranglement que vous pouvez essayer d'appliquer à votre code. L'idée est d'envelopper une fonction avec une fermeture qui contient l'heure du dernier appel. Pour les appels répétés, la dernière fois est vérifiée avant de rappeler la fonction. A cooldown détermine la durée du délai avant qu'un nouveau déclenchement ne soit autorisé (en millisecondes). Il s'agit d'une fonction générale que vous pouvez appliquer à pratiquement tout (requêtes HTTP, par exemple, pour imposer une limitation de débit).

En outre, c'est probablement une erreur de réenregistrer des gestionnaires d'événements à l'intérieur de la boucle d'animation. Il s'agit d'une tâche de configuration unique, et non d'une tâche à effectuer 30 à 60 fois par seconde.

En ce qui concerne la chose que vous étranglez, il est inhabituel que le boulet de canon ne se déplace que lorsque l'on appuie sur la touche flèche. Pour l'exemple minimal ci-dessous, je limite la vitesse de tir, ce qui est (probablement ?) plus logique pour un jeu.

const throttle = (fn, cooldown=1000) => {
  let lastCall = 0;
  return (...args) => {
    if (Date.now() - lastCall > cooldown) {
      lastCall = Date.now();
      fn(...args);
    }
  };
};

const canvas = document.createElement("canvas");
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx.fillStyle = "#000";

const cannonBalls = [];

(function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  for (const e of cannonBalls) {
    e.dx *= 0.99;
    e.dy += 0.1;
    e.x += e.dx;
    e.y += e.dy;
    ctx.beginPath();
    ctx.arc(e.x, e.y, e.r, 0, Math.PI * 2);
    ctx.fill();
  }

  requestAnimationFrame(animate);
})();

const fire = throttle(() => cannonBalls.push({
  x: 10, 
  y: 10,
  dx: 10,
  dy: 0,
  r: 10
}));

document.addEventListener("keydown", e => {
  if (e.keyCode === 32) {
    e.preventDefault();
    !e.repeat && fire();
  }
});

<p>press spacebar to fire</p>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X