Jak zacząć pracę z Canvasem? (3)

Kontynuując. Mamy więc taki kodzik:

const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 500;
document.body.append(canvas);

const ctx = canvas.getContext('2d');
let objects;

function restart() {
    objects = [
        {x: 100, y: 30, vx: 1, vy: 0, color: 'purple'},
        {x: 100, y: 100, vx: 0, vy: 0.5, color: 'red'},
    ];
}
restart();

setInterval(() => {  
  objects.forEach(obj => {
      obj.x += obj.vx;
      obj.y += obj.vy;
      obj.vy += 0.03;
  });

  ctx.clearRect(0, 0, canvas.width, canvas.height);	  
  objects.forEach(obj => {
      ctx.fillStyle = obj.color;
      ctx.fillRect(obj.x, obj.y, 40, 40);
  });
}, 16);	

Co jeśli byśmy chcieli dodać obsługę klawiatury? Żeby to się samo nie ruszało, a żeby klawiaturą ruszać się dało.

Dodajmy nowy obiekt, który będzie miał zerową prędkość

function restart() {
    objects = [
        {x: 100, y: 30, vx: 1, vy: 0, color: 'purple'},
        {x: 100, y: 100, vx: 0, vy: 0.5, color: 'red'},
        {x: 100, y: 100, vx: 0, vy: 0, color: 'blue', falling: false},
    ];
}
restart();

No ale figa, i tak spada. Ale przecież nie obsługujemy nigdzie tego falling=false. więc zmień setInterval na taki:

    setInterval(() => {  
      objects.forEach(obj => {
      	obj.x += obj.vx;
      	obj.y += obj.vy;
      	if (obj.falling != false) obj.vy += 0.03;
      });

      ctx.clearRect(0, 0, canvas.width, canvas.height);	  
      objects.forEach(obj => {
          ctx.fillStyle = obj.color;
          ctx.fillRect(obj.x, obj.y, 40, 40);
      });
    }, 16);	

Jak widzisz teraz jeden z prostokątów nie spada. No dobra, ale powinniśmy go ruszać czymś. Więc dopiszmy obsługę klawiszy. Służy do tego zdarzenie keydown Niech rusza się strzałkami:

const player = objects[2];
document.addEventListener('keydown', e => {
    const speed = 3;
    if (e.code == 'ArrowLeft') {
         player.x -= speed;
    } else if (e.code == 'ArrowRight') {
         player.x += speed;
    } else if (e.code == 'ArrowDown') {
         player.y += speed;
    } else if (e.code == 'ArrowUp') {
         player.y -= speed;
    }
});

No dobra, rusza się, ale coś dziwnego się dzieje. Przy wciskaniu strzałki w górę i w dół przewija się strona! No niemożliwe. Ale to ma proste wytłumaczenie. Po prostu przeglądarka jest przeglądarką i jak ktoś naciska strzałkę to przewija tę stronę. Ale można ją powstrzymać od tego zamiaru. Możemy w funkcji obsługującej zdarzenia wywołać e.preventDefault . Wtedy przeglądarka oleje temat.

flowchart TD event["zdarzenie"] --> handler["funkcja obsługująca zdarzenie"] handler --> preventDefault["preventDefault()"] handler --> withoutPreventDefault["bez preventDefault()"] withoutPreventDefault --> default["przeglądarka robi domyślną akcję"] preventDefault --> nothing["przeglądarka nic nie robi"]
const player = objects[2];
document.addEventListener('keydown', e => {
    const speed = 3;
    if (e.code == 'ArrowLeft') {
         player.x -= speed;
    } else if (e.code == 'ArrowRight') {
         player.x += speed;
    } else if (e.code == 'ArrowDown') {
         player.y += speed;
    } else if (e.code == 'ArrowUp') {
         player.y -= speed;
    }
    e.preventDefault();
});

Z tym jest jeden pewien problem - tym sposobem żadna domyślna akcja przeglądarki nie przejdzie. Jeśli naciśniesz skrót klawiszowy do odświeżenia strony - strona nie przeładuje się, ponieważ zablokowaliśmy każdą akcję.

Lepszym podejściem byłoby sprawdzenie, czy obsłużyliśmy event i tylko wtedy dawać e.preventDefault():

const player = objects[2];
document.addEventListener('keydown', e => {
    const speed = 3;
    let handled = true;
    if (e.code == 'ArrowLeft') {
         player.x -= speed;
    } else if (e.code == 'ArrowRight') {
         player.x += speed;
    } else if (e.code == 'ArrowDown') {
         player.y += speed;
    } else if (e.code == 'ArrowUp') {
         player.y -= speed;
    } else {
        handled = false;
    }
    if (handled) e.preventDefault();
});

Komentarze

Popularne posty z tego bloga

Absurdy Rekrutacji 2023

Przygody juniora (1)

Czy popełniasz te błędy szukając pracy?