Skip to content

Sesion 6 Animaciones

Jesús Parrado Alameda edited this page Mar 7, 2022 · 2 revisions

Sesión 6: Animaciones

  • Tiempo: 2h (50 + 50 min)
  • Fecha: Martes, 8-Marzo-2022
  • Objetivos de la sesión:
    • Manejo básico del canvas
    • Animaciones en el canvas

Contenido

Introducción

Animaciones

Las animaciones se realizan dibujando elementos en cada fotograma.

Si estos fotogramas se muestran con una frecuencia suficientemente alta, se obtendrá una animación suave.

Si la frecuencia no es tan alta, la animación irá "a saltos".

Seguro que alguna vez has hecho una animación en las hojas de un cuaderno.

Basta con pintar en cada una de ellas un dibujo, y que entre dos hojas consecutivas el personaje o elemento cambie ligeramente de posición.

Luego al pasar las hojas rápidamente se nos genera la ilusión de la animación.

En este (cutre) vídeo puedes ver un ejemplo.

Click to see the youtube video

Esto mismo lo podemos hacer digitalmente.

Basta con hacer una serie de dibujos, generar las imágenes correspondientes y visualizarlas una detrás de otra.

Por ejemplo, podemos tener la siguiente secuencia de imágenes:

A partir de ellas podemos tener un gif animado, o las podemos reproducir manualmente.

Fases

El proceso para hacer animaciones, y que se aprecie cómo los objetos se mueven suavemente por la pantalla consiste en estos pasos:

  • Actualizar las posiciones de los objetos. Cada objeto móvil tendrá unas coordenadas que van evolucionando con el tiempo. Hay que calcular sus nuevas posiciones
  • Borrar la pantalla
  • Pintar en la pantalla todos los objetos visibles
  • Repetir

Este proceso se debe realizar al menos 60 veces por segundo (frecuencia de 60Hz).

Es decir, que se dispone de unos 17ms para realizar los cálculos y pintar el nuevo frame.

Si nuestra escena a animar requiere de muchos cálculos (hay muchos elementos que se mueven), podría ocurrir que se no se tenga suficiente tiempo con 17ms para recalcular todo y pintarlo.

Si eso ocurre la frecuencia de la animación (frames/seg) será menor de 60 y el movimiento no se verá tan fluido.

Ejemplo: Cálculo de los frames por segundo

Un juego programado en javascript tarda los siguientes tiempos en realizar una serie de acciones:

  • Cálculo de la física del juego: posiciones, velocidades y aceleraciones de los objetos: 10ms
  • Borrado de la pantalla: 4ms
  • Pintar cada frame: 6ms

¿Cuáles será la frecuencia de refresco? (fps)

Solución:

El tiempo total que se requiere para obtener cada frame es de: 10 + 4 + 6 = 20ms.

Por tanto, la frecuencia de refresco será de 1/20ms = 0.05Khz = 50Hz

Elemento canvas: Dibujando gráficos 2D

En HTML disponemos de un elementos para hacer dibujos en él: El canvas (Lienzo).

Dentro de un canvas podemos realizar el dibujo que queramos, incluir texto, figuras geométricas, rectas, curvas, imágenes...

Aprenderemos a usarlo mediante ejemplos

Ejemplo 1: Creando el canvas

Comenzaremos creando un canvas vacío.

Como siempre, lo definimos en el documento HTML, dándole un identificador (display en nuestro ejemplo).

En el documento HTML situamos el elemento y su identificador, pero NO establecemos su tamaño ni su estilo.

El canvas se define mediante la etiqueta <canvas>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="canvas-01.js" defer></script>
    <link rel="stylesheet" href="canvas-01.css">
    <title>Canvas 01</title>
</head>
<body>
    <h2>Canvas</h2>
    <canvas id="canvas"></canvas>
</body>
</html>

En el fichero canvas-01.css definimos su estilo: lo bordeamos con una línea negra y establecemos el color de su fondo a azul, para distinguirlo.

También redondeamos sus esquinas.

