2017/10/26

Primeros pasos con p5.js

p5.js es una biblioteca de JavaScript que nos permite escribir sketches de una forma muy parecida a Processing. En este artículo voy a explicar, de la manera más resumida posible, qué se necesita para empezar a usar p5.js.

1. Lo primero que necesitamos es una carpeta donde meter todos los archivos que tendrá nuestro proyecto.


2. Dentro de la carpeta creamos un primer archivo de texto que llamaremos index.html





3. Editamos nuestro archivo index.html para darle la estructura básica de una página web. Podemos usar cualquier editor de texto pero es recomendable tener uno diseñado para ayudarnos a escribir código, como Sublime Text. Si ejecutamos nuestro archivo podremos ver nuestra web en un navegador de internet.




4. Añadimos a la carpeta de nuestro proyecto el archivo p5.js que podemos descargarnos aquí.


5. Creamos un tercer archivo de texto en nuestra carpeta que podemos llamar code.js.


6. Volvemos a la edición del archivo index.html para añadir los dos scripts que enlazarán la página web que hemos creado en el punto 2 con los dos archivos .js descritos en los puntos 4 y 5.



8. Ahora ya podemos editar el archivo code.js que es donde escribiremos nuestro sketch.



Una buena forma de trabajar es dividir la pantalla en dos ventanas y dedicar la parte derecha a escribir código y la izquierda a visualizar el resultado en un navegador, tal como se muestra en las imágenes anteriores.

Código html:
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8"/>
    <title>Mi primer sketch p5.js</title>
    <script src="p5.js"></script>
    <script src="code.js"></script>
</head>
  <body>
    <p>Esto es un párrafo dentro del body.</p>
  </body>
</html>

Código p5.js:
function setup() {
  createCanvas(400,300);
  background(255,215,0);
}

function draw() {
  fill(255,0,0);
  strokeWeight(4);
  ellipse(100,50,50,50);
  line(100,250,300,150);
}

Perpectiva Cónica: método de homología

Perpectiva Cónica: método de las prolongaciones

2017/10/22

Estilos con css y posicionamiento con p5.js y div



Código html (index.html):
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8"/>
    <title>Posicionamiento con div</title>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="libraries/p5.js"></script>
    <script src="libraries/p5.sound.js"></script>
    <script src='libraries/p5.dom.js'></script>
    <script src="code.js"></script>
</head>
  <body>
    <p>Esto está escrito directamente en archivo .html, sin estilo</p>
  </body>
</html>

Código p5.js (code.js):
var div1;
var div2;
var div3;
var canvas1;

function setup() {
  div1 = createDiv('Esto está escrito en el archivo .js, dentro de la etiqueta div1, con estilo .css');
  div1.class('uno');
  canvas1 = createCanvas(200,300);
  canvas1.class('canvas1')
  canvas1 = background(150);
  div2 = createDiv('Esto está escrito en el archivo .js, dentro de la etiqueta div2, con estilo .css');
  div2.class('uno');
  div3 = createDiv('Esto está escrito en el archivo .js, dentro de la etiqueta div3');
  div3.class('dos');
}

function draw(){
  fill(255);
  ellipse(mouseX,mouseY,20,20);
}

Código css (style.css):
body{
  background-color: gold;
  font-family: sans-serif;
  text-align: center;
  margin: 0px;
  border: 0px;
  padding: 0px;
}

p{
  margin: 0px;
  border: 0px;
  padding: 0px;
}

div{
  margin: 0px;
  border: 0px;
  padding: 0px;
}

.uno{
  background-color: orange;
  color: #FFFFFF;
  font-size: 10pt;
  margin: 0px;
  border: 0px;
  padding: 0px;
}

.canvas1{
  margin: 0px;
  margin-bottom: -4px;
  border: 0px;
  padding: 0px;
}

2017/10/19

Cinemática v0.03


