Animazioni con il Canvas di javascript: Come animare con gli sprite
Tags: javascript, canvas, sprites, spritesheet
Published: 2021-09-24 09:22:20

---
title: Animazioni con il Canvas di javascript: Come animare con gli sprite
published: true
description: Animazione gli sprites con il canvas
tags: js, canvas, sprites, spritesheet
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8m55nddwh0p5skfs34ie.jpg
---
Se volessimo creare una presentazioni animata o un videogioco con una grafica "non vettoriale" ma con una grafica raster (pixellosa) dovremmo __imparare a gestire gli sprites__. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2h99kr9f75gnotiy7z10.gif)

Ma cosa sono gli sprites? 
__Gli sprites sono delle immagini in sequenza__ che fatte scorrere ad una certa velocità ingannano l'occhio facendolo sembrare in movimento.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2z03fbvljimcwqp534xz.gif)

Per implementare gli sprite nel canvas abbiamo bisogno di uno spritesheet cioè __un immagine che contiene tutte le sequenze__ della nostra animazione. Come in questo esempio.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8m55nddwh0p5skfs34ie.jpg)

Se come me non siete dei grandi grafici, ci sono un sacco di risorse in internet. Li potete trovare tra gli archivi di immagini o in siti come 
* https://itch.io/game-assets 
* https://www.spriters-resource.com/ (quest'ultima è sotto copyright, quindi se li usate fatelo per uso personale)
* https://opengameart.org/

Io ho scelto di animare __questo cane che corre__, è __uno spritesheet semplice su una sola riga con 4 fasi dell'animazione__, più avanti vedremo sprite più complessi su più righe e che comanderemo con i tasti.

###INIZIALIZIAMO
 
Iniziamo inizializando un elemento _canvas_ grande 600x400, stampando, a video l'immagine (spritesheet) che contiente i 4 sprite una volta caricata.

* **HTML**
``` html 
<canvas id="myCanvas"></canvas>
```

* **JS**
``` js
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
canvas.width = 600;
canvas.height = 400;



let img = new Image();
img.src = 'https://i.ibb.co/tmdzwtT/dog.jpg';
img.addEventListener('load', () => {
  ctx.drawImage(img, 0, 0);
})
```

Una volta caricata, si vede __un'immagine 600 x 200 divisa in 4 frame della grandezza di 150 x 200 che comporranno la nostra animazione__. 
Visto che a noi serve solo un frame alla volta dobbiamo __creare una maschera di 150 x 200 che mostra solo un frame alla volta__.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h04k14m9j9yngfp64acj.jpg)

Questa operazione di ritaglio si può fare direttamente con il metodo ctx.drawImage che ha delle opzioni che ci premettono di visualizzare a video sono una pozione rettangolare di un immagine.

