If you're seeing this message, it means we're having trouble loading external resources on our website.

Si estás detrás de un filtro de páginas web, por favor asegúrate de que los dominios *.kastatic.org y *.kasandbox.org estén desbloqueados.

Contenido principal

Movimiento de vectores

Todo esto de matemáticas vectoriales suena a algo que deberíamos saber, pero ¿por qué? ¿Cómo es que en realidad nos va a ayudar a escribir código? La verdad de las cosas es que necesitamos tener un poco de paciencia. Va a tomar un poco de tiempo antes de que la genialidad de usar la clase PVector salga a la luz.
Esto en realidad es una ocurrencia común cuando se está aprendiendo una nueva estructura de datos. Por ejemplo, la primera vez que aprendiste acerca de un arreglo, parecía que era más trabajo usar un arreglo que solo tener varias variables que representaran varias cosas. Pero ese plan deja de ser útil rápidamente cuando necesitas cientos o miles o decenas de miles de cosas.
Lo mismo puede ser cierto para PVector. Lo que por ahora puede parecer más trabajo rendirá frutos más adelante, y de manera muy buena. Y no tienes que esperar mucho, ya que tu recompensa llegará en el siguiente capítulo.

La velocidad

Sin embargo, por ahora, queremos enfocarnos en lo sencillo. ¿Qué significa programar movimiento usando vectores? Vimos el principio de esto en el ejemplo de la pelota que rebota. Un objeto en la pantalla tiene una posición (dónde está en un momento dado) así como una velocidad (instrucciones de cómo se debe mover de un momento a otro). La velocidad se le suma a la posición:
position.add(velocity);
Y luego dibujamos el objeto en esa posición:
ellipse(position.x, position.y, 16, 16);
Esto es lo básico del movimiento:
  • Sumarle la velocidad a la posición
  • Dibujar el objeto en la posición
En el ejemplo de la pelota que rebota, todo este código estaba dentro de la función draw de ProcessingJS. Lo que queremos hacer ahora es encapsular toda la lógica del movimiento dentro de un objeto. De esta manera, podemos crear una base para la programación de objetos que se mueven en todos nuestros programas de ProcessingJS.
En este caso, vamos a crear un objeto general Mover (objeto móvil en inglés) que describirá una cosa que se mueve en la pantalla. Así que debemos considerar las siguientes dos preguntas:
  • ¿Qué datos tiene un mover?
  • ¿Qué funcionalidad tiene un mover?
Nuestro algoritmo básico de movimiento nos da las respuestas a estas preguntas. Un objeto Mover tiene dos piezas de información: posición y velocidad, los cuales son ambos objetos PVector. Podemos empezar por escribir la función constructora que inicializa esas propiedades con valores aleatorios apropiados:
var Mover = function() {
  this.position = new PVector(random(width), random(height));
  this.velocity = new PVector(random(-2, 2), random(-2, 2));
};
Su funcionalidad es casi igual de sencilla. Un Mover necesita moverse y necesita ser visto. Implementaremos estas necesidades como métodos denominados update() (actualizar) y display() (desplegar). Pondremos todo nuestro código de lógica de movimiento en update() y dibujaremos el objeto en display().
Mover.prototype.update = function() {
  this.position.add(this.velocity);
};

Mover.prototype.display = function() {
  stroke(0);
  strokeWeight(2);
  fill(127);
  ellipse(this.position.x, this.position.y, 48, 48);
};
Si la programación orientada a objetos es totalmente nueva para ti, un aspecto aquí podrá parecer un poco confuso. Después de todo, pasamos el principio de este capítulo hablando de PVector. El objeto PVector es la plantilla para hacer el objeto de posición y el objeto de velocidad. Entonces, ¿qué están haciendo dentro de otro objeto, el objeto Mover? De hecho, esto es lo más normal del mundo. Un objeto es simplemente algo que contiene datos (y funcionalidad). ¡Esos datos pueden ser números, cadenas de caracteres, arreglos u otros objetos! Vamos a ver esto una y otra vez durante este curso. Por ejemplo, en la lección de partículas, escribiremos un objeto para describir un sistema de partículas. Ese objeto ParticleSystem (sistema de partículas), tendrá como datos un arreglo de objetos Particle (partículas), ¡y cada objeto Particle tendrá como datos varios objetos PVector!
Terminemos el objeto Mover al incorporar una función para determinar lo que debe hacer el objeto cuando llega al borde de la pantalla. Por ahora hagamos algo sencillo, que aparezca del otro lado:
Mover.prototype.checkEdges = function() {

  if (this.position.x > width) {
    this.position.x = 0;
  } 
  else if (this.position.x < 0) {
    this.position.x = width;
  }

  if (this.position.y > height) {
    this.position.y = 0;
  } 
  else if (this.position.y < 0) {
    this.position.y = height;
  }
};
Ahora que el objeto Mover está terminado, podemos ver lo que tenemos que hacer en nuestro programa principal. Primero declaramos e inicializamos una nueva instancia de Mover:
var mover = new Mover();
Luego llamamos las funciones apropiadas en draw:
draw = function() {
  background(255, 255, 255);

  mover.update();
  mover.checkEdges();
  mover.display(); 
};
Aquí esta el ejemplo completo. Intenta jugar con los números, comentar el código y ver qué pasa:

La aceleración

Bien. En este punto, debemos sentirnos cómodos con dos cosas: (1) qué es un PVector y (2) cómo usamos PVectors dentro de un objeto para llevar el seguimiento de su posición y movimiento. Este es un excelente primer paso y merece un aplauso. Sin embargo, antes de las ovaciones y los gritos de los fans, tenemos que dar un paso más grande hacia adelante. Después de todo, ver el ejemplo básico de movimiento es bastante aburrido: el círculo nunca se acelera, nunca se frena y nunca gira. Para un movimiento más interesante, un movimiento que aparece en el mundo real a nuestro alrededor, tenemos que añadirle un PVector más a nuestro objeto Mover: aceleración.
La definición estricta de aceleración que estamos usando aquí es: la tasa de cambio de la velocidad. Pensemos en esa definición por un momento. ¿Este es un concepto nuevo? Realmente no. La velocidad se define como la tasa de cambio de la posición. En esencia, estamos desarrollando un efecto de “escurrimiento”. La aceleración afecta a la velocidad, que a su vez afecta a la posición (como anuncio breve, este punto se volverá aún más importante en el siguiente capítulo, cuando veamos cómo las fuerzas afectan a la aceleración, la cual afecta a la velocidad, la cual afecta a la posición). En el código, esto se ve así:
velocity.add(acceleration);
position.add(velocity);
Como ejercicio, de ahora en adelante, hagamos una regla para nosotros mismos. Vamos a escribir cada ejemplo en el resto de estas lecciones sin tocar el valor de velocidad y posición (excepto para inicializarlos). En otras palabras, nuestra meta para la programación de movimiento ahora es: proponer un algoritmo de cómo calcular la aceleración y dejar que el efecto de escurrimiento haga su magia. (En realidad, encontrarás razones para romper esta regla, pero es importante ilustrar los principios detrás de nuestro algoritmo de movimiento). Así que tenemos que idear algunas formas de calcular la aceleración:
  1. Una aceleración constante
  2. Una aceleración totalmente aleatoria
  3. Una aceleración hacia el ratón