/* Estilo del canvas
  Lo bordeamos con una línea negra y le damos fondo
  azul para distinguirlo
*/

canvas {
    background-color: lightblue;
    border-style: solid;
    border-width: 1px;
    border-color: black;
    border-radius: 5px;
  }

En el código javascript obtenemos el elemento canvas y fijamos sus dimensiones a 200x100

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;

Esto es lo que nos aparece al abrirlo en el navegador:

Ejemplo 2: Dibujando el trazo de un rectángulo

Vamos a dibujar un rectángulo en el interior del canvas.

Utilizaremos el mismo HTML y CSS que en el ejemplo anterior, pero cambiamos el código javascript.

Para poder dibujar en el canvas hay que obtener un objeto HTML especial que permite hacer dibujos, que denominamos el contexto.

El contexto lo obtenemos mediante el método getContext("2d") del canvas:

const ctx = canvas.getContext("2d");

Ahora ya podemos dibujar usando los métodos del contexto.

Cada una de los objetos a dibujar los delimitamos por los métodos ctx.beginPath() y ctx.closePath().

Para definir un rectángulo invocamos al método rect(), pasándole como parámetros las coordenadas x,y de la esquina superior izquierda, su anchura y su altura.

En este ejemplo pintaremos el trazado de un rectángulo de dimensiones 100x50, y cuya esquina superior izquierda está situada en la coordenada (5,5).

El origen de coordenadas (0,0) está situado en la esquina superior izquierda del canvas.

ctx.rect(5,5, 100, 50);

Cada elemento tiene una parte interna: el relleno (fill) y un trazo (stroke).

Para mostrar el interior usamos el método ctx.fill() y para mostrar el trazo el método ctx.stroke().

El código javascript completo es el siguiente:

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 200;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Cada objeto a dibujar lo delimitaremos 
//-- por los métodos beginPath() y closePath()
ctx.beginPath();
  //-- Definir un rectángulo de dimensiones 100x50,
  //-- cuya esquina superior izquierda está en (5,5)
  ctx.rect(5,5, 100, 50);

  //-- Color de relleno del rectángulo
  ctx.fillStyle = 'blue';

  //-- Mostrar el relleno
  ctx.fill();

  //-- Mostrar el trazo del rectángulo
  ctx.stroke();
ctx.closePath();

Y al ejecutarlo en el navegador nos aparece el rectángulo dentro del canvas:

Ejemplo 3: Trazos y relleno

Es posible dibujar tanto el relleno como el trazo, y cambiar sus propiedades.

En este ejemplo modificamos el grosor del trazo para que sea mayor, utilizando la propiedad lineWidth.

//-- Cambiar el tamaño de la línea del trazo
  ctx.lineWidth = 4;

El programa completo es el siguiente.

Primero se dibuja el relleno, con el método fill() y luego el contorno, con el método stroke().

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");


ctx.beginPath();
    //-- Definir un rectángulo de dimensiones 100x50,
    //-- cuya esquina superior izquierda está en (5,5)
    ctx.rect(5,5, 100, 50);

    //-- Dibujar
    ctx.fillStyle = 'red';

    //-- Cambiar el tamaño de la línea del trazo
    ctx.lineWidth = 4;

    //-- Rellenar
    ctx.fill();

    //-- Dibujar el trazo
    ctx.stroke()
    
ctx.closePath()

El resultado es este:

Ejemplo 4: Tirando líneas

Para dibujar líneas en el canvas se usan los métodos moveTo() y lineTo().

Con el primero se define el punto inicial de la línea.

Y con el segundo se pinta la línea hasta el punto destino.

El grosor de los trazos de las líneas se define con la propiedad lineWidth y el color con strokeStyle.

En este ejemplo se tiran 3 líneas.

La primera es una horizontal.

La siguiente es una horizontal seguida de una vertical, unidas.

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 200;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");