Código html (index.html):
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8"/>
    <title>Botón</title>
    <script src="libraries/p5.js"></script>
    <script src="libraries/p5.dom.js"></script>
    <script src="code.js"></script>
  </head>
  <body link="black" style="text-align:center; margin:0px; background-color:white; font-family:sans-serif; font-size:12px; width:500px; margin-left:auto; margin-right:auto;">
    <h1 style="font-size:24px; text-align:center; color:grey;">CINEMÁTICA</h1>
    <p style="text-align:justify; color:grey;">Cinemática es una aplicación orientada al estudio del movimiento de un objeto en lanzamiento libre. Puedes descargarte una versión para dispositivos android en el siguiente <a href="https://play.google.com/store/apps/details?id=appinventor.ai_fotovallegrafia.Cinematica&feature=more_from_developer#?t=W251bGwsMSwyLDEwMiwiYXBwaW52ZW50b3IuYWlfZm90b3ZhbGxlZ3JhZmlhLkNpbmVtYXRpY2EiXQ.." style="text-decoration:none" target="_blank">enlace</a> o visitar la página de desarrollo en <a href="http://fotovallegrafia.blogspot.com.es/p/aplicaciones-android-cinematica.html" style="text-decoration:none" target="_blank">fotovallegrafía</a> para más información.</p>
    <p style="text-align:justify; color:grey;">El botón <b><cite>¡Fuego!</cite></b> inicia el movimiento con los parámetros prefijados en el formulario. En cualquier momento puedes cambiar los valores numéricos de posición, velocidad y aceleración inicial en <b><cite>x</cite></b> y en <b><cite>y</cite></b> para simular lanzamientos diferentes. Puedes detener el objeto en cualquier momento mediante el botón <b><cite>Pausa</cite></b>.</p>
    <table style="border:1px solid black; margin: 0 auto; width:500px">
      <tr>
        <th style="text-align:right; color:grey">Posición x inicial:</th>
        <th><input type="number" id="px0" placeholder="0" onclick="fpx0()" style="width:70px"></input></th>
        <th style="text-align:right; color:grey">Posición y inicial:</th>
        <th><input type="number" id="py0" placeholder="400" onclick="fpy0()" style="width:70px"></input></th>
      </tr>
      <tr>
        <th style="text-align:right; color:grey">Velocidad x inicial:</th>
        <th><input type="number" id="vx0" placeholder="25" onclick="fvx0()" style="width:70px"></input></th>
        <th style="text-align:right; color:grey">Velocidad y inicial:</th>
        <th><input type="number" id="vy0" placeholder="-75" onclick="fvy0()" style="width:70px"></input></th>
      </tr>
      <tr>
        <th style="text-align:right; color:grey">Aceleración x inicial:</th>
        <th><input type="number" id="ax0" placeholder="0" onclick="fax0()" style="width:70px"></input></th>
        <th style="text-align:right; color:grey">Aceleración y inicial:</th>
        <th><input type="number" id="ay0" placeholder="9,81" onclick="fay0()" style="width:70px"></input></th>
      </tr>
    </table>
    <p>
    <table style="border:1px solid black; margin: 0 auto; width:500px">
      <tr>
        <th><button onclick="ffuego()" style="width:240px">¡Fuego!</button></th>
        <th><button onclick="fpausa()" style="width:240px">Pausa</button></th>
      </tr>
    </table>
    <p>
  </body>
</html>

Código p5.js (code.js):
var lienzo;
var div;
var t = 0;
var x;
var y;
var px0 = 0;
var py0 = 500;
var vx0 = 25;
var vy0 = -95;
var ax0 = 0;
var ay0 = 9.81;
var newton;
var manzana;
var movimiento = 0;

function preload(){
  newton = loadImage("files/IsaacNewtonB05.jpg");
  manzana = loadImage("files/AppleA01.gif");
}

function setup(){
  lienzo = createCanvas(500,500);
  div = createElement('div', 'Antonio Vallecillos 2017');
  div.style("font-family", "sans-serif");
  div.style("color", "grey");
  div.style("font-size", "12px");
  div.style("padding", "5px");
}

function draw(){
  background(255,215,0);
  imageMode(CORNER);
  image(newton, 0, 0, 500, 500);
  x = 0.5 * ax0 * t * t + vx0 * t + round(px0);
  y = 0.5 * ay0 * t * t + vy0 * t + round(py0);
  vx = ax0 * t + vx0;
  vy = ay0 * t + vy0;
  noFill();
  rect(0,0,499,499);
  imageMode(CENTER);
  image(manzana, x, y-2, 25, 25);
  debug();
  if (movimiento == 1) {
    t = t + 0.1;
  }
}

function fpx0() {
  px0 = document.getElementById("px0").value;
}

function fpy0() {
  py0 = document.getElementById("py0").value;
}

function fvx0() {
  vx0 = document.getElementById("vx0").value;
}

function fvy0() {
  vy0 = document.getElementById("vy0").value;
}

function fax0() {
  ax0 = document.getElementById("ax0").value;
}

function fay0() {
  ay0 = document.getElementById("ay0").value;
}

function ffuego(){
  t = 0;
  movimiento = 1;
}

function fpausa(){
  movimiento = 0;
}

function debug(){
  fill(128, 0, 0);
  text("px0 = " + round(px0), 10, 15);
  text("py0 = " + round(py0), 10, 25);
  text("vx0 = " + round(vx0), 10, 35);
  text("vy0 = " + round(vy0), 10, 45);
  text("ax0 = " + round(ax0), 10, 55);
  text("ay0 = " + ay0, 10, 65);
  text("x = " + round(x), 80, 15);
  text("y = " + round(y), 80, 25);
  text("vx = " + round(vx), 80, 35);
  text("vy = " + round(vy), 80, 45);
  text("ax = " + round(ax0), 80, 55);
  text("ay = " + ay0, 80, 65);
}

