Le animazioni viste finora (Come creare un animazione in JavaScript (3)) hanno tutte una caratteristica, gli oggetti quando raggiungono i bordi escono dall'area visibile.
Vediamo come aggiungere la gestione della collisione con i bordi.
Se non vedi l'animazione clicca sul canvas o ricarica la pagina

Per gestire le collisioni con i bordi aggiungo una funzione checkCollision:
function checkCollision() {
  //verifico la collisione con i bordi
  arena.sprites.forEach(sprite => {
    if (sprite.animationOn === true) {
      switch (sprite.type) {
        case SpriteType.RECTANGLE:
          const w2 = sprite.w / 2;
          const h2 = sprite.h / 2;
          if (sprite.x - w2 < 0 || sprite.x + w2 > innerWidth) {
            sprite.deltaX = -sprite.deltaX;
            sprite.x += sprite.deltaX / 2;
          }
          if (sprite.y - h2 < 0 || sprite.y + h2 > innerHeight) {
            sprite.deltaY = -sprite.deltaY;
            sprite.Y += sprite.deltaY / 2;
          }
          break;

        case SpriteType.CIRCLE:
          if (sprite.x - sprite.radius < 0 || sprite.x + sprite.radius > innerWidth) {
            sprite.deltaX = -sprite.deltaX;
            sprite.x += sprite.deltaX / 2;
          }
          if (sprite.y - sprite.radius < 0 || sprite.y + sprite.radius > innerHeight) {
            sprite.deltaY = -sprite.deltaY;
            sprite.Y += sprite.deltaY / 2;
          }
          break;
      }
    }
  });
}
Per ogni tipo di sprite, cerchio e rettangolo, faccio un controllo specifico. Quando l'oggetto raggiunge il bordo, inverto la velocità. Se tocca un bordo laterale, destro o sinistro, inverto la velocità sull'asse x (deltaX), mentre se tocca il bordo superiore o inferiore, inverto la velocità sull'asse y (deltaY).

Il passo successivo è inserire la checkCollision nel loop di animazione:
function animationLoop() {
  updatePosition();
  checkCollision();
  draw();
  requestAnimationFrame(animationLoop);
}

In questo caso ho anche generato gli sprite in modo random:
function createSprites() {
  //trovo il centro del canvas
  const cx = canvas.width / 2;
  const cy = canvas.height / 2;
  arena.addSprite(new SpriteBackground(0, 0, innerWidth, innerHeight, '#444'));
  const text1 = new SpriteText(cx, cy, 'Sgart.it', '150px Arial', '#ccc', null, 'center', 'middle');
  text1.alpha = .5;
  arena.addSprite(text1);
  //aggiungo sprite casuali
  for (var i = 0; i < 40; i++) {
    const w2 = Math.random() * 30.0 + 5.0;
    const h2 = Math.random() * 30.0 + 5.0;
    const x = cx + (Math.random() - .5) * w2 * 2;
    const y = cy + (Math.random() - .5) * h2 * 2;
    const color = colors[Math.random() * colors.length | 0];
    const deltaX = (Math.random() - .5) * 6.0;
    const deltaY = (Math.random() - .5) * 6.0;
    let alpha = Math.random();
    if (alpha < .2) alpha = .2;
    if (alpha > .8) alpha = 1;
    const t = Math.random();
    if (t < .5) {
      const circle = new SpriteCircle(x, y, w2, null, color, deltaX, deltaY);
      circle.alpha = alpha;
      arena.addSprite(circle);
    } else {
      const rect = new SpriteRect(x, y, w2 * 2, h2 * 2, null, color, deltaX, deltaY);
      rect.alpha = alpha;
      arena.addSprite(rect);
    }
  }
  const text2 = new SpriteText(innerWidth - 5, innerHeight - 5, 'Test animazione 4', '40px Arial', null, '#888', 'right', 'bottom');
  text2.alpha = .9;
  arena.addSprite(text2);
}
Il risultato è l'animazione a inizio pagina.