ctx.beginPath();
    //-- Línea horizontal
    ctx.moveTo(10, 20);
    ctx.lineTo(100, 20);

    //-- Línea horizontal y vertical, unidas
    ctx.moveTo(10, 80);
    ctx.lineTo(150,80);
    ctx.lineTo(150,20);

    ctx.strokeStyle = 'blue';
    //-- Cambiar el tamaño de la linea del trazo
    ctx.lineWidth = 4;

    //-- Dibujar el trazo
    ctx.stroke()
    
ctx.closePath()

Este es el resultado:

Ejemplo 5: Dibujando círculos

Para dibujar círculos, circunferencias y arcos usamos el método arc().

Primero hay que invocar el método beginPath(), y luego se dibujan las curvas.

En este ejemplo se dibuja un círculo con relleno amarillo y trazo azul.

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 200;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");


ctx.beginPath();
    //-- Dibujar un circulo: coordenadas x,y del centro
    //-- Radio, Angulo inicial y angulo final
    ctx.arc(100, 50, 10, 0, 2 * Math.PI);
    ctx.strokeStyle = 'blue';
    ctx.lineWidth = 3;
    ctx.fillStyle = 'yellow';

    //-- Dibujar el trazo
    ctx.stroke()

    //-- Dibujar el relleno
    ctx.fill()
    
ctx.closePath()

El resultado es:

Ejemplo 6: Poniendo textos

En el canvas podemos colocar dos tipos de texto, igual que el resto de objetos: Texto sólido (que está rellenado) y texto definido sólo por su trazo exterior (sin rellenado).

En este ejemplo se escriben en el canvas ambos texto. Usamos los métodos fillText() y strokeText().

Con la propiedad font establecemos el tamaño y el tipo de letra.

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 200;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Texto solido
ctx.font = "25px Arial";
ctx.fillStyle = 'yellow'
ctx.fillText("Texto sólido", 10, 30);

//-- Texto trazo
ctx.strokeStyle = 'blue';
ctx.font = "35px Arial";
ctx.strokeText("Texto trazo", 5, 80);

Este es el resultado:

Ejemplo 7: Poniendo imágenes

Dentro del canvas también podemos meter imágenes.

Las imágenes las colocamos dentro del fichero HTML, pero cambiamos sus propiedades de estilo modificadas para que estén deshabilitadas y NO se muestren.

Desde el programa javascript accedemos a esas imágenes y las insertamos en el canvas.

En este ejemplo insertamos una única imágen.

El fichero HTML es el siguiente:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="canvas-07.js" defer></script>
    <link rel="stylesheet" href="canvas-07.css">
    <title>Canvas 07</title>
</head>
<body>
    <h2>Canvas</h2>
    <canvas id="canvas"></canvas>
    <img src="logo-urjc.png" alt="No encontrada" id="logo-urjc">
    <p>Texto de prueba</p>
</body>
</html>

En el fichero de estilo hemos cambiado la propiedad display de la imagen a none, para que no aparezca:

/* Estilo del canvas
  Lo bordeamos con una línea negra y le damos fondo
  azul para distinguirlo
*/

canvas {
    background-color: lightblue;
    border-style: solid;
    border-width: 1px;
    border-color: black;
    border-radius: 5px;
  }

/* Imagen deshabilitada
   Se usa para leerla desde js y
   meterla en el canvas */
   #logo-urjc {
    display: none;
  }

Desde el fichero javascript accedemos al elemento imagen y usando el método drawImage() lo insertamos en el canvas, haciendo que la esquina superior izquierda de la imagen esté en la coordenada (15, 18)

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 500;
canvas.height = 250;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Leer la imagen del documento html
//-- Esta deshabilitada
var logo = document.getElementById("logo-urjc");

logo.onload = ()=> {
  //-- Insertar la imagen en el canvas, una vez que
  //-- ya esté cargada!
  ctx.drawImage(logo, 15,18);
};

Este es el resultado en el navegador:

Programando animaciones en Javascript

Como ya sabemos pintar en el canvas, podemos empezar a hacer animaciones, y mover objetos por el canvas.

Bucle principal: requestAnimationFrame()

En el bucle principal de la animación se tienen que realizar las tareas comentadas en el apartado inicial, que recordamos aquí:

  1. Actualizar las posiciones de los elementos: Cálculos relativos a la física del movimiento
  2. Borrar el canvas
  3. Pintar los elementos visibles
  4. Repetir