Avevo già trattato in questo post, ["Canvas Javascript: Come disegnare immagini"](https://dev.to/camizzilla/canvas-javascript-come-disegnare-immagini-54in), come fare, ma oggi andremo a vedere come si può __utilizzare questo metodo per creare del movimento__.

__Ritagliamo lo spritesheet in modo da visualizzare solo il primo frame__.
Partiamo dalla coordinata dell'immagine 0, 0 (rX, rY) e tagliamo una porzione larga 150px (rL) e lunga 200px (rA) ( il rettangolo che contiene il primo frame)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g5u6iz3s8vk00fal6hjl.jpg)

__Posizioniamo la maschera sul canvas__, circa al centro, alle coordinate 225, 100 (x,y) e lo visualizziamo con le stesse dimensioni del ritaglio, 150x200px (l, a)

``` js
img.addEventListener('load', () => {
  //ctx.drawImage(img, rX, rY, rL, rA, x, y, l, a);
  ctx.drawImage(img, 0, 0, 150, 200, 225, 100, 150, 200);
})
```

Adesso per creare l'effetto di movimento dobbiamo spostare la funzione _ctx.drawImage_ in un ciclo e far scorrere la maschera di ritaglio ad ogni frame e una volta finiti tornare al frame 0.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hgrujtz0e24qjgvnvvrb.gif)

Creiamo una funzione loop che si chiamerà in modo ricorsivo grazie al metodo _requestAnimationFrame_ ad ogni fine ciclo. 

_requestAnimationFrame_ è il metodo creato apposta per gestire i cicli nel canvas. Ne parlo in maniera più approfondita in questo post: ["Animazioni con il Canvas di javascript: Come cos'è e come implementarlo con un esempio base"](https://dev.to/camizzilla/animazioni-con-il-canvas-di-javascript-come-cos-e-e-come-implementarlo-con-un-esempio-base-gh)

``` js
let img = new Image();
img.src = 'https://i.ibb.co/d264Yhf/greeting.png';
img.addEventListener('load', () => {
  requestAnimationFrame(loop)
})

let loop = () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(img, 0, 0, 150, 200, 225, 100, 150, 200);
  requestAnimationFrame(loop)
} 
```

Al caricamento dell'immagine viene chiamata la funzione loop.
Che ha 3 metodi al suo interno: _clearRect_ che ripulisce il canvas, il metodo che stampa a video che abbiamo creato precedentemente e per ultimo _requestAnimationFrame(loop)_ che richiama se stessa.

Il prossimo passo è quello di aumentare il frame ad ogni ciclo.
Nel nostro caso sono 4 frames e vanno dal frame 0 al frame 3.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1sdgdfusq5zztsv9vet.jpg)
 
I frame si trovano ad una distanza di 150px, quindi il valore per rX sarà di: 
* 0 per il frame 0
* 150px per il frame 1
* 300px per il frame 2
* 450px per il frame 3

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o741oke0s1e2pq8nosr3.jpg)

Da questo si può inturire che se moltiplichiamo il numero del frame con la larghezza (Lr) otterremo il valore rX.

rX = lr * frameCounter;

``` js
let lr= 150;
let frameCounter = 0;
let rX = 0

let loop = () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  rX = lr * frameCounter;
  ctx.drawImage(img, rX, 0, lr, 200, 225, 100, 150, 200);
  
  framecounter < 3 ? frameCounter++ : frameCounter = 0;
  requestAnimationFrame(loop)
} 
```

Nel primo ciclo il secondo argomento prende come risultato della moltiplicazione 150 * 0, quindi il ritaglio partirà dalla posizione 0, poi il framecounter aumenta di uno perchè il "frame" è minore di 3.
Nel secondo ciclo, il frame vale 1 che moltiplicato a 150 fa rX: 150... e cosi via 150 * 2 = 300, 150 * 3 = 450 e poi l'animazione ricomincia perchè il valore frame non è maggiore di 3 e il valore di framecounter tornerà a 0.

{% codepen https://codepen.io/camizzilla/pen/xxrjEjN %}

Se dovessimo lasciare il codice così, il nostro cane correrebbe troppo veloce, perchè gli fps, frame per secondo, sono troppo alti.

Gli fps sono dei valore che indicano quante volte il ciclo viene riprodotto in un secondo.

Niente paura, nel prossimo post, spegherò in maniera semplice cos'è l'fps e qual'è la tecnica per implementarlo al meglio.

Per adesso gli applicheremo un setTimeout che non è la miglior soluzione, ma sicuramente la più veloce


``` js
let lr= 150;
let frameCounter = 0;
let rX = 0

let framesPerSecond = 10;

let loop = () => {
  setTimeout( () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    rX = lr * frameCounter;
    ctx.drawImage(img, rX, 0, lr, 200, 225, 100, 150, 200);

    frameCounter < 3 ? frameCounter++ : frameCounter = 0;
    requestAnimationFrame(loop)
  }, 1000 / framesPerSecond);
  
} 
```

CONCLUSIONE

Abbiamo visto come gestire un animazione semplice con gli Sprites.
Successivamente vedremo gli fps per la gestire la velocità dei frame, come gestire SpriteSheet su più righe e come unire i comandi di tastiera con le animazioni.

Se avete dei consigli, suggerimenti o critiche costruttive lasciatemi un commento qui sotto oppure contattatemi trammite i miei social.