Algoritmo #1, una aceleración constante, no es particularmente interesante, pero es el más sencillo y nos ayudará a empezar a incorporar la aceleración en nuestro código.
Lo primero que tenemos que hacer es añadirle otra propiedad de PVector al constructor de Mover para representar la aceleración. La inicializaremos a (0.001,0.01) y mantendremos ese valor para siempre, ya que nuestro algoritmo actual es aceleración constante. Podrías estar pensando, “¡Vaya, esos valores parecen muy pequeños!” Es cierto, son bastante pequeños. Es importante tener en cuenta que nuestros valores de aceleración (medidos en pixeles) se acumularán con el tiempo en la velocidad, aproximadamente treinta veces por segundo dependiendo de los cuadros por segundo de nuestro dibujo. Así que para mantener la magnitud del vector velocidad dentro de un rango razonable, nuestros valores de aceleración deben inicializarse y permanecer muy pequeños.
var Mover = function() {
  this.position = new PVector(width/2,height/2);
  this.velocity = new PVector(0, 0);
  this.acceleration = new PVector(-0.001, 0.01);
};
Observa que arriba también inicializamos la velocidad en 0 (porque sabemos que la estaremos aumentando a medida que se ejecute el programa, debido a la aceleración). Haremos eso en el método update():
Mover.prototype.update = function() {
  this.velocity.add(this.acceleration);
  this.position.add(this.velocity);  
};
Como estamos aumentando la velocidad continuamente, corremos el riesgo de que nuestros valores de velocidad se vuelvan increíblemente grandes si dejamos que el programa se ejecute suficiente tiempo. Queremos ponerle un límite máximo a la velocidad. Podemos hacer eso usando el método de PVector limit, que restringe un vector a una magnitud dada.
Mover.prototype.update = function() {
  this.velocity.add(this.acceleration);
  this.velocity.limit(10);
  this.position.add(this.velocity);  
};
Esto se traduce en lo siguiente:
¿Cuál es la magnitud de la velocidad? Si es menor a 10, no te preocupes; déjala como está. Sin embargo, si es mayor a 10, ¡redúcela a 10!
Echemos un vistazo a los cambios al objeto Mover, incluidos acceleration y limit():
Ahora el algoritmo #2, una aceleración totalmente aleatoria. En este caso, en lugar de inicializar la aceleración en el constructor del objeto, queremos elegir una nueva aceleración en cada ciclo, es decir, cada vez que llamamos update().
Mover.prototype.update = function() {
  this.acceleration = PVector.random2D();
  this.velocity.add(this.acceleration);
  this.velocity.limit(10);
  this.position.add(this.velocity);  
};
Como el vector aleatorio está normalizado, podemos intentar escalarlo con dos técnicas diferentes:
  1. escalar la aceleración a un valor constante:
    acceleration = PVector.random2D();
    acceleration.mult(0.5);
    
  1. escalar la aceleración a un valor aleatorio:
    acceleration = PVector.random2D();
    acceleration.mult(random(2));
    
Aunque esto puede parecer algo obvio, es fundamental entender que la aceleración no se refiere simplemente a que un objeto en movimiento vaya más rápido o más lento , sino más bien cualquier cambio en la velocidad, ya sea en magnitud o dirección. La aceleración se utiliza para dirigir un objeto, y veremos esto una y otra vez en los siguientes capítulos conforme comencemos a programar objetos que toman decisiones sobre cómo moverse en la pantalla.

Este curso de "Simulaciones Naturales" es un derivado de "La Naturaleza del Código" por Daniel Shiffman, usado bajo una Licencia Creative Commons Reconocimiento-NoComercial 3.0 Unported.

¿Quieres unirte a la conversación?

  • Avatar hopper cool style para el usuario azulito1
    que debo hacer en el paso 3 del desafió automóvil
    (4 votos)
    Avatar Default Khan Academy avatar para el usuario
  • Avatar blobby green style para el usuario die.ar.90
    como hacer el segundo paso del desafio visualizador de magnitud
    (3 votos)
    Avatar Default Khan Academy avatar para el usuario
  • Avatar piceratops ultimate style para el usuario Moritz Zeller
    El coche sigue moviendose ligeramente hacia la izquierda. Alguien me puede ayudar ?

    my car still moves to the left side and o dont understand whym could someone help me please.

    var Car = function() {
    this.position = new PVector(width/2, height/2);
    this.velocity = new PVector(0, 0);
    this.acceleration = new PVector(0, 0);
    };

    Car.prototype.update = function() {
    this.velocity.add(this.acceleration);
    this.velocity.limit(10);
    this.position.add(this.velocity);
    if ( this.velocity.x < 0 ) {
    this.velocity.set(0, 0);
    }
    };

    Car.prototype.display = function() {
    stroke(0);
    strokeWeight(2);
    fill(255, 0, 0);
    rect(this.position.x-52, this.position.y-59, 60, 60);
    rect(this.position.x-74, this.position.y-30, 100, 31);
    fill(92, 92, 92);
    ellipse(this.position.x, this.position.y, 30, 26);
    ellipse(this.position.x-50, this.position.y, 30, 30);
    };

    Car.prototype.checkEdges = function() {
    if (this.position.x > width) {
    this.position.x = 0;
    }
    else if (this.position.x < 0) {
    this.position.x = width;
    }
    };

    var car = new Car();

    draw = function() {

    background(255, 255, 255);
    car.update();
    car.checkEdges();
    car.display();
    if ( keyIsPressed && keyCode === 39) {
    car.acceleration.set(0.1, 0);
    } else if (keyIsPressed && keyCode === 37) {
    car.acceleration.set(-0.01, 0);
    } else {
    car.acceleration.set(0, 0);
    }
    };
    (2 votos)
    Avatar Default Khan Academy avatar para el usuario
¿Sabes inglés? Haz clic aquí para ver más discusiones en el sitio en inglés de Khan Academy.