En el objeto window que nos proporciona la interfaz del navegador existe un método llamado requestAnimationFrame() al que se le pasa como parámetro la función que hace de bucle principal, que típicamente la denominamos la función de update (actualización)

Este método se encarga de garantizar que la actualización se hace a una frecuencia de 60Hz (siempre que sea posible)

El esqueleto de nuestros programas de animación será siempre así:

//-- Declaración de variables y objetos

//-- Obtención del canvas y de los elementos HTML a usar

//-- Función principal de actualización
function update() 
{
  //-- Implementación del algoritmo de animación:

  //-- 1) Actualizar posición de los elementos

  //-- 2) Borrar el canvas

  //-- 3) Pintar los elementos en el canvas

  //-- 4) Repetir
  requestAnimationFrame(update);
}

//-- Otras funciones....

//-- ¡Que comience la fiesta! Hay que llamar a update la primera vez
update();

Actualización de elementos: Física

Para tener elementos móviles en nuestra animación, y que parezcan reales, utilizamos las ecuaciones de la cinemática de partículas.

En cada iteración del bucle principal estas ecuaciones se deben recalcular para obtener las variables de estado de nuestros elementos: posiciones, velocidades, etc...

El movimiento más sencillo de implementar es el rectilínea uniforme.

Si nuestro elemento se está moviendo horizontalmente hay que actualizar su posición x sumándole la velocidad, que será una constante.

Si la velocidad está definida en la constante VELX, el cálculo a realizar es una simple suma:

//-- Fisica del movimiento rectilíneo uniforme horizontal
x = x + VELX;

El signo de la velocidad determina hacia dónde se desplaza el elemento: En el sentido positivo del eje de las Xs o en el negativo.

En el caso del movimiento rectilíneo uniforme bidimensional (y no sólo en línea recta) bastará con incrementar de manera independientes sus variables x,y con las velocidades en el eje vertical y horizontal: VELX, VELY:

//-- Física del movimiento rectilíneo uniforme bidimensional
x = x + VELX;
y = y + VELY;

Si lo que queremos implementar es un movimiento rectilíneo uniformemente acelerado, necesitamos una constante nueva: la aceleración en los ejes X e Y: ACCELX, ACCELY.

Ahora las velocidades NO son constantes, sino que van aumentando debido a la aceleración. Los cálculos a realizar son los siguientes:

//-- Física del movimiento uniformemente acelerado bidimensional

//-- Actualizar las posiciones según la velocidad actual
x = x + velx;
y = y + vely;

//-- Actualizar las velocidades según las aceleraciones
velx = velx + ACCELX;
vely = vely + ACCELY;

Mezclando ambos tipos de movimientos: el uniformemente acelerado y el rectilíneo uniforme obtenemos otros, como el tiro parabólico

Además de las ecuaciones que describen el tipo de movimiento, necesitamos condiciones especiales adicionales para detectar colisiones y realizar rebotes.

La física del rebote es también muy sencilla de programar: basta con comprobar la posición del elemento, y si ha llegado a la pared límite hay que cambiar el signo de su velocidad.

Así por ejemplo si hay una bola que se mueve horizontalmente hacia una pared situada en la derecha, con velocidad velx, al llegar a la posición de la pared deberemos cambiar el signo de la velocidad en el eje horizontal:

//-- Rebote en pared vertical: cambiar el signo de la velocidad x
velx = -velx;

Borrado del canvas

El borrado del canvas, para poder pintar el siguiente frame, se realiza con el método ctx.clearRect() al que le pasamos como argumentos la posición del origen y de la esquina inferior derecha.

Este método se usa para borrar un área del cavas, pero si le pasamos el área completa lo borrará todo.

La instrucción a ejecutar siempre será esta:

ctx.clearRect(0, 0, canvas.width, canvas.height);

Donde canvas es el elemento HTML del canvas.

Ejemplo 8: Animando un objeto en reposo