2017/10/09

Movimiento con las flechas del teclado

Control de un sprite con las flechas del teclado (javascript)



Código html (index.html):

<!doctype html>
<html lang="es">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
  <title>Control de un sprite con las flechas del teclado</title>
</head>

<body style="text-align:center; margin:0px; background-color:white">
<!--  <h1 align="center">Control de un sprite con las flechas del teclado</h1>
--> 
  <canvas id="canvas" width="500" height="500" style="background:#999">
    Este navegador no es compatible con el canvas
  </canvas>
  <script type="application/javascript" src="juego.js"></script>
</body>

</html>

Código javascript (juego.js):
var canvas = null;
var ctx = null;
var lastPress = null;
var pause = true;

var x = 0;
var y = 0;
var dir = 0;

var KEY_ENTER = 13;
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;

window.requestAnimationFrame = (function (){
  return window.requestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    function (callback) {
      window.setTimeout(callback, 17);
    };
}());

document.addEventListener('keydown', function(evt){
  lastPress = evt.which;
}, false);

function paint(ctx) {
  // Limpiar el canvas
  ctx.fillStyle = '#000';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  
  // Dibujar un cuadrado
  ctx.fillStyle = '#0F0';
  ctx.fillRect(x, y, 10, 10);
  
  // Debug última tecla pulsada
  ctx.fillStyle = '#FFF';
  ctx.fillText('Codigo de la ultima tecla pulsada: ' + lastPress, 10, 15);
  
  ctx.fillText('Direccion: ' + dir, 10, 25);
  ctx.fillText('Pulsa las teclas de flecha para controlar la direccion', 10, canvas.height-10);
  ctx.fillText('Pulsa Enter para comenzar / pausar el juego', 10, canvas.height-20);
  
  // Escribe PAUSA
  if (pause) {
    ctx.textAlign = 'center';
    ctx.fillText('PAUSA', canvas.width/2, canvas.height/2);
    ctx.textAlign = 'left';
  }
}

function act() {
  // Cambio de dirección
  if (lastPress == KEY_UP) {
    dir = 0;
  }
  if (lastPress == KEY_RIGHT) {
    dir = 1;
  }
  if (lastPress == KEY_DOWN) {
    dir = 2;
  }
  if (lastPress == KEY_LEFT){
    dir = 3;
  }
  
  if (!pause) {
    
    // Mover el cuadrado
    if (dir == 0) {
      y = y - 10;
    }
    if (dir == 1) {
      x = x + 10;
    }
    if (dir == 2) {
      y = y + 10;
    }
    if (dir == 3) {
      x = x - 10;
    }
    
    // Si se sale de la pantalla
    if (x > canvas.width) {
      x = 0;
    }
    if (y > canvas.height) {
      y = 0;
    }
    if (x < 0) {
      x = canvas.width;
    }
    if (y < 0) {
      y = canvas.height;
    }
  }
  
  // Pausa
  if (lastPress == KEY_ENTER) {
    pause = !pause;
    lastPress = null;
  }
}

function repaint(){
  window.requestAnimationFrame(repaint);
  paint(ctx);
}

function run() {
  setTimeout(run, 20);
  act();
}

function init() {
  // Canvas y content
  canvas = document.getElementById('canvas');
  ctx = canvas.getContext('2d');
  
  //Iniciar el juego
  run();
  repaint();
}

window.addEventListener('load', init, false);

2017/10/08

Tap n'fun v0.03

 


Código html (index.html):
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title>Tap n' fun</title>
    <script language="javascript" type="text/javascript" src="libraries/p5.js"></script> 
    <script language="javascript" type="text/javascript" src="libraries/p5.sound.js"></script>
    <script language="javascript" type="text/javascript" src="Tapnfun.js"></script>
  </head>
  <body style="text-align:center; margin:0px; padding:0px; background-color:white">
  </body>
</html>

Código p5.js (Tapnfun.js):
var rojo;
var verde;
var azul;
var amarillo;
var cyan;
var magenta;
var naranja;
var gris;
var blanco;
var negro;
var mySound;

//function preload() {
//  mySound = loadSound('files/Sonido_01.mp3');
//}

function setup() {
  //createCanvas(window.innerWidth,window.innerHeight);
  createCanvas(500,500);
  rojo = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(255,0,0),0,color(0,0,0));
  verde = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(0,255,0),1,color(0,0,0));
  azul = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(0,0,255),2,color(255,255,255));
  amarillo = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(255,255,0),3,color(0,0,0));
  cyan = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(0,255,255),4,color(0,0,0));
  magenta = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(255,0,255),5,color(0,0,0));
  naranja = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(255,128,0),6,color(0,0,0)); 
  gris = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(128,128,128),7,color(0,0,0));
  blanco = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(255,255,255),8,color(0,0,0));
  negro = new Circulo(random(width/3,2*width/3),random(height/3,2*height/3),50,random(1,3),color(0,0,0),9,color(255,255,255));
}

