Lanzar la pelota

facebook-svg gplus-svg twitter-svg

Algunas cosas necesarias:

Necesitamos utilizar la función oMousePos() que detecta la posición del ratón en el canvas y devuelve un objeto con las coordinadas x e y de este.
También necesitamos dos boléanos, cuyo valor al inicio es false: ni arrastramos ni lanzamos la pelota.

var arrastrar = false;
var lanzar = false;

La gravedad, una fuerza que, como en el mundo real, hace que la pelota se caiga.

var gravedad = .5;

Y el rebote: una fuerza cuyo valor es > -1 para frenar la pelota al rebotar contra las paredes:

var rebote = -.5;

Inicializamos la posición del ratón en un punto cualquiera del canvas

var m = {
 x: cx,
 y: cy
};

También declaramos otras dos variables:

var dx,dy;

¿Para que las necesitamos? Cuando hacemos clic en la pelota, no lo hacemos casi nunca en el centro del objeto. Así que necesitamos calcular la distancia entre este punto (dx,dy) y el centro de la pelota.

La pelota

Para crear el objeto pelota utilizamos la siguiente función ( de hecho un constructor ):


function Pelota(r){
	// el radio de la pelota
	this.r = r;
	// las coordenadas de la pelota
	this.x = 1.2*this.r;
	this.y = ch - this.r;
	// las coordenadas iniciales de la pelota
	this.inicial_x = this.x;
	this.inicial_y = this.y;
	// la velocidad de la pelota
	this.vx = 0;
	this.vy = 0;
	// el color de la pelota
	this.color = "#6ab150";
}

También necesitamos un método para dibujar la pelota:


Pelota.prototype.dibujar = function() {
  // dibuja la pelota
  ctx.fillStyle = this.color;
  ctx.beginPath();
  ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
  ctx.fill();
  //cambia el estilo del cursor si el ratón esta encima de la pelota
  if (ctx.isPointInPath(m.x, m.y)) {
    canvas.style.cursor = "pointer";
  } else {
    canvas.style.cursor = "default";
  }
}

Necesitamos otro método para arrastrar la pelota. Este método toma como argumento la posición del ratón m:


Pelota.prototype.arrastrar = function(m) {
  // calcula las nuevas coordenadas de la pelota
  this.x = m.x + dx;
  this.y = m.y + dy;
  // calcula la velocidad (vx y vy) de la pelota mientras la arrastramos
  this.vx = this.x - this.inicial_x;
  this.vy = this.y - this.inicial_y;
  // actualiza el valor inicial
  this.inicial_x = this.x;
  this.inicial_y = this.y;
}

También necesitamos un método para lanzar la pelota. También toma como argumento la posición del ratón m:


Pelota.prototype.lanzar = function(m) {
  this.vy += gravedad;
  this.x += this.vx;
  this.y += this.vy;

  this.colisionParedes();
}

Veamos el método colisionParedes(), que controla el comportamiento de la pelota al colisionar contra las paredes.  Este método comprueba si la pelota toca alguna de la paredes. Por ejemplo esta parte comprueba si la pelota empieza a salirse por la derecha del canvas.

if (this.x > cw - this.r) {
   // no hay que dejarla salir
   this.x = cw - this.r;
   // cambia de dirección y frena la pelota
   this.vx *= rebote;
}

Si la pelota empieza a salirse del canvas, rebota: o sea cambia de dirección, ya que la variable rebote tiene un valor negativo.

var rebote = -.5;
this.vx *= rebote;
Además el valor es > -1, y esto frena la pelota.


Pelota.prototype.colisionParedes = function() {
  if (this.x > cw - this.r) {
    this.x = cw - this.r;
    this.vx *= rebote;

  } else if (this.x < this.r) {
    this.x = this.r;
    this.vx *= rebote;
  }
  if (this.y > ch - this.r) {
    this.y = ch - this.r;
    this.vy *= rebote;

  } else if (this.y < this.r) {
    this.y = this.r
    this.vy *= rebote;
  }
}

Los eventos a utilizar

1. Presionar el botón del ratón, para coger la pelota. El evento del ratón involucrado en este caso es mousedown ( literalmente : ratón abajo ).

canvas.addEventListener("mousedown", function(evt) {
// detecta la posición del ratón
m = oMousePos(canvas, evt);
// porque no hacemos casi nunca clic en el centro de la pelota
// tenemos que calcular la distancia entre el centro de esta y el ratón
dx = pelota.x - m.x;
dy = pelota.y - m.y;
ctx.clearRect(0,0,cw,ch);
pelota.dibujar();
// si hemos hecho clic en la pelota, podemos arrastrar
if (ctx.isPointInPath(m.x, m.y)) {
arrastrar = true;
}
},false);

2. Mantener presionado el botón del ratón y arrastrar la pelota. El evento del ratón involucrado en este caso es mousemove (literalmente : ratón moviéndose). En esta etapa también tenemos que calcular la velocidad de la pelota.

canvas.addEventListener("mousemove", function(evt) {
// limpia el canvas
ctx.clearRect(0,0,cw,ch);
//dibuja la pelota. 
pelota.dibujar();
// detecta la posición del ratón
m = oMousePos(canvas, evt);
},false);

3.Lanzar el objeto arrastrado, soltando el botón del ratón. El evento del ratón involucrado en este caso es mouseup ( literalmente : ratón arriba ). La pelota continua su trayectoria. Desde este momento tenemos que tener en cuenta la gravedad.

canvas.addEventListener("mouseup", function(evt) {
// ya no arrastramos la pelota
arrastrar = false;
// la lanzamos
lanzar = true;
},false);

4. Pasa lo mismo si salimas del canvas: El evento del ratón involucrado es mouseout ( literalmente : ratón fuera ).

canvas.addEventListener("mouseout ", function(evt) {
// ya no arrastramos la pelota
arrastrar = false;
// la lanzamos
lanzar = true;
},false);

La animación

La función animacion es una función recurrente, o sea una función que vuelve a llamarse a si misma.

Lea más sobre animaciones en canvas.

Si el booleano arrastrar == true, arrastra la pelota (pelota.arrastrar(m)). Su por contra el booleano lanzar == true, lanza la pelota (pelota.lanzar(m)).
Al final limpia el canvas y dibuja la pelota.


function Animacion() {
  elId = window.requestAnimationFrame(Animacion);
  if (arrastrar) {
    pelota.arrastrar(m);
  }
  if (lanzar) {
    pelota.lanzar(m);
  }
  // limpia el canvas
  ctx.clearRect(0, 0, cw, ch);
  //dibuja la pelota
  pelota.dibujar();
}
//llama una primera vez la función Animacion
Animacion();

Lo ponemos todo junto

Es recomendable abrirlo y manosearlo en codepen.io

See the Pen lanzar la pelota* by Gabi (@enxaneta) on CodePen.