---
title: "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]](/notas/variables-modos.html)

# Velocidad constante

## Crecimiento indefinido

Podemos tener un acumulador que se incremente indefinidamente. 

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

```java
// 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;
}
```

## Crece y reinicia

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

[[Expresiones condicionales]](/notas/condicionales.html)

```java
// 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; 
 }
}
```

## Rebote

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

### 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]](/notas/boolean.html)

```java
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;
  }
}
```

### 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:

```java
y = y + 2; // incrementa

y = y - 2; // decrementa
```

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

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

Aquí el programa completo:

```java
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;
  }
}
```

# Velocidad variable

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

## Aceleración

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

### 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.

```java
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?

## Duda aleatoria

El incremento a nuestro acumulador puede cambiar aleatoriamente en cada *frame*

```java
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);
}
```