En este primer ejemplo mostraremos el esquema de animación, pero aplicado a un objeto que está en reposo, es decir, con velocidad 0, por lo que no se mueve.

Sin embargo el bucle principal de la animación sí está activo.

La posición del elemento la podemos cambiar manualmente, desde la consola del navegador.

En los ficheros html y css tenemos lo mismo que en los ejemplos anteriores:

  • Fichero Ej-08.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="anim-01.js" defer></script>
    <link rel="stylesheet" href="anim-01.css">
    <title>Ejemplo 8: Animación</title>
</head>
<body>
    <h2>Canvas</h2>
    <canvas id="canvas"></canvas>
</body>
</html>
  • Fichero anim-01.css
/* Estilo del canvas
  Lo bordeamos con una línea negra y le damos fondo
  azul para distinguirlo
*/

canvas {
    background-color: lightblue;
    border-style: solid;
    border-width: 1px;
    border-color: black;
    border-radius: 5px;
  }
  • Fichero anim-01.js
console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Posición del elemento a animar
let x = 0;
let y = 0;

//-- Función principal de animación
function update() 
{
  console.log("test");
  //-- Algoritmo de animación:
  //-- 1) Actualizar posiciones de los elementos
  //-- Por hacer

  //-- 2) Borrar el canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  //-- 3) Dibujar los elementos visibles
  ctx.beginPath();
    ctx.rect(x, y, 20, 20);

    //-- Dibujar
    ctx.fillStyle = 'red';

    //-- Rellenar
    ctx.fill();

    //-- Dibujar el trazo
    ctx.stroke()
  ctx.closePath();

  //-- 4) Volver a ejecutar update cuando toque
  requestAnimationFrame(update);
}

//-- ¡Que empiece la función!
update();

Se definen las variables x,y para almacenar la posición del elemento. En la función principal (update) se imprime un mensaje en la consola (test) para comprobar que está funcionando.

Como el elemento está en reposo, no se actualiza su posición. O visto de otra manera, al ser la velocidad 0 la actualización de sus coordenadas sería:

//-- El objeto está en reposo (velocidad = 0)
x = x + 0;
y = y + 0;

El elemento a animar está constantemente siendo redibujado, pero siempre en la misma posición, por eso no vemos movimiento:

Al ejecutarlo observamos en la consola que efectivamente el mensaje de test está siendo constantemente actualizado.

Si ahora desde la consola cambiamos las coordenadas del objeto, asignando valores a x,y, veremos cómo efectivamente cambia de posición, aunque sigue en reposo, sin moverse.

Ejemplo 9: Movimiento horizontal de un rectángulo

Para lograr que el rectángulo se mueva con movimiento rectilínea uniforme, horizontalmente, sólo hay que asignarle una velocidad en x, e implementar su física correspondiente dentro de la función update()

Los cambios son los siguientes. Primero definimos la variable de la velocidad: velx

//-- Velocidad horizontal del objeto
let velx = 1;

Y ahora implementamos su física:

 //-- (física del movimiento rectilíneo uniforme)
  x = x + velx;

Este es el código completo:

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Coordenadas del objeto
let x = 0;
let y = 10;

//-- Velocidad horizontal del objeto
let velx = 1;

//-- Función principal de animacion
function update() 
{
  console.log("test");
  //-- Algoritmo de animacion:
  //-- 1) Actualizar posicion del  elemento
  //-- (física del movimiento rectilineo uniforme)
  x = x + velx;

  //-- 2) Borrar el canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  //-- 3) Dibujar los elementos visibles
  ctx.beginPath();
    ctx.rect(x, y, 20, 20);

    //-- Dibujar
    ctx.fillStyle = 'red';

    //-- Rellenar
    ctx.fill();

    //-- Dibujar el trazo
    ctx.stroke()
  ctx.closePath();

  //-- 4) Volver a ejecutar update cuando toque
  requestAnimationFrame(update);
}

//-- ¡Que empiece la función!
update();

Al recargar la página veremos cómo el rectángulo rojo se mueve hacia la derecha