function draw(){
  background(255,215,0);
  
  tituloApp();
  debug();
  
  rojo.dibujar();
  rojo.mover();
  verde.dibujar();
  verde.mover();
  azul.dibujar();
  azul.mover();
  amarillo.dibujar();
  amarillo.mover();
  cyan.dibujar();
  cyan.mover();
  magenta.dibujar();
  magenta.mover();
  naranja.dibujar();
  naranja.mover();
  gris.dibujar();
  gris.mover();
  blanco.dibujar();
  blanco.mover();
  negro.dibujar();
  negro.mover();
}

//function windowResized(){
//  resizeCanvas(window.innerWidth,window.innerHeight);
//}

function mousePressed(){
  rojo.tap();
  verde.tap();
  azul.tap();
  amarillo.tap();
  cyan.tap();
  magenta.tap();
  naranja.tap();
  gris.tap();
  blanco.tap();
  negro.tap();
  
//  mySound.setVolume(1);
//  mySound.play();
}

function tituloApp(){
  textSize(12);
  fill(100);
  strokeWeight(0);
  textAlign(CENTER);
  text('TAP `N FUN v0.03 [FEB-04-2017]',width/2,15);
  text('Design & coding: Antonio Vallecillos @fotovallegrafia',width/2,30);
  strokeWeight(1);
  stroke(100);
  line(0,40,width,40);
} 

function debug(){
  textSize(12);
  var p = [10,25,40,55,70,85,100,115,130,145,160,175,190,205];
  fill(100);
  strokeWeight(0);
  textAlign(LEFT);
  text('Debug:',10,height-p[8]);
  text('p[0] = ' + p[0],10,height-p[7]);
  text('Frame Rate: ' + frameRate().toFixed(0) + ' frames per second', 10,height-p[6]);
  text('width = ' + width + ' px',10,height-p[5]);
  text('height = ' + height + ' px',10,height-p[4]);  
  text('displayWidth = ' + displayWidth + ' px',10,height-p[3]);
  text('displayHeight = ' + displayHeight + ' px',10,height-p[2]);
  text('window.innerWidth = ' + window.innerWidth + ' px',10,height-p[1]);
  text('window.innerHeight = ' + window.innerHeight + ' px',10,height-p[0]);
}

function Circulo(extx,exty,extdiametro,extv,extcolor,extid,extidcolor) {
  this.x = extx;
  this.y = exty;
  this.diametro = extdiametro;
  this.velocidad = extv;
  this.angulo = random(0,2*PI);
  this.ccolor = extcolor;
  this.sw = 5;
  this.visible = 1;
  this.borde = 0;
  this.id = extid;
  this.idcolor = extidcolor;
  
  this.dibujar = function(ccolor) {
    strokeWeight(this.sw);
    stroke(this.borde);
    fill(this.ccolor);
    ellipse(this.x,this.y,this.diametro,this.diametro);
    
    fill(this.idcolor);
    stroke(this.idcolor);
    textAlign(CENTER);
    strokeWeight(2);
    textSize(40);
    text(this.id,this.x,this.y+14);
  }

  this.mover = function() {
    if(this.x >= width-this.sw-this.diametro/2){
      this.angulo = this.angulo + random(PI-PI/4, PI+PI/4);
      this.x = this.x-1;
    }else if(this.x <= this.sw+this.diametro/2){
      this.angulo = this.angulo + random(PI-PI/4, PI+PI/4);
      this.x = this.x+1;
    }else if(this.y >= height-this.sw-this.diametro/2){
      this.angulo = this.angulo + random(PI-PI/4, PI+PI/4);
      this.y = this.y-1;
    }else if(this.y <= this.sw+this.diametro/2){
      this.angulo = this.angulo + random(PI-PI/4, PI+PI/4);
      this.y = this.y+1;    
    }else{
      this.angulo = this.angulo + random(-PI/16,PI/16);
      this.x = this.x + cos(this.angulo)*this.velocidad;
      this.y = this.y + sin(this.angulo)*this.velocidad;
    }
  }
  
  this.tap = function(){
    if(this.x-this.diametro/2 <= mouseX && mouseX <= this.x+this.diametro/2 && this.y-this.diametro/2 <= mouseY && mouseY <= this.y+this.diametro/2){
      this.ccolor = color(255,200,0,50);
      this.borde = color(0,50);
      this.idcolor = color(0,50);
      this.velocidad = 0;
    }
  }

}