jardínBit

Animación básica con acumuladores

Podemos crear animaciones parametrizando nuestros dibujos con variables que se comporten como acumuladores: variables a las que en cada frame de animación se les incremente o decremente una cantidad.

[Variables: Contadores, Acumuladores, Banderas]

1 Velocidad constante

1.1 Crecimiento indefinido

Podemos tener un acumulador que se incremente indefinidamente.

Un posible uso es mover una serie de figuras dibujadas respecto a esa variable.

// par de cuadrados que descienden poco a poco,
// el segundo se revela después de un tiempo
float y;
void setup(){
 size(400, 400);
 y = 0;
}

void draw(){
  background(0);
 // dibujos respecto a "y":
 // este cuadrado empieza en el lienzo:
 rect(100, y, 50, 50);
 // este cuadrado empieza 200 pixeles arriba del lienzo:
 rect(200, y-200, 50, 50); 
 
 // incremento de "y":
 y = y + 0.5;
}

1.2 Crece y reinicia

En ocasiones queremos reiniciar el acumulador cuando se cumple cierta condición; para esto usamos expresiones condicionales.

[Expresiones condicionales]

// cuadrado que desciende y al llegar abajo reinicia hasta arriba
float y;
void setup(){
 size(400, 400);
 y = -50;
}

void draw(){
  background(0);
 // cuadrado dibujado respecto a "y":
 rect(150, y, 50, 50);
 
 // incremento de "y":
 y = y + 2;

 // reinicia "y" cuando sea mayor o igual a height
 if( y >= height){
  y = -50; 
 }
}

1.3 Rebote

En otros casos buscaremos que la dirección de crecimiento cambie y se mantenga hasta que se cumpla cierta condición límite.

1.3.1 Rebote con bandera (flag)

Podemos usar una variable como bandera (flag) que indique la dirección de movimiento y que le sirva al programa para determinar si ha de incrementar o decrementar a nuestro acumulador..

Esta variable la invertimos en las condiciones límite. Nota el uso del operador NOT (!) para invertir el valor booleano.

[Variables y expresiones booleanas]

float y;
boolean avanza;
void setup() {
  size(400, 400);
  y = 0;
  avanza = true;
}

void draw() {
  background(0);
  // cuadrado dibujado respecto a "y":
  rect(150, y, 50, 50);

  if (avanza) { // si "avanza" es true...
    y = y + 2; // incrementa
  } else { // si no...
    y = y - 2; // decrementa
  }

  // invierte dirección al llegar a los bordes
  // "si la posición es mayor a cierto límite,
  // o si es menor a otro límite, invierte"
  if ( y >= height-50 || y<= 0) {
    avanza = !avanza;
  }
}

1.3.2 Rebote con velocidad en variable

El incremento al acumulador puede ser una variable que cambia de signo en las condiciones límite.

En lugar de tener lo siguiente para cada dirección:

y = y + 2; // incrementa

y = y - 2; // decrementa

Usamos una variable a la que nombramos vely para referirnos al 2 o al -2:

y = y + vely; // vely será 2 o -2

Aquí el programa completo:

float y;
float vely; // esta variable es el incremento al acumulador

void setup() {
  size(400, 400);
  y = 0;
  vely = 2; // valor inicial de velocidad
}

void draw() {
  background(0);
  // cuadrado dibujado respecto a "y":
  rect(150, y, 50, 50);

  // incrementa/decrementa la posición
  y = y + vely;

  // invierte velocidad al llegar a los bordes
  if ( y >= height-50 || y<= 0) {
    vely = -vely;
  }
}

2 Velocidad variable

Asignar el incremento de nuestro acumulador a una variable nos permite otros comportamientos.

2.1 Aceleración

La aceleración sucede al incrementar en cada frame la cantidad que estamos incrementando a nuestro acumulador original.

2.1.1 Caída con rebote

Este ejemplo tiene un acumulador para la posición y cuyo incremento es dado por vely, y a su vez vely es incrementado en cada frame.

Al llegar al borde inferior, el signo de la velocidad se invierte.

float y;
float vely;
void setup() {
  size(400, 400);
  y = 0;
  vely = 0;
}

void draw() {
  background(0);
  // cuadrado dibujado respecto a "y":
  rect(150, y, 50, 50);

  // incrementamos el acumulador
  y = y + vely;
  // incrementamos la velocidad
  vely = vely + 0.01;

  // rebota al llegar al borde
  if ( y >= height-50) {
    vely = -vely;
  }
}

¿Qué valor habría que asignarle a vely cuando y llega al borde, para que el cuadrado se detenga?

¿Qué pasa si escribes una expresión condicional para que una tecla le asigne a vely un valor negativo?

2.2 Duda aleatoria

El incremento a nuestro acumulador puede cambiar aleatoriamente en cada frame

float y;
float vely;
void setup() {
  size(400, 400);
  y = 0;
  vely = 0;
}

void draw() {
  background(0);
  // cuadrado dibujado respecto a "y":
  rect(150, y, 50, 50);

  // incrementamos el acumulador
  y = y + vely;
  // asignamos una velocidad aleatoria
  vely = random(-1, 2);
}