Desde la consola podemos controlar su física.

Asignamos el valor x = 0 para volver al inicio, y cambiamos la velocidad a diferentes valores para comprobar que efectivamente se mueve más rápidamente: velx = 2, velx = 5,...

¡Ya tenemos nuestra primera animación! 😀️

Ejemplo 10: Rebote del rectángulo

Vamos a modificar la física para que cuando el rectángulo alcance la posición de la derecha del canvas, rebote y vuelva hacia atrás.

Para lograr este rebote hay que detectar primero cuándo se alcanza el borde derecho y luego cambiar de signo su velocidad

Añadimos esto en la física:

//-- Comprobar colisión con borde derecho
  //-- Si se alcanza la anchura del canvas, se cambia la velocidad
  //-- de signo (rebote)
  if (x >= canvas.width) {
    velx = -velx;
  }

También modificamos la velocidad inicial a 2, para que vaya más rápido.

El código final que nos queda es este:

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Coordenadas del objeto
let x = 0;
let y = 10;

//-- Velocidad horizontal del objeto
let velx = 2;

//-- Funcion principal de animacion
function update() 
{
  console.log("test");
  //-- Algoritmo de animacion:
  //-- 1) Actualizar posicion del  elemento
  //-- (física del movimiento rectilineo uniforme)

  //-- Comprobar colisión con borde derecho
  //-- Si se alcanza la anchura del canvas, se cambia la velocidad
  //-- de signo (rebote)
  if (x >= canvas.width) {
    velx = -velx;
  }

  //-- Actualizar la posición
  x = x + velx;

  //-- 2) Borrar el canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  //-- 3) Dibujar los elementos visibles
  ctx.beginPath();
    ctx.rect(x, y, 20, 20);

    //-- Dibujar
    ctx.fillStyle = 'red';

    //-- Rellenar
    ctx.fill();

    //-- Dibujar el trazo
    ctx.stroke()
  ctx.closePath();

  //-- 4) Volver a ejecutar update cuando toque
  requestAnimationFrame(update);
}

//-- ¡Que empiece la función!
update();

Al recargar la página vemos su funcionamiento.

Efectivamente ahora el rectángulo rebota al llegar al extremo derecho del canvas:

Ejemplo 11: Rectángulo confinado horizontalmente

Para que nuestro rectángulo se quede confinado dentro del canvas, rebotando a izquierda y derecha indefinidamente, sólo hay que añadir la condición de comprobación de que el borde izquierdo se ha alcanzado.

Esto ocurre cuando su posición x sea menor que 0

 //-- Condicion de rebote en extremos del canvas
  if (x < 0 || x >= (canvas.width - 20) ) {
    velx = -velx;
  }
  • Código completo:
console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Coordenadas del objeto
let x = 0;
let y = 10;

//-- Velocidad horizontal del objeto
let velx = 3;

//-- Funcion principal de animacion
function update() 
{
  console.log("test");
  //-- Algoritmo de animacion:
  //-- 1) Actualizar posición del  elemento
  //-- (física del movimiento rectilineo uniforme)

   //-- Condicion de rebote en extremos del canvas
   if (x < 0 || x >= (canvas.width - 20) ) {
    velx = -velx;
  }

  //-- Actualizar la posición
  x = x + velx;

  //-- 2) Borrar el canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  //-- 3) Dibujar los elementos visibles
  ctx.beginPath();
    ctx.rect(x, y, 20, 20);

    //-- Dibujar
    ctx.fillStyle = 'red';

    //-- Rellenar
    ctx.fill();

    //-- Dibujar el trazo
    ctx.stroke()
  ctx.closePath();

  //-- 4) Volver a ejecutar update cuando toque
  requestAnimationFrame(update);
}

//-- ¡Que empiece la función!
update();

En esta animación vemos el funcionamiento.

Ahora nuestro rectángulo está confinado dentro de los límites del canvas...

Ejemplo 12: Movimiento rectilíneo uniforme bidimensional

Para que nuestro rectángulo se mueva en línea recta pero en cualquier dirección, y no sólo horizontalmente, hay que superponer el movimiento en el eje y.

Tenemos que definir ambas velocidades: la horizontal y la vertical.

Vamos a darle un valor bajo a la vertical:

//-- Velocidades del objeto
let velx = 3;
let vely = 0.2;

Y su física hay que añadir la actualización de la variable y:

//-- Actualizar la posición
  x = x + velx;
  y = y + vely;
  • Código completo:
console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Coordenadas del objeto
let x = 0;
let y = 10;

//-- Velocidades del objeto
let velx = 3;
let vely = 0.2;

//-- Función principal de animación
function update() 
{
  console.log("test");
  //-- Algoritmo de animacion:
  //-- 1) Actualizar posicion del  elemento
  //-- (física del movimiento rectilineo uniforme)

   //-- Condición de rebote en extremos del canvas
   if (x < 0 || x >= (canvas.width - 20) ) {
    velx = -velx;
  }

  //-- Actualizar la posición
  x = x + velx;
  y = y + vely;

  //-- 2) Borrar el canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  //-- 3) Dibujar los elementos visibles
  ctx.beginPath();
    ctx.rect(x, y, 20, 20);

    //-- Dibujar
    ctx.fillStyle = 'red';

    //-- Rellenar
    ctx.fill();

    //-- Dibujar el trazo
    ctx.stroke()
  ctx.closePath();

  //-- 4) Volver a ejecutar update cuando toque
  requestAnimationFrame(update);
}

//-- ¡Que empiece la función!
update();

En la animación vemos el resultado.

Nuestro objeto se mueve también verticalmente, pero con velocidad más lenta.

Ejemplo 13: Rectángulo rebotando dentro del canvas en 2D

Para terminar, haremos que nuestro rectángulo se quede confinado dentro del canvas, rebotando tanto en los límites verticales como horizontales del canvas.

Basta con añadir las condiciones para la coordenada y:

//-- Condición de rebote en extremos horizontales del canvas
  if (y <= 0 || y > 80) {
    vely = -vely;
  }

Además cambiamos los valores de las velocidades, para que se mueva más rápido por el eje y:

//-- Velocidades del objeto
let velx = 3;
let vely = 1;

El código completo queda así:

console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Coordenadas del objeto
let x = 0;
let y = 10;

//-- Velocidades del objeto
let velx = 3;
let vely = 1;

//-- Función principal de animación
function update() 
{
  console.log("test");
  //-- Algoritmo de animacion:
  //-- 1) Actualizar posición del  elemento
  //-- (física del movimiento rectilineo uniforme)

   //-- Condición de rebote en extremos verticales del canvas
   if (x < 0 || x >= (canvas.width - 20) ) {
    velx = -velx;
  }

  //-- Condición de rebote en extremos horizontales del canvas
  if (y <= 0 || y > 80) {
    vely = -vely;
  }

  //-- Actualizar la posición
  x = x + velx;
  y = y + vely;

  //-- 2) Borrar el canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  //-- 3) Dibujar los elementos visibles
  ctx.beginPath();
    ctx.rect(x, y, 20, 20);

    //-- Dibujar
    ctx.fillStyle = 'red';

    //-- Rellenar
    ctx.fill();

    //-- Dibujar el trazo
    ctx.stroke()
  ctx.closePath();

  //-- 4) Volver a ejecutar update cuando toque
  requestAnimationFrame(update);
}

//-- ¡Que empiece la función!
update();

Y este es el resultado:

Autor

Jesús Parrado Alameda (jesusgpa)

Creditos

Licencia

Enlaces

Página principal


Teoría

Práctica 0: Herramientas

Práctica 1: CV

Práctica 2: Calculadora

Práctica 3: Videojuego retro

Práctica 4: Procesado de imagen

Práctica 5: Vídeo

Examenes

Curso 2021/2022

  • [2022 - 15 de Marzo: Parcial 1 ]
  • [2022 - 19 de Mayo: Parcial 2 ]
  • [2022 - 2 de Julio: Final. Conv. extraordinaria ]
Clone this wiki locally